Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // For WinDDK ATL compatibility, these ATL headers must come first. | 5 // For WinDDK ATL compatibility, these ATL headers must come first. |
| 6 #include "build/build_config.h" | 6 #include "build/build_config.h" |
| 7 | 7 |
| 8 #if defined(OS_WIN) | 8 #if defined(OS_WIN) |
| 9 #include <atlbase.h> // NOLINT | 9 #include <atlbase.h> // NOLINT |
| 10 #include <atlwin.h> // NOLINT | 10 #include <atlwin.h> // NOLINT |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 #include "ui/gfx/range/range.h" | 41 #include "ui/gfx/range/range.h" |
| 42 #include "ui/gfx/render_text.h" | 42 #include "ui/gfx/render_text.h" |
| 43 #include "ui/gfx/text_utils.h" | 43 #include "ui/gfx/text_utils.h" |
| 44 #include "ui/gfx/vector_icons_public.h" | 44 #include "ui/gfx/vector_icons_public.h" |
| 45 #include "ui/native_theme/native_theme.h" | 45 #include "ui/native_theme/native_theme.h" |
| 46 | 46 |
| 47 using ui::NativeTheme; | 47 using ui::NativeTheme; |
| 48 | 48 |
| 49 namespace { | 49 namespace { |
| 50 | 50 |
| 51 // Don't trust the number of lines from AiS. Cap it. | |
| 52 constexpr int kMAX_DISPLAY_LINES = 3; | |
|
Peter Kasting
2016/06/01 16:15:29
Nit: Declare this in the lone scope where it's use
Kevin Bailey
2016/06/01 17:33:59
Done.
| |
| 53 | |
| 51 // A mapping from OmniboxResultView's ResultViewState/ColorKind types to | 54 // A mapping from OmniboxResultView's ResultViewState/ColorKind types to |
| 52 // NativeTheme colors. | 55 // NativeTheme colors. |
| 53 struct TranslationTable { | 56 struct TranslationTable { |
| 54 ui::NativeTheme::ColorId id; | 57 ui::NativeTheme::ColorId id; |
| 55 OmniboxResultView::ResultViewState state; | 58 OmniboxResultView::ResultViewState state; |
| 56 OmniboxResultView::ColorKind kind; | 59 OmniboxResultView::ColorKind kind; |
| 57 } static const kTranslationTable[] = { | 60 } static const kTranslationTable[] = { |
| 58 { NativeTheme::kColorId_ResultsTableNormalBackground, | 61 { NativeTheme::kColorId_ResultsTableNormalBackground, |
| 59 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND }, | 62 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND }, |
| 60 { NativeTheme::kColorId_ResultsTableHoveredBackground, | 63 { NativeTheme::kColorId_ResultsTableHoveredBackground, |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 // updating the text in the omnibox but this alert and GetAccessibleState | 274 // updating the text in the omnibox but this alert and GetAccessibleState |
| 272 // below make the answer contents accessible. | 275 // below make the answer contents accessible. |
| 273 if (match_.answer) | 276 if (match_.answer) |
| 274 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true); | 277 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true); |
| 275 } | 278 } |
| 276 | 279 |
| 277 gfx::Size OmniboxResultView::GetPreferredSize() const { | 280 gfx::Size OmniboxResultView::GetPreferredSize() const { |
| 278 if (!match_.answer) | 281 if (!match_.answer) |
| 279 return gfx::Size(0, GetContentLineHeight()); | 282 return gfx::Size(0, GetContentLineHeight()); |
| 280 // An answer implies a match and a description in a large font. | 283 // An answer implies a match and a description in a large font. |
| 281 return gfx::Size(0, GetContentLineHeight() + GetAnswerLineHeight()); | 284 const auto& text_fields = match_.answer->second_line().text_fields(); |
| 285 if (!text_fields.empty() && text_fields[0].has_num_lines()) { | |
|
Peter Kasting
2016/06/01 16:15:29
Nit: You use [0] here and .front() below. Pick on
Kevin Bailey
2016/06/01 17:34:00
Done.
| |
| 286 if (!description_rendertext_) | |
|
Peter Kasting
2016/06/01 16:15:29
Nit: {}
Kevin Bailey
2016/06/01 17:34:00
Done.
| |
| 287 description_rendertext_ = | |
| 288 CreateAnswerLine(match_.answer->second_line(), font_list_); | |
| 289 description_rendertext_->SetDisplayRect( | |
| 290 gfx::Rect(text_bounds().width(), 0)); | |
|
Peter Kasting
2016/06/01 16:15:29
Nit: Prefer text_bounds_
Kevin Bailey
2016/06/01 17:34:00
This one surprises me, particularly since 'text_bo
| |
| 291 description_rendertext_->GetStringSize(); | |
| 292 return gfx::Size( | |
| 293 0, GetContentLineHeight() + | |
| 294 GetAnswerLineHeight() * description_rendertext_->GetNumLines()); | |
| 295 } else { | |
| 296 return gfx::Size(0, GetContentLineHeight() + GetAnswerLineHeight()); | |
|
Peter Kasting
2016/06/01 16:15:29
Nit: Reverse the conditional above and do this as
Kevin Bailey
2016/06/01 17:34:00
Done.
| |
| 297 } | |
| 282 } | 298 } |
| 283 | 299 |
| 284 void OmniboxResultView::GetAccessibleState(ui::AXViewState* state) { | 300 void OmniboxResultView::GetAccessibleState(ui::AXViewState* state) { |
| 285 state->name = match_.answer | 301 state->name = match_.answer |
| 286 ? l10n_util::GetStringFUTF16( | 302 ? l10n_util::GetStringFUTF16( |
| 287 IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents, | 303 IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents, |
| 288 match_.answer->second_line().AccessibleText()) | 304 match_.answer->second_line().AccessibleText()) |
| 289 : match_.contents; | 305 : match_.contents; |
| 290 } | 306 } |
| 291 | 307 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR); | 439 gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR); |
| 424 prefix_render_text->SetHorizontalAlignment( | 440 prefix_render_text->SetHorizontalAlignment( |
| 425 is_match_contents_rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT); | 441 is_match_contents_rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT); |
| 426 prefix_render_text->SetDisplayRect( | 442 prefix_render_text->SetDisplayRect( |
| 427 gfx::Rect(mirroring_context_->mirrored_left_coord( | 443 gfx::Rect(mirroring_context_->mirrored_left_coord( |
| 428 prefix_x, prefix_x + prefix_width), | 444 prefix_x, prefix_x + prefix_width), |
| 429 y, prefix_width, GetContentLineHeight())); | 445 y, prefix_width, GetContentLineHeight())); |
| 430 prefix_render_text->Draw(canvas); | 446 prefix_render_text->Draw(canvas); |
| 431 } | 447 } |
| 432 | 448 |
| 433 // Set the display rect to trigger eliding. | 449 // Set the display rect to trigger elision. |
| 434 const int height = (render_text_type == DESCRIPTION && match.answer) ? | 450 int final_width = right_x - x; |
|
Peter Kasting
2016/06/01 16:15:29
Nit: const?
Kevin Bailey
2016/06/01 17:34:00
Done.
| |
| 435 GetAnswerLineHeight() : GetContentLineHeight(); | 451 int height = GetContentLineHeight(); |
| 452 if (render_text_type == DESCRIPTION && match.answer) { | |
| 453 render_text->SetDisplayRect(gfx::Rect(gfx::Size(final_width, 0))); | |
| 454 render_text->GetStringSize(); | |
| 455 height = GetAnswerLineHeight() * render_text->GetNumLines(); | |
| 456 } | |
| 436 render_text->SetDisplayRect( | 457 render_text->SetDisplayRect( |
| 437 gfx::Rect(mirroring_context_->mirrored_left_coord(x, right_x), y, | 458 gfx::Rect(mirroring_context_->mirrored_left_coord(x, right_x), y, |
| 438 right_x - x, height)); | 459 final_width, height)); |
| 439 render_text->Draw(canvas); | 460 render_text->Draw(canvas); |
| 440 return right_x; | 461 return right_x; |
| 441 } | 462 } |
| 442 | 463 |
| 443 std::unique_ptr<gfx::RenderText> OmniboxResultView::CreateRenderText( | 464 std::unique_ptr<gfx::RenderText> OmniboxResultView::CreateRenderText( |
| 444 const base::string16& text) const { | 465 const base::string16& text) const { |
| 445 std::unique_ptr<gfx::RenderText> render_text( | 466 std::unique_ptr<gfx::RenderText> render_text( |
| 446 gfx::RenderText::CreateInstance()); | 467 gfx::RenderText::CreateInstance()); |
| 447 render_text->SetDisplayRect(gfx::Rect(gfx::Size(INT_MAX, 0))); | 468 render_text->SetDisplayRect(gfx::Rect(gfx::Size(INT_MAX, 0))); |
| 448 render_text->SetCursorEnabled(false); | 469 render_text->SetCursorEnabled(false); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 canvas->DrawImageInt(GetIcon(), GetMirroredXForRect(icon_bounds_), | 695 canvas->DrawImageInt(GetIcon(), GetMirroredXForRect(icon_bounds_), |
| 675 icon_bounds_.y()); | 696 icon_bounds_.y()); |
| 676 int x = GetMirroredXForRect(text_bounds_); | 697 int x = GetMirroredXForRect(text_bounds_); |
| 677 mirroring_context_->Initialize(x, text_bounds_.width()); | 698 mirroring_context_->Initialize(x, text_bounds_.width()); |
| 678 InitContentsRenderTextIfNecessary(); | 699 InitContentsRenderTextIfNecessary(); |
| 679 | 700 |
| 680 if (!description_rendertext_) { | 701 if (!description_rendertext_) { |
| 681 if (match_.answer) { | 702 if (match_.answer) { |
| 682 contents_rendertext_ = | 703 contents_rendertext_ = |
| 683 CreateAnswerLine(match_.answer->first_line(), font_list_); | 704 CreateAnswerLine(match_.answer->first_line(), font_list_); |
| 684 description_rendertext_ = CreateAnswerLine( | 705 description_rendertext_ = |
| 685 match_.answer->second_line(), | 706 CreateAnswerLine(match_.answer->second_line(), font_list_); |
| 686 ui::ResourceBundle::GetSharedInstance().GetFontList( | |
| 687 ui::ResourceBundle::LargeFont)); | |
| 688 } else if (!match_.description.empty()) { | 707 } else if (!match_.description.empty()) { |
| 689 description_rendertext_ = CreateClassifiedRenderText( | 708 description_rendertext_ = CreateClassifiedRenderText( |
| 690 match_.description, match_.description_class, true); | 709 match_.description, match_.description_class, true); |
| 691 } | 710 } |
| 692 } | 711 } |
| 693 PaintMatch(match_, contents_rendertext_.get(), | 712 PaintMatch(match_, contents_rendertext_.get(), |
| 694 description_rendertext_.get(), canvas, x); | 713 description_rendertext_.get(), canvas, x); |
| 695 } | 714 } |
| 696 | 715 |
| 697 AutocompleteMatch* keyword_match = match_.associated_keyword.get(); | 716 AutocompleteMatch* keyword_match = match_.associated_keyword.get(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 730 } | 749 } |
| 731 | 750 |
| 732 int OmniboxResultView::GetContentLineHeight() const { | 751 int OmniboxResultView::GetContentLineHeight() const { |
| 733 return std::max( | 752 return std::max( |
| 734 default_icon_size_ + GetLayoutInsets(OMNIBOX_DROPDOWN_ICON).height(), | 753 default_icon_size_ + GetLayoutInsets(OMNIBOX_DROPDOWN_ICON).height(), |
| 735 GetTextHeight() + GetLayoutInsets(OMNIBOX_DROPDOWN_TEXT).height()); | 754 GetTextHeight() + GetLayoutInsets(OMNIBOX_DROPDOWN_TEXT).height()); |
| 736 } | 755 } |
| 737 | 756 |
| 738 std::unique_ptr<gfx::RenderText> OmniboxResultView::CreateAnswerLine( | 757 std::unique_ptr<gfx::RenderText> OmniboxResultView::CreateAnswerLine( |
| 739 const SuggestionAnswer::ImageLine& line, | 758 const SuggestionAnswer::ImageLine& line, |
| 740 gfx::FontList font_list) { | 759 gfx::FontList font_list) const { |
| 741 std::unique_ptr<gfx::RenderText> destination = | 760 std::unique_ptr<gfx::RenderText> destination = |
| 742 CreateRenderText(base::string16()); | 761 CreateRenderText(base::string16()); |
| 743 destination->SetFontList(font_list); | 762 destination->SetFontList(font_list); |
| 744 | 763 |
| 745 for (const SuggestionAnswer::TextField& text_field : line.text_fields()) | 764 for (const SuggestionAnswer::TextField& text_field : line.text_fields()) |
|
Kevin Bailey
2016/06/01 14:56:36
Am I the only bothered by the same variable being
Peter Kasting
2016/06/01 16:15:29
Well, it's really 3 variables due to scoping.
If
Kevin Bailey
2016/06/01 17:33:59
I took care of one, but the others didn't seem lik
Justin Donnelly
2016/06/01 17:38:17
To me a variable named after its type is just sayi
| |
| 746 AppendAnswerText(destination.get(), text_field.text(), text_field.type()); | 765 AppendAnswerText(destination.get(), text_field.text(), text_field.type()); |
| 766 if (!line.text_fields().empty()) { | |
| 767 const SuggestionAnswer::TextField& text_field = line.text_fields().front(); | |
| 768 if (text_field.has_num_lines() && text_field.num_lines() > 1 && | |
| 769 destination->MultilineSupported()) { | |
| 770 destination->SetMultiline(true); | |
| 771 destination->SetMaxLines( | |
| 772 std::min(kMAX_DISPLAY_LINES, text_field.num_lines())); | |
| 773 } | |
| 774 } | |
| 747 const base::char16 space(' '); | 775 const base::char16 space(' '); |
| 748 const auto* text_field = line.additional_text(); | 776 const auto* text_field = line.additional_text(); |
| 749 if (text_field) { | 777 if (text_field) { |
| 750 AppendAnswerText(destination.get(), space + text_field->text(), | 778 AppendAnswerText(destination.get(), space + text_field->text(), |
| 751 text_field->type()); | 779 text_field->type()); |
| 752 } | 780 } |
| 753 text_field = line.status_text(); | 781 text_field = line.status_text(); |
| 754 if (text_field) { | 782 if (text_field) { |
| 755 AppendAnswerText(destination.get(), space + text_field->text(), | 783 AppendAnswerText(destination.get(), space + text_field->text(), |
| 756 text_field->type()); | 784 text_field->type()); |
| 757 } | 785 } |
| 758 return destination; | 786 return destination; |
| 759 } | 787 } |
| 760 | 788 |
| 761 void OmniboxResultView::AppendAnswerText(gfx::RenderText* destination, | 789 void OmniboxResultView::AppendAnswerText(gfx::RenderText* destination, |
| 762 const base::string16& text, | 790 const base::string16& text, |
| 763 int text_type) { | 791 int text_type) const { |
| 764 // TODO(dschuyler): make this better. Right now this only supports unnested | 792 // TODO(dschuyler): make this better. Right now this only supports unnested |
| 765 // bold tags. In the future we'll need to flag unexpected tags while adding | 793 // bold tags. In the future we'll need to flag unexpected tags while adding |
| 766 // support for b, i, u, sub, and sup. We'll also need to support HTML | 794 // support for b, i, u, sub, and sup. We'll also need to support HTML |
| 767 // entities (< for '<', etc.). | 795 // entities (< for '<', etc.). |
| 768 const base::string16 begin_tag = base::ASCIIToUTF16("<b>"); | 796 const base::string16 begin_tag = base::ASCIIToUTF16("<b>"); |
| 769 const base::string16 end_tag = base::ASCIIToUTF16("</b>"); | 797 const base::string16 end_tag = base::ASCIIToUTF16("</b>"); |
| 770 size_t begin = 0; | 798 size_t begin = 0; |
| 771 while (true) { | 799 while (true) { |
| 772 size_t end = text.find(begin_tag, begin); | 800 size_t end = text.find(begin_tag, begin); |
| 773 if (end == base::string16::npos) { | 801 if (end == base::string16::npos) { |
| 774 AppendAnswerTextHelper(destination, text.substr(begin), text_type, false); | 802 AppendAnswerTextHelper(destination, text.substr(begin), text_type, false); |
| 775 break; | 803 break; |
| 776 } | 804 } |
| 777 AppendAnswerTextHelper(destination, text.substr(begin, end - begin), | 805 AppendAnswerTextHelper(destination, text.substr(begin, end - begin), |
| 778 text_type, false); | 806 text_type, false); |
| 779 begin = end + begin_tag.length(); | 807 begin = end + begin_tag.length(); |
| 780 end = text.find(end_tag, begin); | 808 end = text.find(end_tag, begin); |
| 781 if (end == base::string16::npos) | 809 if (end == base::string16::npos) |
| 782 break; | 810 break; |
| 783 AppendAnswerTextHelper(destination, text.substr(begin, end - begin), | 811 AppendAnswerTextHelper(destination, text.substr(begin, end - begin), |
| 784 text_type, true); | 812 text_type, true); |
| 785 begin = end + end_tag.length(); | 813 begin = end + end_tag.length(); |
| 786 } | 814 } |
| 787 } | 815 } |
| 788 | 816 |
| 789 void OmniboxResultView::AppendAnswerTextHelper(gfx::RenderText* destination, | 817 void OmniboxResultView::AppendAnswerTextHelper(gfx::RenderText* destination, |
| 790 const base::string16& text, | 818 const base::string16& text, |
| 791 int text_type, | 819 int text_type, |
| 792 bool is_bold) { | 820 bool is_bold) const { |
| 793 if (text.empty()) | 821 if (text.empty()) |
| 794 return; | 822 return; |
| 795 int offset = destination->text().length(); | 823 int offset = destination->text().length(); |
| 796 gfx::Range range(offset, offset + text.length()); | 824 gfx::Range range(offset, offset + text.length()); |
| 797 destination->AppendText(text); | 825 destination->AppendText(text); |
| 798 const TextStyle& text_style = GetTextStyle(text_type); | 826 const TextStyle& text_style = GetTextStyle(text_type); |
| 799 // TODO(dschuyler): follow up on the problem of different font sizes within | 827 // TODO(dschuyler): follow up on the problem of different font sizes within |
| 800 // one RenderText. Maybe with destination->SetFontList(...). | 828 // one RenderText. Maybe with destination->SetFontList(...). |
| 801 destination->ApplyStyle(gfx::BOLD, is_bold, range); | 829 destination->ApplyStyle(gfx::BOLD, is_bold, range); |
| 802 destination->ApplyColor( | 830 destination->ApplyColor( |
| 803 GetNativeTheme()->GetSystemColor(text_style.colors[GetState()]), range); | 831 GetNativeTheme()->GetSystemColor(text_style.colors[GetState()]), range); |
| 804 destination->ApplyBaselineStyle(text_style.baseline, range); | 832 destination->ApplyBaselineStyle(text_style.baseline, range); |
| 805 } | 833 } |
| 806 | 834 |
| 807 int OmniboxResultView::StartMargin() const { | 835 int OmniboxResultView::StartMargin() const { |
| 808 return ui::MaterialDesignController::IsModeMaterial() ? | 836 return ui::MaterialDesignController::IsModeMaterial() ? |
| 809 model_->start_margin() : 0; | 837 model_->start_margin() : 0; |
| 810 } | 838 } |
| 811 | 839 |
| 812 int OmniboxResultView::EndMargin() const { | 840 int OmniboxResultView::EndMargin() const { |
| 813 return ui::MaterialDesignController::IsModeMaterial() ? | 841 return ui::MaterialDesignController::IsModeMaterial() ? |
| 814 model_->end_margin() : 0; | 842 model_->end_margin() : 0; |
| 815 } | 843 } |
| OLD | NEW |