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

Side by Side Diff: chrome/browser/ui/views/omnibox/omnibox_result_view.cc

Issue 917333004: Answers in Suggest icon downloading (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed some {} Created 5 years, 10 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // For WinDDK ATL compatibility, these ATL headers must come first. 5 // For WinDDK ATL compatibility, these ATL headers must come first.
6 #include "build/build_config.h" 6 #include "build/build_config.h"
7 #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/omnibox/omnibox_result_view.h" 12 #include "chrome/browser/ui/views/omnibox/omnibox_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 "base/memory/scoped_vector.h" 17 #include "base/memory/scoped_vector.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 19 #include "base/strings/string_util.h"
20 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h"
21 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" 22 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
21 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" 23 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
22 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" 24 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h"
23 #include "chrome/grit/generated_resources.h" 25 #include "chrome/grit/generated_resources.h"
24 #include "components/omnibox/suggestion_answer.h" 26 #include "components/omnibox/suggestion_answer.h"
25 #include "grit/components_scaled_resources.h" 27 #include "grit/components_scaled_resources.h"
26 #include "grit/theme_resources.h" 28 #include "grit/theme_resources.h"
27 #include "ui/base/l10n/l10n_util.h" 29 #include "ui/base/l10n/l10n_util.h"
28 #include "ui/base/theme_provider.h" 30 #include "ui/base/theme_provider.h"
29 #include "ui/gfx/canvas.h" 31 #include "ui/gfx/canvas.h"
30 #include "ui/gfx/color_utils.h" 32 #include "ui/gfx/color_utils.h"
31 #include "ui/gfx/image/image.h" 33 #include "ui/gfx/image/image.h"
32 #include "ui/gfx/range/range.h" 34 #include "ui/gfx/range/range.h"
33 #include "ui/gfx/render_text.h" 35 #include "ui/gfx/render_text.h"
34 #include "ui/gfx/text_utils.h" 36 #include "ui/gfx/text_utils.h"
35 #include "ui/native_theme/native_theme.h" 37 #include "ui/native_theme/native_theme.h"
36 38
37 using ui::NativeTheme; 39 using ui::NativeTheme;
38 40
39 namespace { 41 namespace {
40 42
43 // The observer watches for changes in the image being downloaded.
44 class AnswersImageObserverDesktop : public BitmapFetcherService::Observer {
45 public:
46 explicit AnswersImageObserverDesktop(
47 gfx::ImageSkia* image, views::View* view):
48 image_(image),
49 view_(view)
50 {}
Peter Kasting 2015/02/13 03:01:07 Please read the Google style guide on how to forma
dschuyler 2015/02/13 22:25:25 Done.
51
52 void OnImageChanged(
53 BitmapFetcherService::RequestId request_id,
54 const SkBitmap& answers_image) override {
55 DCHECK(!answers_image.empty());
56
57 *image_ = gfx::ImageSkia::CreateFrom1xBitmap(answers_image);
groby-ooo-7-16 2015/02/13 02:30:56 Please don't communicate via shared memory. Pass t
dschuyler 2015/02/13 22:25:25 Done.
58
59 // Setup a redraw event so the icon will be drawn sooner.
60 // Without this it will look like the icon is taking longer to download
61 // than it is truly taking.
Peter Kasting 2015/02/13 03:01:07 It seems like if you didn't do this we could poten
dschuyler 2015/02/13 22:25:26 Empirically, something else eventually causes a pa
62 view_->SchedulePaint();
63 }
64
65 private:
66 gfx::ImageSkia* image_;
67 views::View* view_;
groby-ooo-7-16 2015/02/13 02:30:56 What exactly is the ownership situation? Is view_
Peter Kasting 2015/02/13 03:01:07 In that sense, why not just make the view a Bitmap
groby-ooo-7-16 2015/02/13 06:03:47 Because the ImageFetcher takes ownership of the ob
Peter Kasting 2015/02/13 21:59:32 Can we Just Fix That? That design is atypical of
dschuyler 2015/02/13 22:25:25 Thanks for pointing out this over-site. I intende
dschuyler 2015/02/13 22:25:25 Acknowledged.
dschuyler 2015/02/13 22:25:26 Acknowledged.
groby-ooo-7-16 2015/02/13 22:47:22 Filed http://crbug.com/458681 to fix this. (base::
68 };
Peter Kasting 2015/02/13 03:01:07 DISALLOW_COPY_AND_ASSIGN
dschuyler 2015/02/13 22:25:25 Done.
69
41 // The minimum distance between the top and bottom of the {icon|text} and the 70 // The minimum distance between the top and bottom of the {icon|text} and the
42 // top or bottom of the row. 71 // top or bottom of the row.
43 const int kMinimumIconVerticalPadding = 2; 72 const int kMinimumIconVerticalPadding = 2;
44 const int kMinimumTextVerticalPadding = 3; 73 const int kMinimumTextVerticalPadding = 3;
45 74
46 // A mapping from OmniboxResultView's ResultViewState/ColorKind types to 75 // A mapping from OmniboxResultView's ResultViewState/ColorKind types to
47 // NativeTheme colors. 76 // NativeTheme colors.
48 struct TranslationTable { 77 struct TranslationTable {
49 ui::NativeTheme::ColorId id; 78 ui::NativeTheme::ColorId id;
50 OmniboxResultView::ResultViewState state; 79 OmniboxResultView::ResultViewState state;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 int center_; 149 int center_;
121 int right_; 150 int right_;
122 151
123 DISALLOW_COPY_AND_ASSIGN(MirroringContext); 152 DISALLOW_COPY_AND_ASSIGN(MirroringContext);
124 }; 153 };
125 154
126 OmniboxResultView::OmniboxResultView(OmniboxPopupContentsView* model, 155 OmniboxResultView::OmniboxResultView(OmniboxPopupContentsView* model,
127 int model_index, 156 int model_index,
128 LocationBarView* location_bar_view, 157 LocationBarView* location_bar_view,
129 const gfx::FontList& font_list) 158 const gfx::FontList& font_list)
130 : edge_item_padding_(LocationBarView::kItemPadding), 159 : request_id_(BitmapFetcherService::REQUEST_ID_INVALID),
160 edge_item_padding_(LocationBarView::kItemPadding),
131 item_padding_(LocationBarView::kItemPadding), 161 item_padding_(LocationBarView::kItemPadding),
132 minimum_text_vertical_padding_(kMinimumTextVerticalPadding), 162 minimum_text_vertical_padding_(kMinimumTextVerticalPadding),
133 model_(model), 163 model_(model),
134 model_index_(model_index), 164 model_index_(model_index),
135 location_bar_view_(location_bar_view), 165 location_bar_view_(location_bar_view),
136 font_list_(font_list), 166 font_list_(font_list),
137 font_height_( 167 font_height_(
138 std::max(font_list.GetHeight(), 168 std::max(font_list.GetHeight(),
139 font_list.DeriveWithStyle(gfx::Font::BOLD).GetHeight())), 169 font_list.DeriveWithStyle(gfx::Font::BOLD).GetHeight())),
140 mirroring_context_(new MirroringContext()), 170 mirroring_context_(new MirroringContext()),
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 250
221 int OmniboxResultView::GetTextHeight() const { 251 int OmniboxResultView::GetTextHeight() const {
222 return font_height_; 252 return font_height_;
223 } 253 }
224 254
225 void OmniboxResultView::PaintMatch( 255 void OmniboxResultView::PaintMatch(
226 const AutocompleteMatch& match, 256 const AutocompleteMatch& match,
227 gfx::RenderText* contents, 257 gfx::RenderText* contents,
228 gfx::RenderText* description, 258 gfx::RenderText* description,
229 gfx::Canvas* canvas, 259 gfx::Canvas* canvas,
230 int x) const { 260 int x) {
231 int y = text_bounds_.y(); 261 int y = text_bounds_.y();
232 262
233 if (!separator_rendertext_) { 263 if (!separator_rendertext_) {
234 const base::string16& separator = 264 const base::string16& separator =
235 l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR); 265 l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR);
236 separator_rendertext_.reset(CreateRenderText(separator).release()); 266 separator_rendertext_.reset(CreateRenderText(separator).release());
237 separator_rendertext_->SetColor(GetColor(GetState(), DIMMED_TEXT)); 267 separator_rendertext_->SetColor(GetColor(GetState(), DIMMED_TEXT));
238 separator_width_ = separator_rendertext_->GetContentWidth(); 268 separator_width_ = separator_rendertext_->GetContentWidth();
239 } 269 }
240 270
241 int contents_max_width, description_max_width; 271 int contents_max_width, description_max_width;
242 OmniboxPopupModel::ComputeMatchMaxWidths( 272 OmniboxPopupModel::ComputeMatchMaxWidths(
243 contents->GetContentWidth(), 273 contents->GetContentWidth(),
244 separator_width_, 274 separator_width_,
245 description ? description->GetContentWidth() : 0, 275 description ? description->GetContentWidth() : 0,
246 mirroring_context_->remaining_width(x), 276 mirroring_context_->remaining_width(x),
247 !AutocompleteMatch::IsSearchType(match.type), 277 !AutocompleteMatch::IsSearchType(match.type),
248 &contents_max_width, 278 &contents_max_width,
249 &description_max_width); 279 &description_max_width);
250 280
251 x = DrawRenderText(match, contents, true, canvas, x, y, contents_max_width); 281 x = DrawRenderText(match, contents, true, canvas, x, y, contents_max_width);
252 282
253 if (description_max_width != 0) { 283 if (description_max_width != 0) {
254 x = DrawRenderText(match, separator_rendertext_.get(), false, canvas, x, y, 284 x = DrawRenderText(match, separator_rendertext_.get(), false, canvas, x, y,
255 separator_width_); 285 separator_width_);
286
287 if (match.answer && match_.answer->second_line().image_url().is_valid()) {
288 // Draw the answer/description image.
289 gfx::ImageSkia image = GetAnswerIcon();
290 if (image.width())
Peter Kasting 2015/02/13 03:01:07 This should probably be !image.size().IsEmpty()
dschuyler 2015/02/13 22:25:26 Done.
291 canvas->DrawImageInt(
292 image,
293 // Source x, y, w, h.
294 0,
295 0,
296 image.width(),
297 image.height(),
298 // Destination x, y, w, h.
299 GetMirroredXInView(x),
300 y + kMinimumIconVerticalPadding,
301 default_icon_size_,
302 default_icon_size_,
303 true);
304 x += default_icon_size_ + LocationBarView::kIconInternalPadding;
Peter Kasting 2015/02/13 03:01:07 How come we draw the |image| size, but then we ste
dschuyler 2015/02/13 22:25:25 Maybe I'm confused, but I think that the destinati
Peter Kasting 2015/02/13 22:36:36 I think you're right. I read the code explicitly
305 }
306
256 DrawRenderText(match, description, false, canvas, x, y, 307 DrawRenderText(match, description, false, canvas, x, y,
257 description_max_width); 308 description_max_width);
258 } 309 }
259 } 310 }
260 311
261 int OmniboxResultView::DrawRenderText( 312 int OmniboxResultView::DrawRenderText(
262 const AutocompleteMatch& match, 313 const AutocompleteMatch& match,
263 gfx::RenderText* render_text, 314 gfx::RenderText* render_text,
264 bool contents, 315 bool contents,
265 gfx::Canvas* canvas, 316 gfx::Canvas* canvas,
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 std::max(glyph_bounds.start(), glyph_bounds.end()) : 469 std::max(glyph_bounds.start(), glyph_bounds.end()) :
419 std::min(glyph_bounds.start(), glyph_bounds.end()); 470 std::min(glyph_bounds.start(), glyph_bounds.end());
420 471
421 return is_ui_rtl ? 472 return is_ui_rtl ?
422 (input_render_text->GetContentWidth() - start_padding) : start_padding; 473 (input_render_text->GetContentWidth() - start_padding) : start_padding;
423 } 474 }
424 475
425 // static 476 // static
426 int OmniboxResultView::default_icon_size_ = 0; 477 int OmniboxResultView::default_icon_size_ = 0;
427 478
479 gfx::ImageSkia OmniboxResultView::GetAnswerIcon() {
Peter Kasting 2015/02/13 03:01:07 There's no real need to return |answer_image_| in
dschuyler 2015/02/13 22:25:26 Done.
480 // Check to see if we have already requested this image.
481 const GURL& image_url = match_.answer->second_line().image_url();
482 if (image_url.is_valid() && image_url == image_url_)
groby-ooo-7-16 2015/02/13 02:30:56 We don't care about this condition. ImageFetcher I
dschuyler 2015/02/13 22:25:25 I removed the "image_url.is_valid() && " part. I
Peter Kasting 2015/02/13 22:36:36 Depends on how frequent this is. I probably would
groby-ooo-7-16 2015/02/13 22:47:22 You shouldn't call GetAnswerIcon unless there's a
483 // We have already requested it.
484 return answer_image_;
485
486 // We don't have that image, so we will try to get it.
487 answer_image_ = gfx::ImageSkia();
488
489 // Make a new image download request.
490 Profile* profile = location_bar_view_->profile();
groby-ooo-7-16 2015/02/13 02:30:56 Can |profile| _ever_ be NULL here?
Peter Kasting 2015/02/13 03:01:07 I don't think so.
dschuyler 2015/02/13 22:25:25 Acknowledged.
dschuyler 2015/02/13 22:25:26 Done.
491 if (!profile)
492 return answer_image_;
493 content::BrowserContext* browser_context = profile;
groby-ooo-7-16 2015/02/13 02:30:56 No need for the temporary, just pass the profile d
dschuyler 2015/02/13 22:25:25 Done.
494 if (!browser_context)
495 return answer_image_;
496 BitmapFetcherService* image_service =
497 BitmapFetcherServiceFactory::GetForBrowserContext(browser_context);
498 if (!image_service)
groby-ooo-7-16 2015/02/13 02:30:56 Just DCHECK it's not NULL. It never should be, so
dschuyler 2015/02/13 22:25:25 Done.
499 return answer_image_;
500
501 if (request_id_ != BitmapFetcherService::REQUEST_ID_INVALID) {
groby-ooo-7-16 2015/02/13 02:30:56 Just call CancelRequest, without all the testing.
dschuyler 2015/02/13 22:25:25 Done.
502 // Cancel the prior request.
503 image_service->CancelRequest(request_id_);
504 // Request the new url instead of the prior one.
505 request_id_ = BitmapFetcherService::REQUEST_ID_INVALID;
506 }
507
508 // Request the new image.
509 AnswersImageObserverDesktop* observer =
510 new AnswersImageObserverDesktop(&answer_image_, this);
511 if (observer) {
groby-ooo-7-16 2015/02/13 02:30:56 Skip the test - new can't fail. (If it does, crash
Peter Kasting 2015/02/13 03:01:07 To be more precise: We have a memory allocator tha
dschuyler 2015/02/13 22:25:25 Done.
dschuyler 2015/02/13 22:25:25 Acknowledged.
512 image_url_ = image_url;
513 request_id_ = image_service->RequestImage(image_url, observer);
514 }
515
516 // Return what we have (it may already be valid if the image was cached).
517 return answer_image_;
groby-ooo-7-16 2015/02/13 02:30:56 No need to return an image if you always request -
Peter Kasting 2015/02/13 03:01:07 If OnImageChanged() is called synchronously in the
groby-ooo-7-16 2015/02/13 06:03:47 It is called synchronously when data is retrieved
dschuyler 2015/02/13 22:25:25 Acknowledged.
dschuyler 2015/02/13 22:25:25 Done.
518 }
519
428 const char* OmniboxResultView::GetClassName() const { 520 const char* OmniboxResultView::GetClassName() const {
429 return "OmniboxResultView"; 521 return "OmniboxResultView";
430 } 522 }
431 523
432 gfx::ImageSkia OmniboxResultView::GetIcon() const { 524 gfx::ImageSkia OmniboxResultView::GetIcon() const {
433 const gfx::Image image = model_->GetIconIfExtensionMatch(model_index_); 525 const gfx::Image image = model_->GetIconIfExtensionMatch(model_index_);
434 if (!image.IsEmpty()) 526 if (!image.IsEmpty())
435 return image.AsImageSkia(); 527 return image.AsImageSkia();
436 528
437 int icon = model_->IsStarredMatch(match_) ? 529 int icon = model_->IsStarredMatch(match_) ?
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 } 660 }
569 PaintMatch(*keyword_match, keyword_contents_rendertext_.get(), 661 PaintMatch(*keyword_match, keyword_contents_rendertext_.get(),
570 keyword_description_rendertext_.get(), canvas, x); 662 keyword_description_rendertext_.get(), canvas, x);
571 } 663 }
572 } 664 }
573 665
574 void OmniboxResultView::AnimationProgressed(const gfx::Animation* animation) { 666 void OmniboxResultView::AnimationProgressed(const gfx::Animation* animation) {
575 Layout(); 667 Layout();
576 SchedulePaint(); 668 SchedulePaint();
577 } 669 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698