omnibox_result_view.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_popup_model.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/omnibox/omnibox_result_view_model.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/text/text_elider.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/color_utils.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/render_text.h" 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme_win.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme_aura.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char16 kEllipsis[] = { 0x2026, 0x0 }; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The minimum distance between the top and bottom of the {icon|text} and the 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// top or bottom of the row. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumIconVerticalPadding = 2; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumTextVerticalPadding = 3; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxResultView, public: 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Precalculated data used to draw a complete visual run within the match. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This will include all or part of at least one, and possibly several, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// classifications. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct OmniboxResultView::RunData { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunData() : run_start(0), visual_order(0), is_rtl(false), pixel_width(0) {} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t run_start; // Offset within the match text where this run begins. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visual_order; // Where this run occurs in visual order. The earliest 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // run drawn is run 0. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_rtl; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pixel_width; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Styled text classification pieces within this run, in logical order. 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Classifications classifications; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is a utility class for calculations affected by whether the result 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// view is horizontally mirrored. The drawing functions can be written as if 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all drawing occurs left-to-right, and then use this class to get the actual 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// coordinates to begin drawing onscreen. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OmniboxResultView::MirroringContext { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MirroringContext() : center_(0), right_(0) {} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tells the mirroring context to use the provided range as the physical 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bounds of the drawing region. When coordinate mirroring is needed, the 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mirror point will be the center of this range. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Initialize(int x, int width) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) center_ = x + width / 2; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) right_ = x + width; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given a logical range within the drawing region, returns the coordinate of 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the possibly-mirrored "left" side. (This functions exactly like 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // View::MirroredLeftPointForRect().) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int mirrored_left_coord(int left, int right) const { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::i18n::IsRTL() ? (center_ + (center_ - right)) : left; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given a logical coordinate within the drawing region, returns the remaining 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // width available. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remaining_width(int x) const { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return right_ - x; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int center_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MirroringContext); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView::OmniboxResultView( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OmniboxResultViewModel* model, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int model_index, 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Font& font) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : edge_item_padding_(LocationBarView::GetItemPadding()), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item_padding_(LocationBarView::GetItemPadding()), 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimum_text_vertical_padding_(kMinimumTextVerticalPadding), 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(model), 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_index_(model_index), 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) font_(font), 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) font_height_(std::max(font.GetHeight(), 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) font.DeriveFont(0, gfx::BOLD).GetHeight())), 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ellipsis_width_(font.GetStringWidth(string16(kEllipsis))), 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirroring_context_(new MirroringContext()), 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_(new views::ImageView()), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ALLOW_THIS_IN_INITIALIZER_LIST( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_(new ui::SlideAnimation(this))) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GE(model_index, 0); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (default_icon_size_ == 0) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_icon_size_ = 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutocompleteMatch::TypeToIcon(AutocompleteMatch::URL_WHAT_YOU_TYPED))-> 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->set_owned_by_client(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->EnableCanvasFlippingForRTLUI(true); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetImage(GetKeywordIcon()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SizeToPreferredSize(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView::~OmniboxResultView() { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColor OmniboxResultView::GetColor( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResultViewState state, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ColorKind kind) const { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::NativeTheme* theme = GetNativeTheme(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (theme == ui::NativeThemeWin::instance()) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool win_initialized = false; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SkColor win_colors[NUM_STATES][NUM_KINDS]; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!win_initialized) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_colors[NORMAL][BACKGROUND] = color_utils::GetSysSkColor(COLOR_WINDOW); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_colors[SELECTED][BACKGROUND] = 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::GetSysSkColor(COLOR_HIGHLIGHT); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_colors[NORMAL][TEXT] = color_utils::GetSysSkColor(COLOR_WINDOWTEXT); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_colors[SELECTED][TEXT] = 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommonInitColors(theme, win_colors); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) win_initialized = true; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return win_colors[state][kind]; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SkColor colors[NUM_STATES][NUM_KINDS]; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[SELECTED][BACKGROUND] = theme->GetSystemColor( 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[NORMAL][BACKGROUND] = theme->GetSystemColor( 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::NativeTheme::kColorId_TextfieldDefaultBackground); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[NORMAL][URL] = SkColorSetARGB(0xff, 0x00, 0x99, 0x33); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[SELECTED][URL] = SkColorSetARGB(0xff, 0x00, 0x66, 0x22); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[HOVERED][URL] = SkColorSetARGB(0xff, 0x00, 0x66, 0x22); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommonInitColors(theme, colors); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return colors[state][kind]; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::SetMatch(const AutocompleteMatch& match) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match_ = match; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->Reset(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match.associated_keyword.get()) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetImage(GetKeywordIcon()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!keyword_icon_->parent()) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(keyword_icon_.get()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (keyword_icon_->parent()) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveChildView(keyword_icon_.get()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::ShowKeyword(bool show_keyword) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_keyword) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->Show(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->Hide(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::Invalidate() { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetImage(GetKeywordIcon()); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size OmniboxResultView::GetPreferredSize() { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Size(0, std::max( 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_icon_size_ + (kMinimumIconVerticalPadding * 2), 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTextHeight() + (minimum_text_vertical_padding_ * 2))); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OmniboxResultView, protected: 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OmniboxResultView::ResultViewState OmniboxResultView::GetState() const { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_->IsSelectedIndex(model_index_)) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SELECTED; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::PaintMatch(gfx::Canvas* canvas, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AutocompleteMatch& match, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = DrawString(canvas, match.contents, match.contents_class, false, x, 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_bounds_.y()); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Paint the description. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(pkasting): Because we paint in multiple separate pieces, we can wind 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // up with no space even for an ellipsis for one or both of these pieces. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Instead, we should paint the entire match as a single long string. This 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would also let us use a more properly-localizable string than we get with 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just the IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!match.description.empty()) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 separator = 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatchClassifications classifications; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) classifications.push_back( 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ACMatchClassification(0, ACMatchClassification::NONE)); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = DrawString(canvas, separator, classifications, true, x, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_bounds_.y()); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DrawString(canvas, match.description, match.description_class, true, x, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_bounds_.y()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int OmniboxResultView::GetTextHeight() const { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return font_height_; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::CommonInitColors(const ui::NativeTheme* theme, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColor colors[][NUM_KINDS]) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[HOVERED][BACKGROUND] = 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::AlphaBlend(colors[SELECTED][BACKGROUND], 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[NORMAL][BACKGROUND], 64); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[HOVERED][TEXT] = colors[NORMAL][TEXT]; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_aura = theme == ui::NativeThemeAura::instance(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_aura = false; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < NUM_STATES; ++i) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_aura) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[i][TEXT] = 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::AlphaBlend(SK_ColorBLACK, colors[i][BACKGROUND], 0xdd); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[i][DIMMED_TEXT] = 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::AlphaBlend(SK_ColorBLACK, colors[i][BACKGROUND], 0xbb); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[i][DIMMED_TEXT] = 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::AlphaBlend(colors[i][TEXT], colors[i][BACKGROUND], 128); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[i][URL] = color_utils::GetReadableColor(SkColorSetRGB(0, 128, 0), 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[i][BACKGROUND]); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joi): Programmatically draw the dropdown border using 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this color as well. (Right now it's drawn as black with 25% 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // alpha.) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colors[i][DIVIDER] = 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_utils::AlphaBlend(colors[i][TEXT], colors[i][BACKGROUND], 0x34); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxResultView::SortRunsLogically(const RunData& lhs, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RunData& rhs) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lhs.run_start < rhs.run_start; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool OmniboxResultView::SortRunsVisually(const RunData& lhs, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RunData& rhs) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lhs.visual_order < rhs.visual_order; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int OmniboxResultView::default_icon_size_ = 0; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia OmniboxResultView::GetIcon() const { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image image = model_->GetIconIfExtensionMatch(model_index_); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image.IsEmpty()) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return image.AsImageSkia(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon = match_.starred ? 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetState() == SELECTED) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (icon) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_EXTENSION_APP: 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_EXTENSION_APP_SELECTED; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_HTTP: 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_HTTP_SELECTED; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_SEARCH: 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_SEARCH_SELECTED; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case IDR_OMNIBOX_STAR: 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = IDR_OMNIBOX_STAR_SELECTED; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(icon); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const gfx::ImageSkia* OmniboxResultView::GetKeywordIcon() const { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: If we ever begin returning icons of varying size, then callers need 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to ensure that |keyword_icon_| is resized each time its image is reset. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (GetState() == SELECTED) ? IDR_OMNIBOX_TTS_SELECTED : IDR_OMNIBOX_TTS); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int OmniboxResultView::DrawString( 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Canvas* canvas, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& text, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ACMatchClassifications& classifications, 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool force_dim, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text.empty()) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check whether or not this text is a URL. URLs are always displayed LTR 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // regardless of locale. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_url = true; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ACMatchClassifications::const_iterator i(classifications.begin()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != classifications.end(); ++i) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(i->style & ACMatchClassification::URL)) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_url = false; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Split the text into visual runs. We do this first so that we don't need to 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // worry about whether our eliding might change the visual display in 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unintended ways, e.g. by removing directional markings or by adding an 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ellipsis that's not enclosed in appropriate markings. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::BiDiLineIterator bidi_line; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url)) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_runs = bidi_line.CountRuns(); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<gfx::RenderText> render_texts; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Runs runs; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int run = 0; run < num_runs; ++run) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int run_start_int = 0, run_length_int = 0; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The index we pass to GetVisualRun corresponds to the position of the run 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the displayed text. For example, the string "Google in HEBREW" (where 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HEBREW is text in the Hebrew language) has two runs: "Google in " which 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is an LTR run, and "HEBREW" which is an RTL run. In an LTR context, the 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // run "Google in " has the index 0 (since it is the leftmost run 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // displayed). In an RTL context, the same run has the index 1 because it 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is the rightmost run. This is why the order in which we traverse the 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // runs is different depending on the locale direction. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const UBiDiDirection run_direction = bidi_line.GetVisualRun( 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::i18n::IsRTL() && !is_url) ? (num_runs - run - 1) : run, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &run_start_int, &run_length_int); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(run_length_int, 0); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs.push_back(RunData()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RunData* current_run = &runs.back(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_run->run_start = run_start_int; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t run_end = current_run->run_start + run_length_int; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_run->visual_order = run; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_run->is_rtl = !is_url && (run_direction == UBIDI_RTL); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute classifications for this run. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < classifications.size(); ++i) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t text_start = 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(classifications[i].offset, current_run->run_start); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_start >= run_end) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // We're past the last classification in the run. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t text_end = (i < (classifications.size() - 1)) ? 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(classifications[i + 1].offset, run_end) : run_end; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_end <= current_run->run_start) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // We haven't reached the first classification in the run. 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_texts.push_back(gfx::RenderText::CreateInstance()); 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::RenderText* render_text = render_texts.back(); 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_run->classifications.push_back(render_text); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_text->SetText(text.substr(text_start, text_end - text_start)); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_text->SetFont(font_); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate style-related data. 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (classifications[i].style & ACMatchClassification::MATCH) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_text->SetStyle(gfx::BOLD, true); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResultViewState state = GetState(); 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (classifications[i].style & ACMatchClassification::URL) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_text->SetColor(GetColor(state, URL)); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (classifications[i].style & ACMatchClassification::DIM) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_text->SetColor(GetColor(state, DIMMED_TEXT)); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) render_text->SetColor(GetColor(state, force_dim ? DIMMED_TEXT : TEXT)); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_run->pixel_width += render_text->GetStringSize().width(); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!current_run->classifications.empty()); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!runs.empty()); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sort into logical order so we can elide logically. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(runs.begin(), runs.end(), &SortRunsLogically); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now determine what to elide, if anything. Several subtle points: 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * Because we have the run data, we can get edge cases correct, like 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whether to place an ellipsis before or after the end of a run when the 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // text needs to be elided at the run boundary. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * The "or one before it" comments below refer to cases where an earlier 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // classification fits completely, but leaves too little space for an 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ellipsis that turns out to be needed later. These cases are commented 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more completely in Elide(). 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remaining_width = mirroring_context_->remaining_width(x); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->pixel_width > remaining_width) { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This run or one before it needs to be elided. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Classifications::iterator j(i->classifications.begin()); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j != i->classifications.end(); ++j) { 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int width = (*j)->GetStringSize().width(); 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (width > remaining_width) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This classification or one before it needs to be elided. Erase all 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // further classifications and runs so Elide() can simply reverse- 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iterate over everything to find the specific classification to 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // elide. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->classifications.erase(++j, i->classifications.end()); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs.erase(++i, runs.end()); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Elide(&runs, remaining_width); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_width -= width; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_width -= i->pixel_width; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sort back into visual order so we can display the runs correctly. 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(runs.begin(), runs.end(), &SortRunsVisually); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw the runs. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool reverse_visible_order = (i->is_rtl != base::i18n::IsRTL()); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reverse_visible_order) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::reverse(i->classifications.begin(), i->classifications.end()); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Classifications::const_iterator j(i->classifications.begin()); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j != i->classifications.end(); ++j) { 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size size = (*j)->GetStringSize(); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Align the text runs to a common baseline. 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect rect( 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mirroring_context_->mirrored_left_coord(x, x + size.width()), 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) y + font_.GetBaseline() - (*j)->GetBaseline(), 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size.width(), size.height()); 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*j)->SetDisplayRect(rect); 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*j)->Draw(canvas); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) x += size.width(); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::Elide(Runs* runs, int remaining_width) const { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The complexity of this function is due to edge cases like the following: 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have 100 px of available space, an initial classification that takes 86 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // px, and a font that has a 15 px wide ellipsis character. Now if the first 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // classification is followed by several very narrow classifications (e.g. 3 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // px wide each), we don't know whether we need to elide or not at the time we 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // see the first classification -- it depends on how many subsequent 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // classifications follow, and some of those may be in the next run (or 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // several runs!). This is why instead we let our caller move forward until 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we know we definitely need to elide, and then in this function we move 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // backward again until we find a string that we can successfully do the 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // eliding on. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool first_classification = true; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Runs::reverse_iterator i(runs->rbegin()); i != runs->rend(); ++i) { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Classifications::reverse_iterator j(i->classifications.rbegin()); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j != i->classifications.rend(); ++j) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!first_classification) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also add this classification's width (sans ellipsis) back to the 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available width since we want to consider the available space we'll 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have when we draw this classification. 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_width += (*j)->GetStringSize().width(); 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For all but the first classification we consider, we need to append 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // an ellipsis, since there isn't enough room to draw it after this 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // classification. 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*j)->SetText((*j)->text() + kEllipsis); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_classification = false; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Can we fit at least an ellipsis? 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string16 elided_text = ui::ElideText((*j)->text(), (*j)->GetFont(), 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_width, ui::ELIDE_AT_END); 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Classifications::reverse_iterator prior(j + 1); 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool on_first_classification = (prior == i->classifications.rend()); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elided_text.empty() && (remaining_width >= ellipsis_width_) && 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) on_first_classification) { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Edge case: This classification is bold, we can't fit a bold ellipsis 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but we can fit a normal one, and this is the first classification in 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the run. We should display a lone normal ellipsis, because appending 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one to the end of the previous run might put it in the wrong visual 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // location (if the previous run is reversed from the normal visual 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // order). 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: If this isn't the first classification in the run, we don't 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need to bother with this; see note below. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elided_text = kEllipsis; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!elided_text.empty()) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Success. Elide this classification and stop. 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*j)->SetText(elided_text); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we could only fit an ellipsis, then only make it bold if there was 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an immediate prior classification in this run that was also bold, or 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it will look orphaned. 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((((*j)->GetFont().GetStyle() & gfx::BOLD) != 0) && 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (elided_text.length() == 1) && 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (on_first_classification || 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (((*prior)->GetFont().GetStyle() & gfx::BOLD) == 0))) { 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*j)->SetStyle(gfx::BOLD, false); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Erase any other classifications that come after the elided one. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->classifications.erase(j.base(), i->classifications.end()); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs->erase(i.base(), runs->end()); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We couldn't fit an ellipsis. Move back one classification, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // append an ellipsis, and try again. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: In the edge case that a bold ellipsis doesn't fit but a 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // normal one would, and we reach here, then there is a previous 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // classification in this run, and so either: 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * It's normal, and will be able to draw successfully with the 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ellipsis we'll append to it, or 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * It is also bold, in which case we don't want to fall back 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to a normal ellipsis anyway (see comment above). 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We couldn't draw anything. 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) runs->clear(); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::Layout() { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia icon = GetIcon(); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_bounds_.SetRect(edge_item_padding_ + 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((icon.width() == default_icon_size_) ? 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 : LocationBarView::kIconInternalPadding), 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (height() - icon.height()) / 2, icon.width(), icon.height()); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int text_x = edge_item_padding_ + default_icon_size_ + item_padding_; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int text_height = GetTextHeight(); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int text_width; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_.associated_keyword.get()) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kw_collapsed_size = 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->width() + edge_item_padding_; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int max_kw_x = width() - kw_collapsed_size; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kw_x = 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->CurrentValueBetween(max_kw_x, edge_item_padding_); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kw_text_x = kw_x + keyword_icon_->width() + item_padding_; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_width = kw_x - text_x - item_padding_; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_text_bounds_.SetRect(kw_text_x, 0, 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(width() - kw_text_x - edge_item_padding_, 0), text_height); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->SetPosition(gfx::Point(kw_x, 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (height() - keyword_icon_->height()) / 2)); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_width = width() - text_x - edge_item_padding_; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_bounds_.SetRect(text_x, std::max(0, (height() - text_height) / 2), 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(text_width, 0), text_height); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::OnBoundsChanged(const gfx::Rect& previous_bounds) { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_->SetSlideDuration(width() / 4); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::OnPaint(gfx::Canvas* canvas) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResultViewState state = GetState(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state != NORMAL) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawColor(GetColor(state, BACKGROUND)); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!match_.associated_keyword.get() || 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keyword_icon_->x() > icon_bounds_.right()) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Paint the icon. 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(GetIcon(), GetMirroredXForRect(icon_bounds_), 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_bounds_.y()); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Paint the text. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = GetMirroredXForRect(text_bounds_); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirroring_context_->Initialize(x, text_bounds_.width()); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintMatch(canvas, match_, x); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_.associated_keyword.get()) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Paint the keyword text. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = GetMirroredXForRect(keyword_text_bounds_); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirroring_context_->Initialize(x, keyword_text_bounds_.width()); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintMatch(canvas, *match_.associated_keyword.get(), x); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OmniboxResultView::AnimationProgressed(const ui::Animation* animation) { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 627