15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For WinDDK ATL compatibility, these ATL headers must come first. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlbase.h> // NOLINT 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlwin.h> // NOLINT 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> // NOLINT 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/bidi_line_iterator.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/string_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_popup_model.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h" 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/theme_provider.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/color_utils.h" 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image.h" 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/range/range.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/render_text.h" 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/text_elider.h" 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/text_utils.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing ui::NativeTheme; 37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The minimum distance between the top and bottom of the {icon|text} and the 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// top or bottom of the row. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumIconVerticalPadding = 2; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumTextVerticalPadding = 3; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// A mapping from OmniboxResultView's ResultViewState/ColorKind types to 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// NativeTheme colors. 47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstruct TranslationTable { 48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ui::NativeTheme::ColorId id; 49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::ResultViewState state; 50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::ColorKind kind; 51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} static const kTranslationTable[] = { 52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableNormalBackground, 53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND }, 54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableHoveredBackground, 55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::HOVERED, OmniboxResultView::BACKGROUND }, 56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableSelectedBackground, 57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::SELECTED, OmniboxResultView::BACKGROUND }, 58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableNormalText, 59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::NORMAL, OmniboxResultView::TEXT }, 60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableHoveredText, 61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::HOVERED, OmniboxResultView::TEXT }, 62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableSelectedText, 63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::SELECTED, OmniboxResultView::TEXT }, 64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableNormalDimmedText, 65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::NORMAL, OmniboxResultView::DIMMED_TEXT }, 66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableHoveredDimmedText, 67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::HOVERED, OmniboxResultView::DIMMED_TEXT }, 68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableSelectedDimmedText, 69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::SELECTED, OmniboxResultView::DIMMED_TEXT }, 70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableNormalUrl, 71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::NORMAL, OmniboxResultView::URL }, 72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableHoveredUrl, 73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::HOVERED, OmniboxResultView::URL }, 74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableSelectedUrl, 75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::SELECTED, OmniboxResultView::URL }, 76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableNormalDivider, 77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::NORMAL, OmniboxResultView::DIVIDER }, 78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableHoveredDivider, 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::HOVERED, OmniboxResultView::DIVIDER }, 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch { NativeTheme::kColorId_ResultsTableSelectedDivider, 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OmniboxResultView::SELECTED, OmniboxResultView::DIVIDER }, 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}; 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxResultView, public: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is a utility class for calculations affected by whether the result 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// view is horizontally mirrored. The drawing functions can be written as if 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all drawing occurs left-to-right, and then use this class to get the actual 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// coordinates to begin drawing onscreen. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OmniboxResultView::MirroringContext { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MirroringContext() : center_(0), right_(0) {} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tells the mirroring context to use the provided range as the physical 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bounds of the drawing region. When coordinate mirroring is needed, the 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mirror point will be the center of this range. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Initialize(int x, int width) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) center_ = x + width / 2; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) right_ = x + width; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given a logical range within the drawing region, returns the coordinate of 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the possibly-mirrored "left" side. (This functions exactly like 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // View::MirroredLeftPointForRect().) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mirrored_left_coord(int left, int right) const { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::i18n::IsRTL() ? (center_ + (center_ - right)) : left; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given a logical coordinate within the drawing region, returns the remaining 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // width available. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remaining_width(int x) const { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return right_ - x; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int center_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MirroringContext); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)OmniboxResultView::OmniboxResultView(OmniboxPopupContentsView* model, 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int model_index, 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LocationBarView* location_bar_view, 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const gfx::FontList& font_list) 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : edge_item_padding_(LocationBarView::kItemPadding), 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu item_padding_(LocationBarView::kItemPadding), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimum_text_vertical_padding_(kMinimumTextVerticalPadding), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(model), 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_index_(model_index), 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) location_bar_view_(location_bar_view), 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) font_list_(font_list), 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) font_height_( 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::max(font_list.GetHeight(), 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) font_list.DeriveWithStyle(gfx::Font::BOLD).GetHeight())), 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirroring_context_(new MirroringContext()), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_(new views::ImageView()), 141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) animation_(new gfx::SlideAnimation(this)) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(model_index, 0); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (default_icon_size_ == 0) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_icon_size_ = 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) location_bar_view_->GetThemeProvider()->GetImageSkiaNamed( 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AutocompleteMatch::TypeToIcon( 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AutocompleteMatchType::URL_WHAT_YOU_TYPED))->width(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->set_owned_by_client(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->EnableCanvasFlippingForRTLUI(true); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetImage(GetKeywordIcon()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SizeToPreferredSize(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView::~OmniboxResultView() { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor OmniboxResultView::GetColor( 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResultViewState state, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ColorKind kind) const { 161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (size_t i = 0; i < arraysize(kTranslationTable); ++i) { 162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (kTranslationTable[i].state == state && 163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kTranslationTable[i].kind == kind) { 164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return GetNativeTheme()->GetSystemColor(kTranslationTable[i].id); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NOTREACHED(); 169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return SK_ColorRED; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::SetMatch(const AutocompleteMatch& match) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match_ = match; 17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ResetRenderTexts(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->Reset(); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AutocompleteMatch* associated_keyword_match = match_.associated_keyword.get(); 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (associated_keyword_match) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetImage(GetKeywordIcon()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!keyword_icon_->parent()) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(keyword_icon_.get()); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (keyword_icon_->parent()) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveChildView(keyword_icon_.get()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::ShowKeyword(bool show_keyword) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_keyword) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->Show(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->Hide(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::Invalidate() { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetImage(GetKeywordIcon()); 19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // While the text in the RenderTexts may not have changed, the styling 19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // (color/bold) may need to change. So we reset them to cause them to be 20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // recomputed in OnPaint(). 20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ResetRenderTexts(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size OmniboxResultView::GetPreferredSize() const { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Size(0, std::max( 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_icon_size_ + (kMinimumIconVerticalPadding * 2), 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTextHeight() + (minimum_text_vertical_padding_ * 2))); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxResultView, protected: 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView::ResultViewState OmniboxResultView::GetState() const { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_->IsSelectedIndex(model_index_)) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SELECTED; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int OmniboxResultView::GetTextHeight() const { 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return font_height_; 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void OmniboxResultView::PaintMatch( 22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const AutocompleteMatch& match, 22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) gfx::RenderText* contents, 22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) gfx::RenderText* description, 22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) gfx::Canvas* canvas, 22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int x) const { 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int y = text_bounds_.y(); 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!separator_rendertext_) { 23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const base::string16& separator = 23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR); 23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) separator_rendertext_.reset(CreateRenderText(separator).release()); 23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) separator_rendertext_->SetColor(GetColor(GetState(), DIMMED_TEXT)); 23723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) separator_width_ = separator_rendertext_->GetContentWidth(); 23823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 24023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int contents_max_width, description_max_width; 24123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) OmniboxPopupModel::ComputeMatchMaxWidths( 24223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) contents->GetContentWidth(), 24323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) separator_width_, 24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) description ? description->GetContentWidth() : 0, 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mirroring_context_->remaining_width(x), 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !AutocompleteMatch::IsSearchType(match.type), 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &contents_max_width, 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &description_max_width); 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 25023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) x = DrawRenderText(match, contents, true, canvas, x, y, contents_max_width); 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (description_max_width != 0) { 25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) x = DrawRenderText(match, separator_rendertext_.get(), false, canvas, x, y, 25423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) separator_width_); 25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DrawRenderText(match, description, false, canvas, x, y, 25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) description_max_width); 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int OmniboxResultView::DrawRenderText( 26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const AutocompleteMatch& match, 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::RenderText* render_text, 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool contents, 26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) gfx::Canvas* canvas, 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int x, 266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int y, 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int max_width) const { 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!render_text->text().empty()); 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const int remaining_width = mirroring_context_->remaining_width(x); 271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int right_x = x + max_width; 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Infinite suggestions should appear with the leading ellipses vertically 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // stacked. 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (contents && 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (match.type == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE)) { 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // When the directionality of suggestion doesn't match the UI, we try to 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // vertically stack the ellipsis by restricting the end edge (right_x). 279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const bool is_ui_rtl = base::i18n::IsRTL(); 280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const bool is_match_contents_rtl = 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (render_text->GetTextDirection() == base::i18n::RIGHT_TO_LEFT); 28223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const int offset = 28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetDisplayOffset(match, is_ui_rtl, is_match_contents_rtl); 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<gfx::RenderText> prefix_render_text( 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateRenderText(base::UTF8ToUTF16( 287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch match.GetAdditionalInfo(kACMatchPropertyContentsPrefix)))); 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int prefix_width = prefix_render_text->GetContentWidth(); 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int prefix_x = x; 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int max_match_contents_width = model_->max_match_contents_width(); 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_ui_rtl != is_match_contents_rtl) { 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // RTL infinite suggestions appear near the left edge in LTR UI, while LTR 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // infinite suggestions appear near the right edge in RTL UI. This is 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // against the natural horizontal alignment of the text. We reduce the 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // width of the box for suggestion display, so that the suggestions appear 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // in correct confines. This reduced width allows us to modify the text 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // alignment (see below). 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) right_x = x + std::min(remaining_width - prefix_width, 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::max(offset, max_match_contents_width)); 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_x = right_x; 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We explicitly set the horizontal alignment so that when LTR suggestions 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // show in RTL UI (or vice versa), their ellipses appear stacked in a 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // single column. 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->SetHorizontalAlignment( 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_match_contents_rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT); 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the dropdown is wide enough, place the ellipsis at the position 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // where the omitted text would have ended. Otherwise reduce the offset of 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the ellipsis such that the widest suggestion reaches the end of the 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // dropdown. 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int start_offset = std::max(prefix_width, 314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::min(remaining_width - max_match_contents_width, offset)); 31523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) right_x = x + std::min(remaining_width, start_offset + max_width); 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x += start_offset; 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_x = x - prefix_width; 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_render_text->SetDirectionalityMode(is_match_contents_rtl ? 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR); 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_render_text->SetHorizontalAlignment( 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_match_contents_rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT); 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_render_text->SetDisplayRect(gfx::Rect( 324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mirroring_context_->mirrored_left_coord( 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_x, prefix_x + prefix_width), y, 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_width, height())); 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) prefix_render_text->Draw(canvas); 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Set the display rect to trigger eliding. 331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->SetDisplayRect(gfx::Rect( 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mirroring_context_->mirrored_left_coord(x, right_x), y, 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) right_x - x, height())); 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->Draw(canvas); 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return right_x; 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<gfx::RenderText> OmniboxResultView::CreateRenderText( 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& text) const { 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<gfx::RenderText> render_text(gfx::RenderText::CreateInstance()); 34123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) render_text->SetCursorEnabled(false); 34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) render_text->SetElideBehavior(gfx::ELIDE_TAIL); 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->SetFontList(font_list_); 344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->SetText(text); 345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return render_text.Pass(); 346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 34823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)scoped_ptr<gfx::RenderText> OmniboxResultView::CreateClassifiedRenderText( 34923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const base::string16& text, 350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ACMatchClassifications& classifications, 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool force_dim) const { 35223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) scoped_ptr<gfx::RenderText> render_text(CreateRenderText(text)); 353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t text_length = render_text->text().length(); 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < classifications.size(); ++i) { 355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t text_start = classifications[i].offset; 356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (text_start >= text_length) 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t text_end = (i < (classifications.size() - 1)) ? 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::min(classifications[i + 1].offset, text_length) : 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) text_length; 362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Range current_range(text_start, text_end); 363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Calculate style-related data. 365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (classifications[i].style & ACMatchClassification::MATCH) 366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->ApplyStyle(gfx::BOLD, true, current_range); 367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ColorKind color_kind = TEXT; 369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (classifications[i].style & ACMatchClassification::URL) { 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) color_kind = URL; 371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Consider logical string for domain "ABC.comי/hello" where ABC are 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Hebrew (RTL) characters. This string should ideally show as 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // "CBA.com/hello". If we do not force LTR on URL, it will appear as 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // "com/hello.CBA". 375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // With IDN and RTL TLDs, it might be okay to allow RTL rendering of URLs, 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // but it still has some pitfalls like : 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // ABC.COM/abc-pqr/xyz/FGH will appear as HGF/abc-pqr/xyz/MOC.CBA which 378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // really confuses the path hierarchy of the URL. 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Also, if the URL supports https, the appearance will change into LTR 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // directionality. 381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // In conclusion, LTR rendering of URL is probably the safest bet. 382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR); 383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (force_dim || 384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (classifications[i].style & ACMatchClassification::DIM)) { 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) color_kind = DIMMED_TEXT; 386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_text->ApplyColor(GetColor(GetState(), color_kind), current_range); 388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 38923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return render_text.Pass(); 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int OmniboxResultView::GetMatchContentsWidth() const { 39323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) InitContentsRenderTextIfNecessary(); 39423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return contents_rendertext_ ? contents_rendertext_->GetContentWidth() : 0; 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// TODO(skanuj): This is probably identical across all OmniboxResultView rows in 398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// the omnibox dropdown. Consider sharing the result. 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int OmniboxResultView::GetDisplayOffset( 40023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const AutocompleteMatch& match, 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_ui_rtl, 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool is_match_contents_rtl) const { 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (match.type != AutocompleteMatchType::SEARCH_SUGGEST_INFINITE) 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& input_text = 407effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::UTF8ToUTF16(match.GetAdditionalInfo(kACMatchPropertyInputText)); 408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int contents_start_index = 0; 409effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::StringToInt(match.GetAdditionalInfo(kACMatchPropertyContentsStartIndex), 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &contents_start_index); 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<gfx::RenderText> input_render_text(CreateRenderText(input_text)); 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Range& glyph_bounds = 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) input_render_text->GetGlyphBounds(contents_start_index); 415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int start_padding = is_match_contents_rtl ? 416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::max(glyph_bounds.start(), glyph_bounds.end()) : 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::min(glyph_bounds.start(), glyph_bounds.end()); 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return is_ui_rtl ? 420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (input_render_text->GetContentWidth() - start_padding) : start_padding; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int OmniboxResultView::default_icon_size_ = 0; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia OmniboxResultView::GetIcon() const { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image image = model_->GetIconIfExtensionMatch(model_index_); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image.IsEmpty()) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return image.AsImageSkia(); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon = match_.starred ? 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetState() == SELECTED) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (icon) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_EXTENSION_APP: 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_EXTENSION_APP_SELECTED; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_HTTP: 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_HTTP_SELECTED; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_SEARCH: 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_SEARCH_SELECTED; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_STAR: 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_STAR_SELECTED; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return *(location_bar_view_->GetThemeProvider()->GetImageSkiaNamed(icon)); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::ImageSkia* OmniboxResultView::GetKeywordIcon() const { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: If we ever begin returning icons of varying size, then callers need 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to ensure that |keyword_icon_| is resized each time its image is reset. 458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return location_bar_view_->GetThemeProvider()->GetImageSkiaNamed( 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (GetState() == SELECTED) ? IDR_OMNIBOX_TTS_SELECTED : IDR_OMNIBOX_TTS); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool OmniboxResultView::ShowOnlyKeywordMatch() const { 46323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return match_.associated_keyword && 46423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (keyword_icon_->x() <= icon_bounds_.right()); 46523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 46623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 46723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void OmniboxResultView::ResetRenderTexts() const { 46823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) contents_rendertext_.reset(); 46923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) description_rendertext_.reset(); 47023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) separator_rendertext_.reset(); 47123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_contents_rendertext_.reset(); 47223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_description_rendertext_.reset(); 47323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 47423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 47523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void OmniboxResultView::InitContentsRenderTextIfNecessary() const { 47623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!contents_rendertext_) { 47723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) contents_rendertext_.reset( 47823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CreateClassifiedRenderText( 47923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) match_.contents, match_.contents_class, false).release()); 48023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 48123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 48223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::Layout() { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia icon = GetIcon(); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_bounds_.SetRect(edge_item_padding_ + 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((icon.width() == default_icon_size_) ? 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 : LocationBarView::kIconInternalPadding), 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (height() - icon.height()) / 2, icon.width(), icon.height()); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int text_x = edge_item_padding_ + default_icon_size_ + item_padding_; 4920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int text_width = width() - text_x - edge_item_padding_; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_.associated_keyword.get()) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kw_collapsed_size = 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->width() + edge_item_padding_; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int max_kw_x = width() - kw_collapsed_size; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kw_x = 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->CurrentValueBetween(max_kw_x, edge_item_padding_); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kw_text_x = kw_x + keyword_icon_->width() + item_padding_; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_width = kw_x - text_x - item_padding_; 5030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) keyword_text_bounds_.SetRect( 5040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) kw_text_x, 0, 5050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::max(width() - kw_text_x - edge_item_padding_, 0), height()); 5060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) keyword_icon_->SetPosition( 5070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) gfx::Point(kw_x, (height() - keyword_icon_->height()) / 2)); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) text_bounds_.SetRect(text_x, 0, std::max(text_width, 0), height()); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::OnBoundsChanged(const gfx::Rect& previous_bounds) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->SetSlideDuration(width() / 4); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::OnPaint(gfx::Canvas* canvas) { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResultViewState state = GetState(); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state != NORMAL) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawColor(GetColor(state, BACKGROUND)); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // NOTE: While animating the keyword match, both matches may be visible. 52323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 52423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!ShowOnlyKeywordMatch()) { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(GetIcon(), GetMirroredXForRect(icon_bounds_), 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_bounds_.y()); 52723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int x = GetMirroredXForRect(text_bounds_); 52823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mirroring_context_->Initialize(x, text_bounds_.width()); 52923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) InitContentsRenderTextIfNecessary(); 53023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!description_rendertext_ && !match_.description.empty()) { 53123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) description_rendertext_.reset( 53223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CreateClassifiedRenderText( 53323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) match_.description, match_.description_class, true).release()); 53423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 53523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) PaintMatch(match_, contents_rendertext_.get(), 53623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) description_rendertext_.get(), canvas, x); 53723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 53823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 53923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AutocompleteMatch* keyword_match = match_.associated_keyword.get(); 54023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (keyword_match) { 54123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int x = GetMirroredXForRect(keyword_text_bounds_); 54223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) mirroring_context_->Initialize(x, keyword_text_bounds_.width()); 54323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!keyword_contents_rendertext_) { 54423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_contents_rendertext_.reset( 54523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CreateClassifiedRenderText(keyword_match->contents, 54623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_match->contents_class, 54723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) false).release()); 54823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 54923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!keyword_description_rendertext_ && 55023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) !keyword_match->description.empty()) { 55123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_description_rendertext_.reset( 55223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CreateClassifiedRenderText(keyword_match->description, 55323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_match->description_class, 55423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) true).release()); 55523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 55623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) PaintMatch(*keyword_match, keyword_contents_rendertext_.get(), 55723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) keyword_description_rendertext_.get(), canvas, x); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void OmniboxResultView::AnimationProgressed(const gfx::Animation* animation) { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565