Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: chrome/browser/ui/views/autocomplete/autocomplete_result_view.cc

Issue 6731036: Enabled pressing TAB to cycle through the Omnibox results. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // For WinDDK ATL compatibility, these ATL headers must come first. 5 // For WinDDK ATL compatibility, these ATL headers must come first.
6 #include "build/build_config.h" 6 #include "build/build_config.h"
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <atlbase.h> // NOLINT 8 #include <atlbase.h> // NOLINT
9 #include <atlwin.h> // NOLINT 9 #include <atlwin.h> // NOLINT
10 #endif 10 #endif
11 11
12 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view.h" 12 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view.h"
13 13
14 #include <algorithm> // NOLINT 14 #include <algorithm> // NOLINT
15 15
16 #include "base/i18n/bidi_line_iterator.h" 16 #include "base/i18n/bidi_line_iterator.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/search_engines/template_url.h"
19 #include "chrome/browser/search_engines/template_url_model.h"
17 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view_model.h" 20 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view_model.h"
18 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" 21 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
19 #include "grit/generated_resources.h" 22 #include "grit/generated_resources.h"
20 #include "grit/theme_resources.h" 23 #include "grit/theme_resources.h"
21 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/resource/resource_bundle.h" 25 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/base/text/text_elider.h" 26 #include "ui/base/text/text_elider.h"
24 #include "ui/gfx/canvas_skia.h" 27 #include "ui/gfx/canvas_skia.h"
25 #include "ui/gfx/color_utils.h" 28 #include "ui/gfx/color_utils.h"
29 #include "views/controls/image_view.h"
30 #include "views/controls/label.h"
26 31
27 #if defined(OS_LINUX) 32 #if defined(OS_LINUX)
28 #include "chrome/browser/ui/gtk/gtk_util.h" 33 #include "chrome/browser/ui/gtk/gtk_util.h"
29 #include "ui/gfx/skia_utils_gtk.h" 34 #include "ui/gfx/skia_utils_gtk.h"
30 #endif 35 #endif
31 36
32 namespace { 37 namespace {
33 38
34 const char16 kEllipsis[] = { 0x2026 }; 39 const char16 kEllipsis[] = { 0x2026 };
35 40
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 return right_ - x; 104 return right_ - x;
100 } 105 }
101 106
102 private: 107 private:
103 int center_; 108 int center_;
104 int right_; 109 int right_;
105 110
106 DISALLOW_COPY_AND_ASSIGN(MirroringContext); 111 DISALLOW_COPY_AND_ASSIGN(MirroringContext);
107 }; 112 };
108 113
114 class AutocompleteResultView::IconLabelView : public views::View {
115 public:
116 explicit IconLabelView(gfx::Font font);
117
118 virtual void Layout();
119 virtual gfx::Size GetPreferredSize();
120 virtual void OnPaint(gfx::Canvas* canvas);
121
122 void SetLabelColor(SkColor color);
123 void SetLabelText(const string16& text);
124 void SetSelected(bool flag);
Peter Kasting 2011/04/13 21:06:59 Nit: Name the arg |selected|.
125
126 private:
127 views::ImageView* image_;
128 views::Label* label_;
129 bool selected_;
130
131 DISALLOW_COPY_AND_ASSIGN(IconLabelView);
132 };
133
134 AutocompleteResultView::IconLabelView::IconLabelView(gfx::Font font)
135 : selected_(false) {
136 image_ = new views::ImageView();
137 AddChildView(image_);
Peter Kasting 2011/04/13 21:06:59 Nit: I think our typical practice is to AddChildVi
138 image_->SetImage(
139 ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_OMNIBOX_SEARCH));
140 label_ = new views::Label();
141 AddChildView(label_);
142 label_->SetFont(font);
143 label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
144 }
145
146 void AutocompleteResultView::IconLabelView::Layout() {
147 const int icon_width = image_->GetPreferredSize().width();
148 image_->SetBounds(LocationBarView::kItemPadding * 2,
Peter Kasting 2011/04/13 21:06:59 The use of padding constants in these next two fun
149 (height() - icon_width) / 2, icon_width, icon_width);
150 const int label_padding = icon_width + LocationBarView::kItemPadding * 3;
151 const int label_height = label_->GetPreferredSize().height();
152 label_->SetBounds(label_padding, (height() - label_height) / 2, width() -
153 label_padding, label_height);
154 }
155
156 gfx::Size AutocompleteResultView::IconLabelView::GetPreferredSize() {
157 gfx::Size size(image_->GetPreferredSize());
158 size.Enlarge(label_->GetPreferredSize().width() +
159 LocationBarView::kExtensionItemPadding +
160 LocationBarView::kItemPadding * 3, 0);
161 return size;
162 }
163
164 void AutocompleteResultView::IconLabelView::OnPaint(gfx::Canvas* canvas) {
165 if (selected_) {
166 canvas->Save();
167 canvas->ClipRectInt(LocationBarView::kItemPadding, 0, width() -
168 LocationBarView::kItemPadding, height());
169 canvas->AsCanvasSkia()->drawColor(GetColor(SELECTED, BACKGROUND));
170 canvas->Restore();
171 } else {
172 canvas->AsCanvasSkia()->drawColor(GetColor(NORMAL, BACKGROUND));
173 }
174
175 SkPaint paint;
176 paint.setColor(GetColor(NORMAL, DIMMED_TEXT));
177 paint.setStrokeWidth(SkIntToScalar(1));
178 paint.setAntiAlias(true);
179
180 canvas->AsCanvasSkia()->drawLine(
181 SkIntToScalar(LocationBarView::kVerticalEdgeThickness),
182 SkIntToScalar(LocationBarView::kNormalHorizontalEdgeThickness),
183 SkIntToScalar(LocationBarView::kVerticalEdgeThickness),
184 SkIntToScalar(height() -
185 LocationBarView::kNormalHorizontalEdgeThickness * 2), paint);
186 }
187
188 void AutocompleteResultView::IconLabelView::SetLabelColor(SkColor color) {
189 label_->SetColor(color);
190 }
191
192 void AutocompleteResultView::IconLabelView::SetLabelText(const string16& text) {
193 label_->SetText(UTF16ToWide(text));
194 }
195
196 void AutocompleteResultView::IconLabelView::SetSelected(bool flag) {
197 selected_ = flag;
198
199 if (selected_)
Peter Kasting 2011/04/13 21:06:59 Nit: Collapse this to one call using ?:
200 image_->SetImage(ResourceBundle::GetSharedInstance().
201 GetBitmapNamed(IDR_OMNIBOX_SEARCH_SELECTED));
202 else
203 image_->SetImage(ResourceBundle::GetSharedInstance().
204 GetBitmapNamed(IDR_OMNIBOX_SEARCH));
205
206 SchedulePaint();
207 }
208
109 AutocompleteResultView::AutocompleteResultView( 209 AutocompleteResultView::AutocompleteResultView(
110 AutocompleteResultViewModel* model, 210 AutocompleteResultViewModel* model,
111 int model_index, 211 int model_index,
112 const gfx::Font& font, 212 const gfx::Font& font,
113 const gfx::Font& bold_font) 213 const gfx::Font& bold_font)
114 : icon_vertical_padding_(kMinimumIconVerticalPadding), 214 : icon_vertical_padding_(kMinimumIconVerticalPadding),
115 text_vertical_padding_(kMinimumTextVerticalPadding), 215 text_vertical_padding_(kMinimumTextVerticalPadding),
116 model_(model), 216 model_(model),
117 model_index_(model_index), 217 model_index_(model_index),
118 normal_font_(font), 218 normal_font_(font),
119 bold_font_(bold_font), 219 bold_font_(bold_font),
120 ellipsis_width_(font.GetStringWidth(string16(kEllipsis))), 220 ellipsis_width_(font.GetStringWidth(string16(kEllipsis))),
121 mirroring_context_(new MirroringContext()), 221 mirroring_context_(new MirroringContext()),
122 match_(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED) { 222 match_(NULL, 0, false, AutocompleteMatch::URL_WHAT_YOU_TYPED),
223 search_view_(new IconLabelView(font)),
224 ALLOW_THIS_IN_INITIALIZER_LIST(animation_(new ui::SlideAnimation(this))) {
123 CHECK_GE(model_index, 0); 225 CHECK_GE(model_index, 0);
124 if (icon_size_ == 0) { 226 if (icon_size_ == 0) {
125 icon_size_ = ResourceBundle::GetSharedInstance().GetBitmapNamed( 227 icon_size_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
126 AutocompleteMatch::TypeToIcon(AutocompleteMatch::URL_WHAT_YOU_TYPED))-> 228 AutocompleteMatch::TypeToIcon(AutocompleteMatch::URL_WHAT_YOU_TYPED))->
127 width(); 229 width();
128 } 230 }
231
232 animation_->SetSlideDuration(500);
233
234 AddChildView(search_view_.get());
129 } 235 }
130 236
131 AutocompleteResultView::~AutocompleteResultView() { 237 AutocompleteResultView::~AutocompleteResultView() {
132 } 238 }
133 239
134 void AutocompleteResultView::OnPaint(gfx::Canvas* canvas) { 240 void AutocompleteResultView::OnPaint(gfx::Canvas* canvas) {
135 const ResultViewState state = GetState(); 241 const ResultViewState state = GetState();
136 if (state != NORMAL) 242 if (state != NORMAL &&
243 match_.keyword_state != AutocompleteMatch::DUAL_SHOWING_KEYWORD)
137 canvas->AsCanvasSkia()->drawColor(GetColor(state, BACKGROUND)); 244 canvas->AsCanvasSkia()->drawColor(GetColor(state, BACKGROUND));
138 245
139 // Paint the icon. 246 // Paint the icon.
140 canvas->DrawBitmapInt(*GetIcon(), GetMirroredXForRect(icon_bounds_), 247 canvas->DrawBitmapInt(*GetIcon(), GetMirroredXForRect(icon_bounds_),
141 icon_bounds_.y()); 248 icon_bounds_.y());
142 249
143 // Paint the text. 250 // Paint the text.
144 int x = GetMirroredXForRect(text_bounds_); 251 int x = GetMirroredXForRect(text_bounds_);
145 mirroring_context_->Initialize(x, text_bounds_.width()); 252 mirroring_context_->Initialize(x, text_bounds_.width());
146 PaintMatch(canvas, match_, x); 253 PaintMatch(canvas, match_, x);
147 } 254 }
148 255
149 void AutocompleteResultView::Layout() { 256 void AutocompleteResultView::Layout() {
150 icon_bounds_.SetRect(LocationBarView::kEdgeItemPadding, 257 icon_bounds_.SetRect(LocationBarView::kEdgeItemPadding,
151 (height() - icon_size_) / 2, icon_size_, icon_size_); 258 (height() - icon_size_) / 2, icon_size_, icon_size_);
152 int text_x = icon_bounds_.right() + LocationBarView::kItemPadding; 259 const int text_x = icon_bounds_.right() + LocationBarView::kItemPadding;
153 int font_height = std::max(normal_font_.GetHeight(), bold_font_.GetHeight()); 260 const int font_height = std::max(normal_font_.GetHeight(),
154 text_bounds_.SetRect(text_x, std::max(0, (height() - font_height) / 2), 261 bold_font_.GetHeight());
155 std::max(bounds().width() - text_x - LocationBarView::kEdgeItemPadding, 262 const int text_y = std::max(0, (height() - font_height) / 2);
156 0), font_height); 263
264 if (match_.has_keyword_hint()) {
265 gfx::Size search_size = search_view_->GetPreferredSize();
266 const float expanded_x = static_cast<float>(text_x +
267 normal_font_.GetStringWidth(UTF8ToUTF16(ui::kEllipsis)) +
268 LocationBarView::kItemPadding);
269 const float collapsed_x = static_cast<float>(bounds().width() -
270 search_size.width());
271 const int search_x = static_cast<int>(collapsed_x - ((collapsed_x -
272 expanded_x) * animation_->GetCurrentValue()));
273
274 text_bounds_.SetRect(text_x, text_y, std::max(search_x - text_x, 0),
275 font_height);
276 search_view_->SetBounds(search_x, 0, std::max(bounds().width() -
277 search_x, 0), height());
278 } else {
279 text_bounds_.SetRect(text_x, text_y,
280 std::max(bounds().width() - text_x, 0), font_height);
281 }
157 } 282 }
158 283
159 gfx::Size AutocompleteResultView::GetPreferredSize() { 284 gfx::Size AutocompleteResultView::GetPreferredSize() {
160 return gfx::Size(0, GetPreferredHeight(normal_font_, bold_font_)); 285 return gfx::Size(0, GetPreferredHeight(normal_font_, bold_font_));
161 } 286 }
162 287
163 int AutocompleteResultView::GetPreferredHeight( 288 int AutocompleteResultView::GetPreferredHeight(
164 const gfx::Font& font, 289 const gfx::Font& font,
165 const gfx::Font& bold_font) { 290 const gfx::Font& bold_font) {
166 int text_height = std::max(font.GetHeight(), bold_font.GetHeight()) + 291 int text_height = std::max(font.GetHeight(), bold_font.GetHeight()) +
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; 387 return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL;
263 } 388 }
264 389
265 const SkBitmap* AutocompleteResultView::GetIcon() const { 390 const SkBitmap* AutocompleteResultView::GetIcon() const {
266 const SkBitmap* bitmap = model_->GetSpecialIcon(model_index_); 391 const SkBitmap* bitmap = model_->GetSpecialIcon(model_index_);
267 if (bitmap) 392 if (bitmap)
268 return bitmap; 393 return bitmap;
269 394
270 int icon = match_.starred ? 395 int icon = match_.starred ?
271 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type); 396 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type);
272 if (model_->IsSelectedIndex(model_index_)) { 397 if (model_->IsSelectedIndex(model_index_) &&
398 match_.keyword_state != AutocompleteMatch::DUAL_SHOWING_KEYWORD) {
273 switch (icon) { 399 switch (icon) {
274 case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_SELECTED; break; 400 case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_SELECTED; break;
275 case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_SELECTED; break; 401 case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_SELECTED; break;
276 case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_SELECTED; break; 402 case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_SELECTED; break;
277 case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_SELECTED; break; 403 case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_SELECTED; break;
278 default: NOTREACHED(); break; 404 default: NOTREACHED(); break;
279 } 405 }
280 } 406 }
281 return ResourceBundle::GetSharedInstance().GetBitmapNamed(icon); 407 return ResourceBundle::GetSharedInstance().GetBitmapNamed(icon);
282 } 408 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 473
348 current_run->classifications.push_back(ClassificationData()); 474 current_run->classifications.push_back(ClassificationData());
349 ClassificationData* current_data = 475 ClassificationData* current_data =
350 &current_run->classifications.back(); 476 &current_run->classifications.back();
351 current_data->text = text.substr(text_start, text_end - text_start); 477 current_data->text = text.substr(text_start, text_end - text_start);
352 478
353 // Calculate style-related data. 479 // Calculate style-related data.
354 const int style = classifications[i].style; 480 const int style = classifications[i].style;
355 const bool use_bold_font = !!(style & ACMatchClassification::MATCH); 481 const bool use_bold_font = !!(style & ACMatchClassification::MATCH);
356 current_data->font = &(use_bold_font ? bold_font_ : normal_font_); 482 current_data->font = &(use_bold_font ? bold_font_ : normal_font_);
357 const ResultViewState state = GetState(); 483 const ResultViewState state =
484 (match_.keyword_state == AutocompleteMatch::DUAL_SHOWING_KEYWORD) ?
485 NORMAL : GetState();
358 if (style & ACMatchClassification::URL) 486 if (style & ACMatchClassification::URL)
359 current_data->color = GetColor(state, URL); 487 current_data->color = GetColor(state, URL);
360 else if (style & ACMatchClassification::DIM) 488 else if (style & ACMatchClassification::DIM)
361 current_data->color = GetColor(state, DIMMED_TEXT); 489 current_data->color = GetColor(state, DIMMED_TEXT);
362 else 490 else
363 current_data->color = GetColor(state, force_dim ? DIMMED_TEXT : TEXT); 491 current_data->color = GetColor(state, force_dim ? DIMMED_TEXT : TEXT);
364 current_data->pixel_width = 492 current_data->pixel_width =
365 current_data->font->GetStringWidth(current_data->text); 493 current_data->font->GetStringWidth(current_data->text);
366 current_run->pixel_width += current_data->pixel_width; 494 current_run->pixel_width += current_data->pixel_width;
367 } 495 }
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 // * It's normal, and will be able to draw successfully with the 631 // * It's normal, and will be able to draw successfully with the
504 // ellipsis we'll append to it, or 632 // ellipsis we'll append to it, or
505 // * It is also bold, in which case we don't want to fall back 633 // * It is also bold, in which case we don't want to fall back
506 // to a normal ellipsis anyway (see comment above). 634 // to a normal ellipsis anyway (see comment above).
507 } 635 }
508 } 636 }
509 637
510 // We couldn't draw anything. 638 // We couldn't draw anything.
511 runs->clear(); 639 runs->clear();
512 } 640 }
641
642 void AutocompleteResultView::SetMatch(const AutocompleteMatch& match) {
643 const bool same_match = match.destination_url == match_.destination_url;
644 const bool is_keyword_mode =
645 match_.keyword_state == AutocompleteMatch::DUAL_SHOWING_KEYWORD;
646 const bool wants_keyword_mode =
647 match.keyword_state == AutocompleteMatch::DUAL_SHOWING_KEYWORD;
648
649 match_ = match;
650
651 if (wants_keyword_mode && !is_keyword_mode)
Peter Kasting 2011/04/13 21:06:59 Do you need to check |same_match| here? Nit: All
652 animation_->Show();
653 else if (same_match && !wants_keyword_mode && is_keyword_mode)
654 animation_->Hide();
655 else if ((!same_match) || (same_match && !animation_->is_animating())) {
Peter Kasting 2011/04/13 21:06:59 Nit: You can eliminate "same_match &&" and all the
656 animation_->Stop();
657 animation_->Reset();
658 }
659
660 search_view_->SetSelected(wants_keyword_mode);
661 search_view_->SetVisible(match_.has_keyword_hint());
Peter Kasting 2011/04/13 21:06:59 Here you really want to check if the match is a DU
662
663 if (wants_keyword_mode) {
664 int message_id = match_.keyword_url->IsExtensionKeyword() ?
665 IDS_EXTENSION_KEYWORD_COMMAND : IDS_KEYWORD_SEARCH;
666 string16 text = l10n_util::GetStringFUTF16(message_id,
667 match_.keyword, l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE));
Peter Kasting 2011/04/13 21:06:59 You should be using match_.keyword_url->AdjustedSh
668 text.append(
669 l10n_util::GetStringUTF16(
670 IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR));
671 text.append(
672 l10n_util::GetStringFUTF16(IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION,
673 match_.keyword));
674 search_view_->SetLabelText(text);
675 search_view_->SetLabelColor(GetColor(SELECTED, DIMMED_TEXT));
676 } else {
677 search_view_->SetLabelText(UTF8ToUTF16(ui::kEllipsis));
678 search_view_->SetLabelColor(GetColor(NORMAL, DIMMED_TEXT));
679 }
680 Layout();
681 }
682
683 void AutocompleteResultView::AnimationProgressed(
684 const ui::Animation* animation) {
685 Layout();
686 SchedulePaint();
687 }
688
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698