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

Side by Side Diff: chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc

Issue 79032: Split out the contents view into its own header. rename it to AutocompletePop... (Closed) Base URL: svn://chrome-svn.corp.google.com/chrome/trunk/src/
Patch Set: '' Created 11 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
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file.
4
5 #include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h"
6
7 #include <dwmapi.h>
8
9 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
10 #include "chrome/browser/views/autocomplete/autocomplete_popup_win.h"
11 #include "chrome/common/gfx/chrome_canvas.h"
12 #include "chrome/common/gfx/color_utils.h"
13 #include "chrome/common/gfx/insets.h"
14 #include "chrome/common/gfx/path.h"
15 #include "chrome/common/resource_bundle.h"
16 #include "chrome/views/widget/widget.h"
17 #include "grit/theme_resources.h"
18 #include "skia/include/SkShader.h"
19
20 // The stroke color around the popup border.
21 static const SkColor kEdgeColor = SkColorSetRGB(183, 195, 219);
22 static const int kPopupTransparency = 235;
23 static const int kHoverRowAlpha = 0x40;
24
25 class AutocompleteResultView : public views::View {
26 public:
27 AutocompleteResultView(AutocompleteResultViewModel* model, int model_index);
28 virtual ~AutocompleteResultView();
29
30 // Overridden from views::View:
31 virtual void Paint(ChromeCanvas* canvas);
32 virtual gfx::Size GetPreferredSize();
33 virtual void OnMouseEntered(const views::MouseEvent& event);
34 virtual void OnMouseMoved(const views::MouseEvent& event);
35 virtual void OnMouseExited(const views::MouseEvent& event);
36 virtual bool OnMousePressed(const views::MouseEvent& event);
37 virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled);
38 virtual bool OnMouseDragged(const views::MouseEvent& event);
39
40 private:
41 // Paint the result view in different ways.
42 void PaintAsSearchDefault(ChromeCanvas* canvas);
43 void PaintAsURLSuggestion(ChromeCanvas* canvas);
44 void PaintAsQuerySuggestion(ChromeCanvas* canvas);
45 void PaintAsMoreRow(ChromeCanvas* canvas);
46
47 // Get colors for row backgrounds and text for different row states.
48 SkColor GetHighlightRowColor() const;
49 SkColor GetHighlightTextColor() const;
50 SkColor GetHoverRowColor() const;
51 SkColor GetTextColor() const;
52
53 // This row's model and model index.
54 AutocompleteResultViewModel* model_;
55 size_t model_index_;
56
57 // True if the mouse is over this row.
58 bool hot_;
59
60 DISALLOW_COPY_AND_ASSIGN(AutocompleteResultView);
61 };
62
63 AutocompleteResultView::AutocompleteResultView(
64 AutocompleteResultViewModel* model,
65 int model_index)
66 : model_(model),
67 model_index_(model_index),
68 hot_(false) {
69 }
70
71 AutocompleteResultView::~AutocompleteResultView() {
72 }
73
74 void AutocompleteResultView::Paint(ChromeCanvas* canvas) {
75 // Paint the row background if any.
76 if (model_->IsSelectedIndex(model_index_))
77 canvas->FillRectInt(GetHighlightRowColor(), 0, 0, width(), height());
78 else if (hot_)
79 canvas->FillRectInt(GetHoverRowColor(), 0, 0, width(), height());
80 }
81
82 gfx::Size AutocompleteResultView::GetPreferredSize() {
83 return gfx::Size(0, 30);
84 }
85
86 void AutocompleteResultView::OnMouseEntered(const views::MouseEvent& event) {
87 hot_ = true;
88 SchedulePaint();
89 }
90
91 void AutocompleteResultView::OnMouseMoved(const views::MouseEvent& event) {
92 if (!hot_) {
93 hot_ = true;
94 SchedulePaint();
95 }
96 }
97
98 void AutocompleteResultView::OnMouseExited(const views::MouseEvent& event) {
99 hot_ = false;
100 SchedulePaint();
101 }
102
103 bool AutocompleteResultView::OnMousePressed(const views::MouseEvent& event) {
104 if (event.IsOnlyLeftMouseButton()) {
105 model_->SetHoveredLine(model_index_);
106 model_->SetSelectedLine(model_index_, false);
107 } else if (event.IsOnlyMiddleMouseButton()) {
108 model_->SetHoveredLine(model_index_);
109 }
110 return true;
111 }
112
113 void AutocompleteResultView::OnMouseReleased(const views::MouseEvent& event,
114 bool canceled) {
115 if (canceled)
116 return;
117 if (event.IsOnlyMiddleMouseButton())
118 model_->OpenIndex(model_index_, NEW_BACKGROUND_TAB);
119 else if (event.IsOnlyLeftMouseButton())
120 model_->OpenIndex(model_index_, CURRENT_TAB);
121 }
122
123 bool AutocompleteResultView::OnMouseDragged(const views::MouseEvent& event) {
124 // TODO(beng): move all message handling into the contents view and override
125 // GetViewForPoint.
126 return false;
127 }
128
129 void AutocompleteResultView::PaintAsSearchDefault(ChromeCanvas* canvas) {
130
131 }
132
133 void AutocompleteResultView::PaintAsURLSuggestion(ChromeCanvas* canvas) {
134
135 }
136
137 void AutocompleteResultView::PaintAsQuerySuggestion(ChromeCanvas* canvas) {
138
139 }
140
141 void AutocompleteResultView::PaintAsMoreRow(ChromeCanvas* canvas) {
142
143 }
144
145 SkColor AutocompleteResultView::GetHighlightRowColor() const {
146 return color_utils::GetSysSkColor(COLOR_HIGHLIGHT);
147 }
148
149 SkColor AutocompleteResultView::GetHighlightTextColor() const {
150 return color_utils::GetSysSkColor(COLOR_HIGHLIGHTTEXT);
151 }
152
153 SkColor AutocompleteResultView::GetHoverRowColor() const {
154 COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
155 return SkColorSetARGB(kHoverRowAlpha, GetRValue(color), GetGValue(color),
156 GetBValue(color));
157 }
158
159 SkColor AutocompleteResultView::GetTextColor() const {
160 return color_utils::GetSysSkColor(COLOR_WINDOWTEXT);
161 }
162
163 class PopupBorder : public views::Border {
164 public:
165 PopupBorder() {
166 InitClass();
167 }
168 virtual ~PopupBorder() {}
169
170 // Returns the border radius of the edge of the popup.
171 static int GetBorderRadius() {
172 InitClass();
173 return dropshadow_topleft_->width() - dropshadow_left_->width() - 1;
174 }
175
176 // Overridden from views::Border:
177 virtual void Paint(const views::View& view, ChromeCanvas* canvas) const;
178 virtual void GetInsets(gfx::Insets* insets) const;
179
180 private:
181 // Border graphics.
182 static SkBitmap* dropshadow_left_;
183 static SkBitmap* dropshadow_topleft_;
184 static SkBitmap* dropshadow_top_;
185 static SkBitmap* dropshadow_topright_;
186 static SkBitmap* dropshadow_right_;
187 static SkBitmap* dropshadow_bottomright_;
188 static SkBitmap* dropshadow_bottom_;
189 static SkBitmap* dropshadow_bottomleft_;
190
191 static void InitClass();
192
193 DISALLOW_COPY_AND_ASSIGN(PopupBorder);
194 };
195
196 // static
197 SkBitmap* PopupBorder::dropshadow_left_ = NULL;
198 SkBitmap* PopupBorder::dropshadow_topleft_ = NULL;
199 SkBitmap* PopupBorder::dropshadow_top_ = NULL;
200 SkBitmap* PopupBorder::dropshadow_topright_ = NULL;
201 SkBitmap* PopupBorder::dropshadow_right_ = NULL;
202 SkBitmap* PopupBorder::dropshadow_bottomright_ = NULL;
203 SkBitmap* PopupBorder::dropshadow_bottom_ = NULL;
204 SkBitmap* PopupBorder::dropshadow_bottomleft_ = NULL;
205
206 void PopupBorder::Paint(const views::View& view, ChromeCanvas* canvas) const {
207 int ds_tl_width = dropshadow_topleft_->width();
208 int ds_tl_height = dropshadow_topleft_->height();
209 int ds_tr_width = dropshadow_topright_->width();
210 int ds_tr_height = dropshadow_topright_->height();
211 int ds_br_width = dropshadow_bottomright_->width();
212 int ds_br_height = dropshadow_bottomright_->height();
213 int ds_bl_width = dropshadow_bottomleft_->width();
214 int ds_bl_height = dropshadow_bottomleft_->height();
215
216 canvas->DrawBitmapInt(*dropshadow_topleft_, 0, 0);
217 canvas->TileImageInt(*dropshadow_top_, ds_tl_width, 0,
218 view.width() - ds_tr_width - ds_tl_width,
219 dropshadow_top_->height());
220 canvas->DrawBitmapInt(*dropshadow_topright_, view.width() - ds_tr_width, 0);
221 canvas->TileImageInt(*dropshadow_right_,
222 view.width() - dropshadow_right_->width(),
223 ds_tr_height, dropshadow_right_->width(),
224 view.height() - ds_tr_height - ds_br_height);
225 canvas->DrawBitmapInt(*dropshadow_bottomright_, view.width() - ds_br_width,
226 view.height() - ds_br_height);
227 canvas->TileImageInt(*dropshadow_bottom_, ds_bl_width,
228 view.height() - dropshadow_bottom_->height(),
229 view.width() - ds_bl_width - ds_br_width,
230 dropshadow_bottom_->height());
231 canvas->DrawBitmapInt(*dropshadow_bottomleft_, 0,
232 view.height() - dropshadow_bottomleft_->height());
233 canvas->TileImageInt(*dropshadow_left_, 0, ds_tl_height,
234 dropshadow_left_->width(),
235 view.height() - ds_tl_height - ds_bl_height);
236 }
237
238 void PopupBorder::GetInsets(gfx::Insets* insets) const {
239 // The left, right and bottom edge image sizes define our insets. The corner
240 // images don't determine this because they can extend in both directions.
241 insets->Set(dropshadow_top_->height(), dropshadow_left_->width(),
242 dropshadow_bottom_->height(), dropshadow_right_->width());
243 }
244
245 void PopupBorder::InitClass() {
246 static bool initialized = false;
247 if (!initialized) {
248 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
249 dropshadow_left_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_L);
250 dropshadow_topleft_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_TL);
251 dropshadow_top_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_T);
252 dropshadow_topright_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_TR);
253 dropshadow_right_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_R);
254 dropshadow_bottomright_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_BR);
255 dropshadow_bottom_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_B);
256 dropshadow_bottomleft_ = rb.GetBitmapNamed(IDR_OMNIBOX_POPUP_DS_BL);
257 initialized = true;
258 }
259 }
260
261 ////////////////////////////////////////////////////////////////////////////////
262 // AutocompletePopupContentsView, public:
263
264 AutocompletePopupContentsView::AutocompletePopupContentsView(
265 AutocompletePopupWin* popup)
266 : popup_(popup) {
267 set_border(new PopupBorder);
268 }
269
270 void AutocompletePopupContentsView::SetAutocompleteResult(
271 const AutocompleteResult& result) {
272 RemoveAllChildViews(true);
273 for (size_t i = 0; i < result.size(); ++i) {
274 AutocompleteMatch match = result.match_at(i);
275 AutocompleteResultView* result = new AutocompleteResultView(this, i);
276 AddChildView(result);
277 }
278 Layout();
279 }
280
281 void AutocompletePopupContentsView::InvalidateLine(int index) {
282 GetChildViewAt(index)->SchedulePaint();
283 }
284
285 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) {
286 return index == popup_->GetModel()->selected_line();
287 }
288
289 AutocompleteMatch::Type AutocompletePopupContentsView::GetResultTypeAtIndex(
290 size_t index) {
291 return popup_->GetModel()->result().match_at(index).type;
292 }
293
294 void AutocompletePopupContentsView::OpenIndex(
295 size_t index,
296 WindowOpenDisposition disposition) {
297 popup_->OpenIndex(index, disposition);
298 }
299
300 void AutocompletePopupContentsView::SetHoveredLine(size_t index) {
301 popup_->SetHoveredLine(index);
302 }
303
304 void AutocompletePopupContentsView::SetSelectedLine(size_t index,
305 bool revert_to_default) {
306 popup_->SetSelectedLine(index, revert_to_default);
307 }
308
309 ////////////////////////////////////////////////////////////////////////////////
310 // AutocompletePopupContentsView, views::View overrides:
311
312 void AutocompletePopupContentsView::PaintChildren(ChromeCanvas* canvas) {
313 // We paint our children in an unconventional way.
314 //
315 // Because the border of this view creates an anti-aliased round-rect region
316 // for the contents, we need to render our rectangular result child views into
317 // this round rect region. We can't use a simple clip because clipping is
318 // 1-bit and we get nasty jagged edges.
319 //
320 // Instead, we paint all our children into a second canvas and use that as a
321 // shader to fill a path representing the round-rect clipping region. This
322 // yields a nice anti-aliased edge.
323 gfx::Rect contents_rect = GetLocalBounds(false);
324 ChromeCanvas contents_canvas(contents_rect.width(), contents_rect.height(),
325 true);
326 contents_canvas.FillRectInt(color_utils::GetSysSkColor(COLOR_WINDOW), 0, 0,
327 contents_rect.width(), contents_rect.height());
328 // We want the contents background to be slightly transparent so we can see
329 // the blurry glass effect on DWM systems behind.
330 MakeCanvasTransparent(&contents_canvas);
331 View::PaintChildren(&contents_canvas);
332
333 // Now paint the contents of the contents canvas into the actual canvas.
334 SkPaint paint;
335 paint.setAntiAlias(true);
336
337 SkShader* shader = SkShader::CreateBitmapShader(
338 contents_canvas.getDevice()->accessBitmap(false),
339 SkShader::kClamp_TileMode,
340 SkShader::kClamp_TileMode);
341 paint.setShader(shader);
342 shader->unref();
343
344 gfx::Path path;
345 MakeContentsPath(&path, contents_rect);
346 canvas->drawPath(path, paint);
347 }
348
349 void AutocompletePopupContentsView::Layout() {
350 UpdateBlurRegion();
351
352 // Size our children to the available content area.
353 gfx::Rect contents_rect = GetLocalBounds(false);
354 int child_count = GetChildViewCount();
355 int top = contents_rect.y();
356 for (int i = 0; i < child_count; ++i) {
357 View* v = GetChildViewAt(i);
358 v->SetBounds(contents_rect.x(), top, contents_rect.width(),
359 v->GetPreferredSize().height());
360 top = v->bounds().bottom();
361 }
362
363 // We need to manually schedule a paint here since we are a layered window and
364 // won't implicitly require painting until we ask for one.
365 SchedulePaint();
366 }
367
368 ////////////////////////////////////////////////////////////////////////////////
369 // AutocompletePopupContentsView, private:
370
371 void AutocompletePopupContentsView::MakeContentsPath(
372 gfx::Path* path,
373 const gfx::Rect& bounding_rect) {
374 SkRect rect;
375 rect.set(SkIntToScalar(bounding_rect.x()),
376 SkIntToScalar(bounding_rect.y()),
377 SkIntToScalar(bounding_rect.right()),
378 SkIntToScalar(bounding_rect.bottom()));
379
380 SkScalar radius = SkIntToScalar(PopupBorder::GetBorderRadius());
381 path->addRoundRect(rect, radius, radius);
382 }
383
384 void AutocompletePopupContentsView::UpdateBlurRegion() {
385 // Provide a blurred background effect within the contents region of the
386 // popup.
387 DWM_BLURBEHIND bb = {0};
388 bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
389 bb.fEnable = true;
390
391 // Translate the contents rect into widget coordinates, since that's what
392 // DwmEnableBlurBehindWindow expects a region in.
393 gfx::Rect contents_rect = GetLocalBounds(false);
394 gfx::Point origin(contents_rect.origin());
395 views::View::ConvertPointToWidget(this, &origin);
396 contents_rect.set_origin(origin);
397
398 gfx::Path contents_path;
399 MakeContentsPath(&contents_path, contents_rect);
400 ScopedGDIObject<HRGN> popup_region;
401 popup_region.Set(contents_path.CreateHRGN());
402 bb.hRgnBlur = popup_region.Get();
403 DwmEnableBlurBehindWindow(GetWidget()->GetNativeView(), &bb);
404 }
405
406 void AutocompletePopupContentsView::MakeCanvasTransparent(
407 ChromeCanvas* canvas) {
408 // Allow the window blur effect to show through the popup background.
409 SkPaint paint;
410 paint.setColor(SkColorSetARGB(kPopupTransparency, 255, 255, 255));
411 paint.setPorterDuffXfermode(SkPorterDuff::kDstIn_Mode);
412 paint.setStyle(SkPaint::kFill_Style);
413 canvas->FillRectInt(0, 0, canvas->getDevice()->width(),
414 canvas->getDevice()->height(), paint);
415 }
416
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698