OLD | NEW |
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 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.
h" | 5 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.
h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <commctrl.h> | 8 #include <commctrl.h> |
9 #include <dwmapi.h> | 9 #include <dwmapi.h> |
10 #include <objidl.h> | 10 #include <objidl.h> |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "base/win/scoped_gdi_object.h" | 42 #include "base/win/scoped_gdi_object.h" |
43 #if !defined(USE_AURA) | 43 #if !defined(USE_AURA) |
44 #include "ui/views/widget/native_widget_win.h" | 44 #include "ui/views/widget/native_widget_win.h" |
45 #endif | 45 #endif |
46 #endif | 46 #endif |
47 | 47 |
48 namespace { | 48 namespace { |
49 | 49 |
50 const SkAlpha kGlassPopupAlpha = 240; | 50 const SkAlpha kGlassPopupAlpha = 240; |
51 const SkAlpha kOpaquePopupAlpha = 255; | 51 const SkAlpha kOpaquePopupAlpha = 255; |
| 52 |
52 // The size delta between the font used for the edit and the result rows. Passed | 53 // The size delta between the font used for the edit and the result rows. Passed |
53 // to gfx::Font::DeriveFont. | 54 // to gfx::Font::DeriveFont. |
54 #if defined(OS_CHROMEOS) | 55 #if defined(OS_CHROMEOS) |
55 // Don't adjust the size on Chrome OS (http://crbug.com/61433). | 56 // Don't adjust the size on Chrome OS (http://crbug.com/61433). |
56 const int kEditFontAdjust = 0; | 57 const int kEditFontAdjust = 0; |
57 #else | 58 #else |
58 const int kEditFontAdjust = -1; | 59 const int kEditFontAdjust = -1; |
59 #endif | 60 #endif |
60 | 61 |
61 // Horizontal padding between the buttons on the opt in promo. | 62 // Horizontal padding between the buttons on the opt in promo. |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { | 226 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { |
226 // The following little dance is required because set_border() requires a | 227 // The following little dance is required because set_border() requires a |
227 // pointer to a non-const object. | 228 // pointer to a non-const object. |
228 views::BubbleBorder* bubble_border = | 229 views::BubbleBorder* bubble_border = |
229 new views::BubbleBorder(views::BubbleBorder::NONE, | 230 new views::BubbleBorder(views::BubbleBorder::NONE, |
230 views::BubbleBorder::NO_SHADOW); | 231 views::BubbleBorder::NO_SHADOW); |
231 bubble_border_ = bubble_border; | 232 bubble_border_ = bubble_border; |
232 set_border(bubble_border); | 233 set_border(bubble_border); |
233 // The contents is owned by the LocationBarView. | 234 // The contents is owned by the LocationBarView. |
234 set_parent_owned(false); | 235 set_parent_owned(false); |
| 236 |
| 237 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { |
| 238 AutocompleteResultView* result_view = |
| 239 CreateResultView(this, i, result_font_, result_bold_font_); |
| 240 result_view->SetVisible(false); |
| 241 AddChildViewAt(result_view, static_cast<int>(i)); |
| 242 } |
235 } | 243 } |
236 | 244 |
237 AutocompletePopupContentsView::~AutocompletePopupContentsView() { | 245 AutocompletePopupContentsView::~AutocompletePopupContentsView() { |
238 // We don't need to do anything with |popup_| here. The OS either has already | 246 // We don't need to do anything with |popup_| here. The OS either has already |
239 // closed the window, in which case it's been deleted, or it will soon, in | 247 // closed the window, in which case it's been deleted, or it will soon, in |
240 // which case there's nothing we need to do. | 248 // which case there's nothing we need to do. |
241 } | 249 } |
242 | 250 |
243 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { | 251 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { |
244 if (!size_animation_.is_animating()) | 252 if (!size_animation_.is_animating()) |
(...skipping 25 matching lines...) Expand all Loading... |
270 } | 278 } |
271 | 279 |
272 //////////////////////////////////////////////////////////////////////////////// | 280 //////////////////////////////////////////////////////////////////////////////// |
273 // AutocompletePopupContentsView, AutocompletePopupView overrides: | 281 // AutocompletePopupContentsView, AutocompletePopupView overrides: |
274 | 282 |
275 bool AutocompletePopupContentsView::IsOpen() const { | 283 bool AutocompletePopupContentsView::IsOpen() const { |
276 return (popup_ != NULL); | 284 return (popup_ != NULL); |
277 } | 285 } |
278 | 286 |
279 void AutocompletePopupContentsView::InvalidateLine(size_t line) { | 287 void AutocompletePopupContentsView::InvalidateLine(size_t line) { |
280 child_at(static_cast<int>(line))->SchedulePaint(); | 288 AutocompleteResultView* result = static_cast<AutocompleteResultView*>( |
| 289 child_at(static_cast<int>(line))); |
| 290 result->Invalidate(); |
| 291 |
| 292 if (HasMatchAt(line) && GetMatchAtIndex(line).associated_keyword.get()) { |
| 293 result->ShowKeyword(IsSelectedIndex(line) && |
| 294 model_->selected_line_state() == AutocompletePopupModel::KEYWORD); |
| 295 } |
281 } | 296 } |
282 | 297 |
283 void AutocompletePopupContentsView::UpdatePopupAppearance() { | 298 void AutocompletePopupContentsView::UpdatePopupAppearance() { |
284 if (model_->result().empty()) { | 299 if (model_->result().empty()) { |
285 // No matches, close any existing popup. | 300 // No matches, close any existing popup. |
286 if (popup_ != NULL) { | 301 if (popup_ != NULL) { |
287 size_animation_.Stop(); | 302 size_animation_.Stop(); |
| 303 |
288 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack | 304 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack |
289 // triggered by the popup receiving a message (e.g. LBUTTONUP), and | 305 // triggered by the popup receiving a message (e.g. LBUTTONUP), and |
290 // destroying the popup would cause us to read garbage when we unwind back | 306 // destroying the popup would cause us to read garbage when we unwind back |
291 // to that level. | 307 // to that level. |
292 popup_->Close(); // This will eventually delete the popup. | 308 popup_->Close(); // This will eventually delete the popup. |
293 popup_.reset(); | 309 popup_.reset(); |
294 } | 310 } |
295 return; | 311 return; |
296 } | 312 } |
297 | 313 |
298 // Update the match cached by each row, in the process of doing so make sure | 314 // Update the match cached by each row, in the process of doing so make sure |
299 // we have enough row views. | 315 // we have enough row views. |
300 size_t child_rv_count = child_count(); | 316 size_t child_rv_count = child_count(); |
301 if (opt_in_view_) { | 317 if (opt_in_view_) { |
302 DCHECK_GT(child_rv_count, 0u); | 318 DCHECK_GT(child_rv_count, 0u); |
303 child_rv_count--; | 319 child_rv_count--; |
304 } | 320 } |
305 for (size_t i = 0; i < model_->result().size(); ++i) { | 321 const size_t result_size = model_->result().size(); |
306 AutocompleteResultView* result_view; | 322 for (size_t i = 0; i < result_size; ++i) { |
307 if (i >= child_rv_count) { | 323 AutocompleteResultView* view = static_cast<AutocompleteResultView*>( |
308 result_view = | 324 child_at(i)); |
309 CreateResultView(this, i, result_font_, result_bold_font_); | 325 view->SetMatch(GetMatchAtIndex(i)); |
310 AddChildViewAt(result_view, static_cast<int>(i)); | 326 view->SetVisible(true); |
311 } else { | |
312 result_view = static_cast<AutocompleteResultView*>(child_at(i)); | |
313 result_view->SetVisible(true); | |
314 } | |
315 result_view->SetMatch(GetMatchAtIndex(i)); | |
316 } | 327 } |
317 for (size_t i = model_->result().size(); i < child_rv_count; ++i) | 328 for (size_t i = result_size; i < child_rv_count; ++i) |
318 child_at(i)->SetVisible(false); | 329 child_at(i)->SetVisible(false); |
319 | 330 |
320 PromoCounter* counter = profile_->GetInstantPromoCounter(); | 331 PromoCounter* counter = profile_->GetInstantPromoCounter(); |
321 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { | 332 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { |
322 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); | 333 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); |
323 AddChildView(opt_in_view_); | 334 AddChildView(opt_in_view_); |
324 } else if (opt_in_view_ && (!counter || | 335 } else if (opt_in_view_ && (!counter || |
325 !counter->ShouldShow(base::Time::Now()))) { | 336 !counter->ShouldShow(base::Time::Now()))) { |
326 delete opt_in_view_; | 337 delete opt_in_view_; |
327 opt_in_view_ = NULL; | 338 opt_in_view_ = NULL; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } | 390 } |
380 | 391 |
381 void AutocompletePopupContentsView::OnDragCanceled() { | 392 void AutocompletePopupContentsView::OnDragCanceled() { |
382 ignore_mouse_drag_ = true; | 393 ignore_mouse_drag_ = true; |
383 } | 394 } |
384 | 395 |
385 //////////////////////////////////////////////////////////////////////////////// | 396 //////////////////////////////////////////////////////////////////////////////// |
386 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: | 397 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: |
387 | 398 |
388 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { | 399 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { |
389 return HasMatchAt(index) ? index == model_->selected_line() : false; | 400 return index == model_->selected_line(); |
390 } | 401 } |
391 | 402 |
392 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { | 403 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { |
393 return HasMatchAt(index) ? index == model_->hovered_line() : false; | 404 return index == model_->hovered_line(); |
394 } | 405 } |
395 | 406 |
396 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( | 407 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( |
397 size_t index) const { | 408 size_t index) const { |
398 if (!HasMatchAt(index)) | 409 if (!HasMatchAt(index)) |
399 return NULL; | 410 return NULL; |
400 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); | 411 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); |
401 } | 412 } |
402 | 413 |
403 //////////////////////////////////////////////////////////////////////////////// | 414 //////////////////////////////////////////////////////////////////////////////// |
(...skipping 15 matching lines...) Expand all Loading... |
419 // Size our children to the available content area. | 430 // Size our children to the available content area. |
420 LayoutChildren(); | 431 LayoutChildren(); |
421 | 432 |
422 // We need to manually schedule a paint here since we are a layered window and | 433 // We need to manually schedule a paint here since we are a layered window and |
423 // won't implicitly require painting until we ask for one. | 434 // won't implicitly require painting until we ask for one. |
424 SchedulePaint(); | 435 SchedulePaint(); |
425 } | 436 } |
426 | 437 |
427 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( | 438 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( |
428 const gfx::Point& point) { | 439 const gfx::Point& point) { |
429 // If there is no opt in view, then we want all mouse events. Otherwise let | 440 // If there is no opt in view then we want all mouse events. Otherwise, let |
430 // any descendants of the opt-in view get mouse events. | 441 // any descendants of the opt-in view get mouse events. |
431 if (!opt_in_view_) | 442 if (!opt_in_view_) |
432 return this; | 443 return this; |
433 | 444 |
434 views::View* child = views::View::GetEventHandlerForPoint(point); | 445 views::View* child = views::View::GetEventHandlerForPoint(point); |
435 views::View* ancestor = child; | 446 views::View* ancestor = child; |
436 while (ancestor && ancestor != opt_in_view_) | 447 while (ancestor && ancestor != opt_in_view_) |
437 ancestor = ancestor->parent(); | 448 ancestor = ancestor->parent(); |
438 return ancestor ? child : this; | 449 return ancestor ? child : this; |
439 } | 450 } |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 void AutocompletePopupContentsView::OpenIndex( | 641 void AutocompletePopupContentsView::OpenIndex( |
631 size_t index, | 642 size_t index, |
632 WindowOpenDisposition disposition) { | 643 WindowOpenDisposition disposition) { |
633 if (!HasMatchAt(index)) | 644 if (!HasMatchAt(index)) |
634 return; | 645 return; |
635 | 646 |
636 // OpenMatch() may close the popup, which will clear the result set and, by | 647 // OpenMatch() may close the popup, which will clear the result set and, by |
637 // extension, |match| and its contents. So copy the relevant match out to | 648 // extension, |match| and its contents. So copy the relevant match out to |
638 // make sure it stays alive until the call completes. | 649 // make sure it stays alive until the call completes. |
639 AutocompleteMatch match = model_->result().match_at(index); | 650 AutocompleteMatch match = model_->result().match_at(index); |
640 string16 keyword; | |
641 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); | |
642 omnibox_view_->OpenMatch(match, disposition, GURL(), index, | 651 omnibox_view_->OpenMatch(match, disposition, GURL(), index, |
643 is_keyword_hint ? string16() : keyword); | 652 match.keyword); |
644 } | 653 } |
645 | 654 |
646 size_t AutocompletePopupContentsView::GetIndexForPoint( | 655 size_t AutocompletePopupContentsView::GetIndexForPoint( |
647 const gfx::Point& point) { | 656 const gfx::Point& point) { |
648 if (!HitTest(point)) | 657 if (!HitTest(point)) |
649 return AutocompletePopupModel::kNoMatch; | 658 return AutocompletePopupModel::kNoMatch; |
650 | 659 |
651 int nb_match = model_->result().size(); | 660 int nb_match = model_->result().size(); |
652 DCHECK(nb_match <= child_count()); | 661 DCHECK(nb_match <= child_count()); |
653 for (int i = 0; i < nb_match; ++i) { | 662 for (int i = 0; i < nb_match; ++i) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 opt_in_view_ = NULL; | 697 opt_in_view_ = NULL; |
689 PromoCounter* counter = profile_->GetInstantPromoCounter(); | 698 PromoCounter* counter = profile_->GetInstantPromoCounter(); |
690 DCHECK(counter); | 699 DCHECK(counter); |
691 counter->Hide(); | 700 counter->Hide(); |
692 if (opt_in) { | 701 if (opt_in) { |
693 browser::ShowInstantConfirmDialogIfNecessary( | 702 browser::ShowInstantConfirmDialogIfNecessary( |
694 location_bar_->GetWidget()->GetNativeWindow(), profile_); | 703 location_bar_->GetWidget()->GetNativeWindow(), profile_); |
695 } | 704 } |
696 UpdatePopupAppearance(); | 705 UpdatePopupAppearance(); |
697 } | 706 } |
OLD | NEW |