| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include "ui/gfx/paint_vector_icon.h" | 43 #include "ui/gfx/paint_vector_icon.h" |
| 44 #include "ui/gfx/range/range.h" | 44 #include "ui/gfx/range/range.h" |
| 45 #include "ui/gfx/render_text.h" | 45 #include "ui/gfx/render_text.h" |
| 46 #include "ui/gfx/text_utils.h" | 46 #include "ui/gfx/text_utils.h" |
| 47 #include "ui/native_theme/native_theme.h" | 47 #include "ui/native_theme/native_theme.h" |
| 48 | 48 |
| 49 using ui::NativeTheme; | 49 using ui::NativeTheme; |
| 50 | 50 |
| 51 namespace { | 51 namespace { |
| 52 | 52 |
| 53 // The padding that should be placed between content and description in a | 53 // The vertical margin that should be used above and below each suggestion. |
| 54 // vertical layout. | 54 static const int kVerticalMargin = 1; |
| 55 static const int kVerticalPadding = 3; | 55 |
| 56 // The vertical padding to provide each RenderText in addition to the height of |
| 57 // the font. Where possible, RenderText uses this additional space to vertically |
| 58 // center the cap height of the font instead of centering the entire font. |
| 59 static const int kVerticalPadding = 4; |
| 56 | 60 |
| 57 // A mapping from OmniboxResultView's ResultViewState/ColorKind types to | 61 // A mapping from OmniboxResultView's ResultViewState/ColorKind types to |
| 58 // NativeTheme colors. | 62 // NativeTheme colors. |
| 59 struct TranslationTable { | 63 struct TranslationTable { |
| 60 ui::NativeTheme::ColorId id; | 64 ui::NativeTheme::ColorId id; |
| 61 OmniboxResultView::ResultViewState state; | 65 OmniboxResultView::ResultViewState state; |
| 62 OmniboxResultView::ColorKind kind; | 66 OmniboxResultView::ColorKind kind; |
| 63 } static const kTranslationTable[] = { | 67 } static const kTranslationTable[] = { |
| 64 { NativeTheme::kColorId_ResultsTableNormalBackground, | 68 { NativeTheme::kColorId_ResultsTableNormalBackground, |
| 65 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND }, | 69 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND }, |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 // selected. The non-answer text is already accessible as a consequence of | 300 // selected. The non-answer text is already accessible as a consequence of |
| 297 // updating the text in the omnibox but this alert and GetAccessibleNodeData | 301 // updating the text in the omnibox but this alert and GetAccessibleNodeData |
| 298 // below make the answer contents accessible. | 302 // below make the answer contents accessible. |
| 299 if (match_.answer) | 303 if (match_.answer) |
| 300 NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); | 304 NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); |
| 301 } | 305 } |
| 302 | 306 |
| 303 gfx::Size OmniboxResultView::CalculatePreferredSize() const { | 307 gfx::Size OmniboxResultView::CalculatePreferredSize() const { |
| 304 int height = GetTextHeight() + (2 * GetVerticalMargin()); | 308 int height = GetTextHeight() + (2 * GetVerticalMargin()); |
| 305 if (match_.answer) | 309 if (match_.answer) |
| 306 height += GetAnswerHeight() + kVerticalPadding; | 310 height += GetAnswerHeight(); |
| 307 else if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) | 311 else if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) |
| 308 height += GetTextHeight() + kVerticalPadding; | 312 height += GetTextHeight(); |
| 309 return gfx::Size(0, height); | 313 return gfx::Size(0, height); |
| 310 } | 314 } |
| 311 | 315 |
| 312 void OmniboxResultView::GetAccessibleNodeData(ui::AXNodeData* node_data) { | 316 void OmniboxResultView::GetAccessibleNodeData(ui::AXNodeData* node_data) { |
| 313 node_data->SetName(match_.answer | 317 node_data->SetName(match_.answer |
| 314 ? l10n_util::GetStringFUTF16( | 318 ? l10n_util::GetStringFUTF16( |
| 315 IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents, | 319 IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents, |
| 316 match_.answer->second_line().AccessibleText()) | 320 match_.answer->second_line().AccessibleText()) |
| 317 : match_.contents); | 321 : match_.contents); |
| 318 } | 322 } |
| 319 | 323 |
| 320 void OmniboxResultView::OnNativeThemeChanged(const ui::NativeTheme* theme) { | 324 void OmniboxResultView::OnNativeThemeChanged(const ui::NativeTheme* theme) { |
| 321 Invalidate(); | 325 Invalidate(); |
| 322 SchedulePaint(); | 326 SchedulePaint(); |
| 323 } | 327 } |
| 324 | 328 |
| 325 //////////////////////////////////////////////////////////////////////////////// | 329 //////////////////////////////////////////////////////////////////////////////// |
| 326 // OmniboxResultView, protected: | 330 // OmniboxResultView, protected: |
| 327 | 331 |
| 328 OmniboxResultView::ResultViewState OmniboxResultView::GetState() const { | 332 OmniboxResultView::ResultViewState OmniboxResultView::GetState() const { |
| 329 if (model_->IsSelectedIndex(model_index_)) | 333 if (model_->IsSelectedIndex(model_index_)) |
| 330 return SELECTED; | 334 return SELECTED; |
| 331 return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; | 335 return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; |
| 332 } | 336 } |
| 333 | 337 |
| 334 int OmniboxResultView::GetTextHeight() const { | 338 int OmniboxResultView::GetTextHeight() const { |
| 335 return font_height_; | 339 return font_height_ + kVerticalPadding; |
| 336 } | 340 } |
| 337 | 341 |
| 338 void OmniboxResultView::PaintMatch(const AutocompleteMatch& match, | 342 void OmniboxResultView::PaintMatch(const AutocompleteMatch& match, |
| 339 gfx::RenderText* contents, | 343 gfx::RenderText* contents, |
| 340 gfx::RenderText* description, | 344 gfx::RenderText* description, |
| 341 gfx::Canvas* canvas, | 345 gfx::Canvas* canvas, |
| 342 int x) const { | 346 int x) const { |
| 343 int y = text_bounds_.y() + GetVerticalMargin(); | 347 int y = text_bounds_.y() + GetVerticalMargin(); |
| 344 | 348 |
| 345 if (!separator_rendertext_) { | 349 if (!separator_rendertext_) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 360 OmniboxPopupModel::ComputeMatchMaxWidths( | 364 OmniboxPopupModel::ComputeMatchMaxWidths( |
| 361 contents->GetContentWidth(), separator_width_, | 365 contents->GetContentWidth(), separator_width_, |
| 362 description ? description->GetContentWidth() : 0, | 366 description ? description->GetContentWidth() : 0, |
| 363 mirroring_context_->remaining_width(x), description_on_separate_line, | 367 mirroring_context_->remaining_width(x), description_on_separate_line, |
| 364 !AutocompleteMatch::IsSearchType(match.type), &contents_max_width, | 368 !AutocompleteMatch::IsSearchType(match.type), &contents_max_width, |
| 365 &description_max_width); | 369 &description_max_width); |
| 366 | 370 |
| 367 // Answers in Suggest results. | 371 // Answers in Suggest results. |
| 368 if (match.answer && description_max_width != 0) { | 372 if (match.answer && description_max_width != 0) { |
| 369 DrawRenderText(match, contents, CONTENTS, canvas, x, y, contents_max_width); | 373 DrawRenderText(match, contents, CONTENTS, canvas, x, y, contents_max_width); |
| 370 y += GetTextHeight() + kVerticalPadding; | 374 y += GetTextHeight(); |
| 371 if (!answer_image_.isNull()) { | 375 if (!answer_image_.isNull()) { |
| 372 int answer_icon_size = GetAnswerHeight(); | 376 // GetAnswerHeight includes some padding. Using that results in an image |
| 377 // that's too large so we use the font height here instead. |
| 378 int answer_icon_size = GetAnswerFont().GetHeight(); |
| 373 canvas->DrawImageInt(answer_image_, 0, 0, answer_image_.width(), | 379 canvas->DrawImageInt(answer_image_, 0, 0, answer_image_.width(), |
| 374 answer_image_.height(), GetMirroredXInView(x), y, | 380 answer_image_.height(), GetMirroredXInView(x), |
| 375 answer_icon_size, answer_icon_size, true); | 381 y + (kVerticalPadding / 2), answer_icon_size, |
| 382 answer_icon_size, true); |
| 376 // TODO(dschuyler): Perhaps this should be based on the font size | 383 // TODO(dschuyler): Perhaps this should be based on the font size |
| 377 // instead of hardcoded to 2 dp (e.g. by adding a space in an | 384 // instead of hardcoded to 2 dp (e.g. by adding a space in an |
| 378 // appropriate font to the beginning of the description, then reducing | 385 // appropriate font to the beginning of the description, then reducing |
| 379 // the additional padding here to zero). | 386 // the additional padding here to zero). |
| 380 const int kAnswerIconToTextPadding = 2; | 387 const int kAnswerIconToTextPadding = 2; |
| 381 x += answer_icon_size + kAnswerIconToTextPadding; | 388 x += answer_icon_size + kAnswerIconToTextPadding; |
| 382 } | 389 } |
| 383 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, | 390 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, |
| 384 description_max_width); | 391 description_max_width); |
| 385 return; | 392 return; |
| 386 } | 393 } |
| 387 | 394 |
| 388 // Regular results. | 395 // Regular results. |
| 389 if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) { | 396 if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) { |
| 390 // For no description, shift down halfways to draw contents in middle. | 397 // For no description, shift down halfways to draw contents in middle. |
| 391 if (description_max_width == 0) | 398 if (description_max_width == 0) |
| 392 y += (GetTextHeight() + kVerticalPadding) / 2; | 399 y += GetTextHeight() / 2; |
| 393 | 400 |
| 394 DrawRenderText(match, contents, CONTENTS, canvas, x, y, contents_max_width); | 401 DrawRenderText(match, contents, CONTENTS, canvas, x, y, contents_max_width); |
| 395 | 402 |
| 396 if (description_max_width != 0) { | 403 if (description_max_width != 0) { |
| 397 y += GetTextHeight() + kVerticalPadding; | 404 y += GetTextHeight(); |
| 398 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, | 405 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, |
| 399 description_max_width); | 406 description_max_width); |
| 400 } | 407 } |
| 401 } else { | 408 } else { |
| 402 x = DrawRenderText(match, contents, CONTENTS, canvas, x, y, | 409 x = DrawRenderText(match, contents, CONTENTS, canvas, x, y, |
| 403 contents_max_width); | 410 contents_max_width); |
| 404 if (description_max_width != 0) { | 411 if (description_max_width != 0) { |
| 405 x = DrawRenderText(match, separator_rendertext_.get(), SEPARATOR, canvas, | 412 x = DrawRenderText(match, separator_rendertext_.get(), SEPARATOR, canvas, |
| 406 x, y, separator_width_); | 413 x, y, separator_width_); |
| 407 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, | 414 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 // the omnibox border outline shape exactly in OnPaint(). We have to inset | 647 // the omnibox border outline shape exactly in OnPaint(). We have to inset |
| 641 // here to keep the icons lined up. | 648 // here to keep the icons lined up. |
| 642 const int start_x = BackgroundWith1PxBorder::kLocationBarBorderThicknessDip + | 649 const int start_x = BackgroundWith1PxBorder::kLocationBarBorderThicknessDip + |
| 643 horizontal_padding; | 650 horizontal_padding; |
| 644 const int end_x = width() - start_x; | 651 const int end_x = width() - start_x; |
| 645 | 652 |
| 646 const gfx::ImageSkia icon = GetIcon(); | 653 const gfx::ImageSkia icon = GetIcon(); |
| 647 | 654 |
| 648 int row_height = GetTextHeight(); | 655 int row_height = GetTextHeight(); |
| 649 if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) | 656 if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) |
| 650 row_height += kVerticalPadding + GetTextHeight(); | 657 row_height += match_.answer ? GetAnswerHeight() : GetTextHeight(); |
| 651 | 658 |
| 652 const int icon_y = GetVerticalMargin() + (row_height - icon.height()) / 2; | 659 const int icon_y = GetVerticalMargin() + (row_height - icon.height()) / 2; |
| 653 icon_bounds_.SetRect(start_x, icon_y, icon.width(), icon.height()); | 660 icon_bounds_.SetRect(start_x, icon_y, icon.width(), icon.height()); |
| 654 | 661 |
| 655 const int text_x = start_x + LocationBarView::kIconWidth + horizontal_padding; | 662 const int text_x = start_x + LocationBarView::kIconWidth + horizontal_padding; |
| 656 int text_width = end_x - text_x; | 663 int text_width = end_x - text_x; |
| 657 | 664 |
| 658 if (match_.associated_keyword.get()) { | 665 if (match_.associated_keyword.get()) { |
| 659 const int max_kw_x = end_x - keyword_icon_->width(); | 666 const int max_kw_x = end_x - keyword_icon_->width(); |
| 660 const int kw_x = animation_->CurrentValueBetween(max_kw_x, start_x); | 667 const int kw_x = animation_->CurrentValueBetween(max_kw_x, start_x); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 ? match_.answer->second_line().text_fields()[0].type() | 747 ? match_.answer->second_line().text_fields()[0].type() |
| 741 : SuggestionAnswer::SUGGESTION; | 748 : SuggestionAnswer::SUGGESTION; |
| 742 return ui::ResourceBundle::GetSharedInstance().GetFontList( | 749 return ui::ResourceBundle::GetSharedInstance().GetFontList( |
| 743 GetTextStyle(text_type).font); | 750 GetTextStyle(text_type).font); |
| 744 } | 751 } |
| 745 | 752 |
| 746 int OmniboxResultView::GetAnswerHeight() const { | 753 int OmniboxResultView::GetAnswerHeight() const { |
| 747 // If the answer specifies a maximum of 1 line we can simply return the answer | 754 // If the answer specifies a maximum of 1 line we can simply return the answer |
| 748 // font height. | 755 // font height. |
| 749 if (match_.answer->second_line().num_text_lines() == 1) | 756 if (match_.answer->second_line().num_text_lines() == 1) |
| 750 return GetAnswerFont().GetHeight(); | 757 return GetAnswerFont().GetHeight() + kVerticalPadding; |
| 751 | 758 |
| 752 // Multi-line answers require layout in order to determine the number of lines | 759 // Multi-line answers require layout in order to determine the number of lines |
| 753 // the RenderText will use. | 760 // the RenderText will use. |
| 754 if (!description_rendertext_) { | 761 if (!description_rendertext_) { |
| 755 description_rendertext_ = | 762 description_rendertext_ = |
| 756 CreateAnswerText(match_.answer->second_line(), GetAnswerFont()); | 763 CreateAnswerText(match_.answer->second_line(), GetAnswerFont()); |
| 757 } | 764 } |
| 758 description_rendertext_->SetDisplayRect(gfx::Rect(text_bounds_.width(), 0)); | 765 description_rendertext_->SetDisplayRect(gfx::Rect(text_bounds_.width(), 0)); |
| 759 description_rendertext_->GetStringSize(); | 766 description_rendertext_->GetStringSize(); |
| 760 return GetAnswerFont().GetHeight() * description_rendertext_->GetNumLines(); | 767 return (GetAnswerFont().GetHeight() * |
| 768 description_rendertext_->GetNumLines()) + |
| 769 kVerticalPadding; |
| 761 } | 770 } |
| 762 | 771 |
| 763 int OmniboxResultView::GetVerticalMargin() const { | 772 int OmniboxResultView::GetVerticalMargin() const { |
| 764 // Regardless of the text size, we ensure a minimum size for the content line | 773 // Regardless of the text size, we ensure a minimum size for the content line |
| 765 // here. This minimum is larger for hybrid mouse/touch devices to ensure an | 774 // here. This minimum is larger for hybrid mouse/touch devices to ensure an |
| 766 // adequately sized touch target. | 775 // adequately sized touch target. |
| 767 using Md = ui::MaterialDesignController; | 776 using Md = ui::MaterialDesignController; |
| 768 const int kIconVerticalPad = base::GetFieldTrialParamByFeatureAsInt( | 777 const int kIconVerticalPad = base::GetFieldTrialParamByFeatureAsInt( |
| 769 omnibox::kUIExperimentVerticalMargin, | 778 omnibox::kUIExperimentVerticalMargin, |
| 770 OmniboxFieldTrial::kUIVerticalMarginParam, | 779 OmniboxFieldTrial::kUIVerticalMarginParam, |
| 771 Md::GetMode() == Md::MATERIAL_HYBRID ? 8 : 4); | 780 Md::GetMode() == Md::MATERIAL_HYBRID ? 8 : 4); |
| 772 const int min_height = LocationBarView::kIconWidth + 2 * kIconVerticalPad; | 781 const int min_height = LocationBarView::kIconWidth + 2 * kIconVerticalPad; |
| 773 | 782 |
| 774 return std::max(kVerticalPadding, (min_height - GetTextHeight()) / 2); | 783 return std::max(kVerticalMargin, (min_height - GetTextHeight()) / 2); |
| 775 } | 784 } |
| 776 | 785 |
| 777 std::unique_ptr<gfx::RenderText> OmniboxResultView::CreateAnswerText( | 786 std::unique_ptr<gfx::RenderText> OmniboxResultView::CreateAnswerText( |
| 778 const SuggestionAnswer::ImageLine& line, | 787 const SuggestionAnswer::ImageLine& line, |
| 779 const gfx::FontList& font_list) const { | 788 const gfx::FontList& font_list) const { |
| 780 std::unique_ptr<gfx::RenderText> destination = | 789 std::unique_ptr<gfx::RenderText> destination = |
| 781 CreateRenderText(base::string16()); | 790 CreateRenderText(base::string16()); |
| 782 destination->SetFontList(font_list); | 791 destination->SetFontList(font_list); |
| 783 | 792 |
| 784 for (const SuggestionAnswer::TextField& text_field : line.text_fields()) | 793 for (const SuggestionAnswer::TextField& text_field : line.text_fields()) |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 destination->AppendText(text); | 855 destination->AppendText(text); |
| 847 const TextStyle& text_style = GetTextStyle(text_type); | 856 const TextStyle& text_style = GetTextStyle(text_type); |
| 848 // TODO(dschuyler): follow up on the problem of different font sizes within | 857 // TODO(dschuyler): follow up on the problem of different font sizes within |
| 849 // one RenderText. Maybe with destination->SetFontList(...). | 858 // one RenderText. Maybe with destination->SetFontList(...). |
| 850 destination->ApplyWeight( | 859 destination->ApplyWeight( |
| 851 is_bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL, range); | 860 is_bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL, range); |
| 852 destination->ApplyColor( | 861 destination->ApplyColor( |
| 853 GetNativeTheme()->GetSystemColor(text_style.colors[GetState()]), range); | 862 GetNativeTheme()->GetSystemColor(text_style.colors[GetState()]), range); |
| 854 destination->ApplyBaselineStyle(text_style.baseline, range); | 863 destination->ApplyBaselineStyle(text_style.baseline, range); |
| 855 } | 864 } |
| OLD | NEW |