| 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 |
| 11 #endif | 11 #endif |
| 12 | 12 |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" | 14 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" |
| 15 | 15 |
| 16 #include <limits.h> | 16 #include <limits.h> |
| 17 | 17 |
| 18 #include <algorithm> // NOLINT | 18 #include <algorithm> // NOLINT |
| 19 | 19 |
| 20 #include "base/feature_list.h" |
| 20 #include "base/i18n/bidi_line_iterator.h" | 21 #include "base/i18n/bidi_line_iterator.h" |
| 21 #include "base/metrics/field_trial_params.h" | 22 #include "base/metrics/field_trial_params.h" |
| 22 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 24 #include "chrome/browser/ui/layout_constants.h" | 25 #include "chrome/browser/ui/layout_constants.h" |
| 25 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h" | 26 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h" |
| 26 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 27 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
| 27 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" | 28 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" |
| 28 #include "chrome/grit/generated_resources.h" | 29 #include "chrome/grit/generated_resources.h" |
| 29 #include "components/grit/components_scaled_resources.h" | 30 #include "components/grit/components_scaled_resources.h" |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 // updating the text in the omnibox but this alert and GetAccessibleNodeData | 297 // updating the text in the omnibox but this alert and GetAccessibleNodeData |
| 297 // below make the answer contents accessible. | 298 // below make the answer contents accessible. |
| 298 if (match_.answer) | 299 if (match_.answer) |
| 299 NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); | 300 NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); |
| 300 } | 301 } |
| 301 | 302 |
| 302 gfx::Size OmniboxResultView::GetPreferredSize() const { | 303 gfx::Size OmniboxResultView::GetPreferredSize() const { |
| 303 int height = GetTextHeight() + (2 * GetVerticalMargin()); | 304 int height = GetTextHeight() + (2 * GetVerticalMargin()); |
| 304 if (match_.answer) | 305 if (match_.answer) |
| 305 height += GetAnswerHeight() + kVerticalPadding; | 306 height += GetAnswerHeight() + kVerticalPadding; |
| 307 else if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) |
| 308 height += GetTextHeight() + kVerticalPadding; |
| 306 return gfx::Size(0, height); | 309 return gfx::Size(0, height); |
| 307 } | 310 } |
| 308 | 311 |
| 309 void OmniboxResultView::GetAccessibleNodeData(ui::AXNodeData* node_data) { | 312 void OmniboxResultView::GetAccessibleNodeData(ui::AXNodeData* node_data) { |
| 310 node_data->SetName(match_.answer | 313 node_data->SetName(match_.answer |
| 311 ? l10n_util::GetStringFUTF16( | 314 ? l10n_util::GetStringFUTF16( |
| 312 IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents, | 315 IDS_OMNIBOX_ACCESSIBLE_ANSWER, match_.contents, |
| 313 match_.answer->second_line().AccessibleText()) | 316 match_.answer->second_line().AccessibleText()) |
| 314 : match_.contents); | 317 : match_.contents); |
| 315 } | 318 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 344 l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR); | 347 l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR); |
| 345 separator_rendertext_ = CreateRenderText(separator); | 348 separator_rendertext_ = CreateRenderText(separator); |
| 346 separator_rendertext_->SetColor(GetColor(GetState(), DIMMED_TEXT)); | 349 separator_rendertext_->SetColor(GetColor(GetState(), DIMMED_TEXT)); |
| 347 separator_width_ = separator_rendertext_->GetContentWidth(); | 350 separator_width_ = separator_rendertext_->GetContentWidth(); |
| 348 } | 351 } |
| 349 | 352 |
| 350 contents->SetDisplayRect(gfx::Rect(gfx::Size(INT_MAX, 0))); | 353 contents->SetDisplayRect(gfx::Rect(gfx::Size(INT_MAX, 0))); |
| 351 if (description) | 354 if (description) |
| 352 description->SetDisplayRect(gfx::Rect(gfx::Size(INT_MAX, 0))); | 355 description->SetDisplayRect(gfx::Rect(gfx::Size(INT_MAX, 0))); |
| 353 int contents_max_width, description_max_width; | 356 int contents_max_width, description_max_width; |
| 357 bool description_on_separate_line = |
| 358 match.answer != nullptr || |
| 359 base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout); |
| 354 OmniboxPopupModel::ComputeMatchMaxWidths( | 360 OmniboxPopupModel::ComputeMatchMaxWidths( |
| 355 contents->GetContentWidth(), | 361 contents->GetContentWidth(), separator_width_, |
| 356 separator_width_, | |
| 357 description ? description->GetContentWidth() : 0, | 362 description ? description->GetContentWidth() : 0, |
| 358 mirroring_context_->remaining_width(x), | 363 mirroring_context_->remaining_width(x), description_on_separate_line, |
| 359 match.answer != nullptr, | 364 !AutocompleteMatch::IsSearchType(match.type), &contents_max_width, |
| 360 !AutocompleteMatch::IsSearchType(match.type), | |
| 361 &contents_max_width, | |
| 362 &description_max_width); | 365 &description_max_width); |
| 363 | 366 |
| 364 int after_contents_x = DrawRenderText(match, contents, CONTENTS, canvas, | 367 // Answers in Suggest results. |
| 365 x, y, contents_max_width); | 368 if (match.answer && description_max_width != 0) { |
| 369 DrawRenderText(match, contents, CONTENTS, canvas, x, y, contents_max_width); |
| 370 y += GetTextHeight() + kVerticalPadding; |
| 371 if (!answer_image_.isNull()) { |
| 372 int answer_icon_size = GetAnswerHeight(); |
| 373 canvas->DrawImageInt(answer_image_, 0, 0, answer_image_.width(), |
| 374 answer_image_.height(), GetMirroredXInView(x), y, |
| 375 answer_icon_size, answer_icon_size, true); |
| 376 // 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 |
| 378 // appropriate font to the beginning of the description, then reducing |
| 379 // the additional padding here to zero). |
| 380 const int kAnswerIconToTextPadding = 2; |
| 381 x += answer_icon_size + kAnswerIconToTextPadding; |
| 382 } |
| 383 return; |
| 384 } |
| 366 | 385 |
| 367 if (description_max_width != 0) { | 386 // Regular results. |
| 368 if (match.answer) { | 387 if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) { |
| 388 // For no description, shift down halfways to draw contents in middle. |
| 389 if (description_max_width == 0) |
| 390 y += (GetTextHeight() + kVerticalPadding) / 2; |
| 391 |
| 392 DrawRenderText(match, contents, CONTENTS, canvas, x, y, contents_max_width); |
| 393 |
| 394 if (description_max_width != 0) { |
| 369 y += GetTextHeight() + kVerticalPadding; | 395 y += GetTextHeight() + kVerticalPadding; |
| 370 if (!answer_image_.isNull()) { | 396 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, |
| 371 int answer_icon_size = GetAnswerHeight(); | 397 description_max_width); |
| 372 canvas->DrawImageInt( | 398 } |
| 373 answer_image_, | 399 } else { |
| 374 0, 0, answer_image_.width(), answer_image_.height(), | 400 x = DrawRenderText(match, contents, CONTENTS, canvas, x, y, |
| 375 GetMirroredXInView(x), y, answer_icon_size, answer_icon_size, true); | 401 contents_max_width); |
| 376 // TODO(dschuyler): Perhaps this should be based on the font size | 402 if (description_max_width != 0) { |
| 377 // 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 | |
| 379 // the additional padding here to zero). | |
| 380 const int kAnswerIconToTextPadding = 2; | |
| 381 x += answer_icon_size + kAnswerIconToTextPadding; | |
| 382 } | |
| 383 } else { | |
| 384 x = DrawRenderText(match, separator_rendertext_.get(), SEPARATOR, canvas, | 403 x = DrawRenderText(match, separator_rendertext_.get(), SEPARATOR, canvas, |
| 385 after_contents_x, y, separator_width_); | 404 x, y, separator_width_); |
| 405 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, |
| 406 description_max_width); |
| 386 } | 407 } |
| 387 | |
| 388 DrawRenderText(match, description, DESCRIPTION, canvas, x, y, | |
| 389 description_max_width); | |
| 390 } | 408 } |
| 391 } | 409 } |
| 392 | 410 |
| 393 int OmniboxResultView::DrawRenderText( | 411 int OmniboxResultView::DrawRenderText( |
| 394 const AutocompleteMatch& match, | 412 const AutocompleteMatch& match, |
| 395 gfx::RenderText* render_text, | 413 gfx::RenderText* render_text, |
| 396 RenderTextType render_text_type, | 414 RenderTextType render_text_type, |
| 397 gfx::Canvas* canvas, | 415 gfx::Canvas* canvas, |
| 398 int x, | 416 int x, |
| 399 int y, | 417 int y, |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 return match_.associated_keyword && | 610 return match_.associated_keyword && |
| 593 (keyword_icon_->x() <= icon_bounds_.right()); | 611 (keyword_icon_->x() <= icon_bounds_.right()); |
| 594 } | 612 } |
| 595 | 613 |
| 596 void OmniboxResultView::InitContentsRenderTextIfNecessary() const { | 614 void OmniboxResultView::InitContentsRenderTextIfNecessary() const { |
| 597 if (!contents_rendertext_) { | 615 if (!contents_rendertext_) { |
| 598 if (match_.answer) { | 616 if (match_.answer) { |
| 599 contents_rendertext_ = | 617 contents_rendertext_ = |
| 600 CreateAnswerText(match_.answer->first_line(), font_list_); | 618 CreateAnswerText(match_.answer->first_line(), font_list_); |
| 601 } else { | 619 } else { |
| 620 bool swap_match_text = |
| 621 base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout) && |
| 622 !AutocompleteMatch::IsSearchType(match_.type) && |
| 623 !match_.description.empty(); |
| 624 |
| 602 contents_rendertext_ = CreateClassifiedRenderText( | 625 contents_rendertext_ = CreateClassifiedRenderText( |
| 603 match_.contents, match_.contents_class, false); | 626 swap_match_text ? match_.description : match_.contents, |
| 627 swap_match_text ? match_.description_class : match_.contents_class, |
| 628 false); |
| 604 } | 629 } |
| 605 } | 630 } |
| 606 } | 631 } |
| 607 | 632 |
| 608 void OmniboxResultView::Layout() { | 633 void OmniboxResultView::Layout() { |
| 609 const int horizontal_padding = | 634 const int horizontal_padding = |
| 610 GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING) + | 635 GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING) + |
| 611 LocationBarView::kIconInteriorPadding; | 636 LocationBarView::kIconInteriorPadding; |
| 612 // The horizontal bounds we're given are the outside bounds, so we can match | 637 // The horizontal bounds we're given are the outside bounds, so we can match |
| 613 // the omnibox border outline shape exactly in OnPaint(). We have to inset | 638 // the omnibox border outline shape exactly in OnPaint(). We have to inset |
| 614 // here to keep the icons lined up. | 639 // here to keep the icons lined up. |
| 615 const int start_x = BackgroundWith1PxBorder::kLocationBarBorderThicknessDip + | 640 const int start_x = BackgroundWith1PxBorder::kLocationBarBorderThicknessDip + |
| 616 horizontal_padding; | 641 horizontal_padding; |
| 617 const int end_x = width() - start_x; | 642 const int end_x = width() - start_x; |
| 618 | 643 |
| 619 const gfx::ImageSkia icon = GetIcon(); | 644 const gfx::ImageSkia icon = GetIcon(); |
| 620 const int icon_y = | 645 |
| 621 GetVerticalMargin() + (GetTextHeight() - icon.height()) / 2; | 646 int row_height = GetTextHeight(); |
| 647 if (base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout)) |
| 648 row_height += kVerticalPadding + GetTextHeight(); |
| 649 |
| 650 const int icon_y = GetVerticalMargin() + (row_height - icon.height()) / 2; |
| 622 icon_bounds_.SetRect(start_x, icon_y, icon.width(), icon.height()); | 651 icon_bounds_.SetRect(start_x, icon_y, icon.width(), icon.height()); |
| 623 | 652 |
| 624 const int text_x = start_x + LocationBarView::kIconWidth + horizontal_padding; | 653 const int text_x = start_x + LocationBarView::kIconWidth + horizontal_padding; |
| 625 int text_width = end_x - text_x; | 654 int text_width = end_x - text_x; |
| 626 | 655 |
| 627 if (match_.associated_keyword.get()) { | 656 if (match_.associated_keyword.get()) { |
| 628 const int max_kw_x = end_x - keyword_icon_->width(); | 657 const int max_kw_x = end_x - keyword_icon_->width(); |
| 629 const int kw_x = animation_->CurrentValueBetween(max_kw_x, start_x); | 658 const int kw_x = animation_->CurrentValueBetween(max_kw_x, start_x); |
| 630 const int kw_text_x = kw_x + keyword_icon_->width() + horizontal_padding; | 659 const int kw_text_x = kw_x + keyword_icon_->width() + horizontal_padding; |
| 631 | 660 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 653 icon_bounds_.y()); | 682 icon_bounds_.y()); |
| 654 int x = GetMirroredXForRect(text_bounds_); | 683 int x = GetMirroredXForRect(text_bounds_); |
| 655 mirroring_context_->Initialize(x, text_bounds_.width()); | 684 mirroring_context_->Initialize(x, text_bounds_.width()); |
| 656 InitContentsRenderTextIfNecessary(); | 685 InitContentsRenderTextIfNecessary(); |
| 657 | 686 |
| 658 if (!description_rendertext_) { | 687 if (!description_rendertext_) { |
| 659 if (match_.answer) { | 688 if (match_.answer) { |
| 660 description_rendertext_ = | 689 description_rendertext_ = |
| 661 CreateAnswerText(match_.answer->second_line(), GetAnswerFont()); | 690 CreateAnswerText(match_.answer->second_line(), GetAnswerFont()); |
| 662 } else if (!match_.description.empty()) { | 691 } else if (!match_.description.empty()) { |
| 692 // If the description is empty, we wouldn't swap with the contents -- |
| 693 // nor would we create the description RenderText object anyways. |
| 694 bool swap_match_text = base::FeatureList::IsEnabled( |
| 695 omnibox::kUIExperimentVerticalLayout) && |
| 696 !AutocompleteMatch::IsSearchType(match_.type); |
| 697 |
| 663 description_rendertext_ = CreateClassifiedRenderText( | 698 description_rendertext_ = CreateClassifiedRenderText( |
| 664 match_.description, match_.description_class, true); | 699 swap_match_text ? match_.contents : match_.description, |
| 700 swap_match_text ? match_.contents_class : match_.description_class, |
| 701 false); |
| 665 } | 702 } |
| 666 } | 703 } |
| 667 PaintMatch(match_, contents_rendertext_.get(), | 704 PaintMatch(match_, contents_rendertext_.get(), |
| 668 description_rendertext_.get(), canvas, x); | 705 description_rendertext_.get(), canvas, x); |
| 669 } | 706 } |
| 670 | 707 |
| 671 AutocompleteMatch* keyword_match = match_.associated_keyword.get(); | 708 AutocompleteMatch* keyword_match = match_.associated_keyword.get(); |
| 672 if (keyword_match) { | 709 if (keyword_match) { |
| 673 int x = GetMirroredXForRect(keyword_text_bounds_); | 710 int x = GetMirroredXForRect(keyword_text_bounds_); |
| 674 mirroring_context_->Initialize(x, keyword_text_bounds_.width()); | 711 mirroring_context_->Initialize(x, keyword_text_bounds_.width()); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 destination->AppendText(text); | 844 destination->AppendText(text); |
| 808 const TextStyle& text_style = GetTextStyle(text_type); | 845 const TextStyle& text_style = GetTextStyle(text_type); |
| 809 // TODO(dschuyler): follow up on the problem of different font sizes within | 846 // TODO(dschuyler): follow up on the problem of different font sizes within |
| 810 // one RenderText. Maybe with destination->SetFontList(...). | 847 // one RenderText. Maybe with destination->SetFontList(...). |
| 811 destination->ApplyWeight( | 848 destination->ApplyWeight( |
| 812 is_bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL, range); | 849 is_bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL, range); |
| 813 destination->ApplyColor( | 850 destination->ApplyColor( |
| 814 GetNativeTheme()->GetSystemColor(text_style.colors[GetState()]), range); | 851 GetNativeTheme()->GetSystemColor(text_style.colors[GetState()]), range); |
| 815 destination->ApplyBaselineStyle(text_style.baseline, range); | 852 destination->ApplyBaselineStyle(text_style.baseline, range); |
| 816 } | 853 } |
| OLD | NEW |