OLD | NEW |
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 #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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 #endif | 46 #endif |
47 #endif | 47 #endif |
48 #if defined(USE_AURA) | 48 #if defined(USE_AURA) |
49 #include "ash/wm/window_animations.h" | 49 #include "ash/wm/window_animations.h" |
50 #endif | 50 #endif |
51 | 51 |
52 namespace { | 52 namespace { |
53 | 53 |
54 const SkAlpha kGlassPopupAlpha = 240; | 54 const SkAlpha kGlassPopupAlpha = 240; |
55 const SkAlpha kOpaquePopupAlpha = 255; | 55 const SkAlpha kOpaquePopupAlpha = 255; |
56 | |
57 // The size delta between the font used for the edit and the result rows. Passed | 56 // The size delta between the font used for the edit and the result rows. Passed |
58 // to gfx::Font::DeriveFont. | 57 // to gfx::Font::DeriveFont. |
59 #if defined(OS_CHROMEOS) | 58 #if defined(OS_CHROMEOS) |
60 // Don't adjust the size on Chrome OS (http://crbug.com/61433). | 59 // Don't adjust the size on Chrome OS (http://crbug.com/61433). |
61 const int kEditFontAdjust = 0; | 60 const int kEditFontAdjust = 0; |
62 #else | 61 #else |
63 const int kEditFontAdjust = -1; | 62 const int kEditFontAdjust = -1; |
64 #endif | 63 #endif |
65 | 64 |
66 // Horizontal padding between the buttons on the opt in promo. | 65 // Horizontal padding between the buttons on the opt in promo. |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { | 230 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { |
232 // The following little dance is required because set_border() requires a | 231 // The following little dance is required because set_border() requires a |
233 // pointer to a non-const object. | 232 // pointer to a non-const object. |
234 views::BubbleBorder* bubble_border = | 233 views::BubbleBorder* bubble_border = |
235 new views::BubbleBorder(views::BubbleBorder::NONE, | 234 new views::BubbleBorder(views::BubbleBorder::NONE, |
236 views::BubbleBorder::NO_SHADOW); | 235 views::BubbleBorder::NO_SHADOW); |
237 bubble_border_ = bubble_border; | 236 bubble_border_ = bubble_border; |
238 set_border(bubble_border); | 237 set_border(bubble_border); |
239 // The contents is owned by the LocationBarView. | 238 // The contents is owned by the LocationBarView. |
240 set_parent_owned(false); | 239 set_parent_owned(false); |
241 | |
242 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { | |
243 AutocompleteResultView* result_view = | |
244 CreateResultView(this, i, result_font_, result_bold_font_); | |
245 result_view->SetVisible(false); | |
246 AddChildViewAt(result_view, static_cast<int>(i)); | |
247 } | |
248 } | 240 } |
249 | 241 |
250 AutocompletePopupContentsView::~AutocompletePopupContentsView() { | 242 AutocompletePopupContentsView::~AutocompletePopupContentsView() { |
251 // We don't need to do anything with |popup_| here. The OS either has already | 243 // We don't need to do anything with |popup_| here. The OS either has already |
252 // closed the window, in which case it's been deleted, or it will soon, in | 244 // closed the window, in which case it's been deleted, or it will soon, in |
253 // which case there's nothing we need to do. | 245 // which case there's nothing we need to do. |
254 } | 246 } |
255 | 247 |
256 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { | 248 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { |
257 if (!size_animation_.is_animating()) | 249 if (!size_animation_.is_animating()) |
(...skipping 25 matching lines...) Expand all Loading... |
283 } | 275 } |
284 | 276 |
285 //////////////////////////////////////////////////////////////////////////////// | 277 //////////////////////////////////////////////////////////////////////////////// |
286 // AutocompletePopupContentsView, AutocompletePopupView overrides: | 278 // AutocompletePopupContentsView, AutocompletePopupView overrides: |
287 | 279 |
288 bool AutocompletePopupContentsView::IsOpen() const { | 280 bool AutocompletePopupContentsView::IsOpen() const { |
289 return (popup_ != NULL); | 281 return (popup_ != NULL); |
290 } | 282 } |
291 | 283 |
292 void AutocompletePopupContentsView::InvalidateLine(size_t line) { | 284 void AutocompletePopupContentsView::InvalidateLine(size_t line) { |
293 AutocompleteResultView* result = static_cast<AutocompleteResultView*>( | 285 child_at(static_cast<int>(line))->SchedulePaint(); |
294 child_at(static_cast<int>(line))); | |
295 result->Invalidate(); | |
296 | |
297 if (HasMatchAt(line) && GetMatchAtIndex(line).associated_keyword.get()) { | |
298 result->ShowKeyword(IsSelectedIndex(line) && | |
299 model_->selected_line_state() == AutocompletePopupModel::KEYWORD); | |
300 } | |
301 } | 286 } |
302 | 287 |
303 void AutocompletePopupContentsView::UpdatePopupAppearance() { | 288 void AutocompletePopupContentsView::UpdatePopupAppearance() { |
304 if (model_->result().empty()) { | 289 if (model_->result().empty()) { |
305 // No matches, close any existing popup. | 290 // No matches, close any existing popup. |
306 if (popup_ != NULL) { | 291 if (popup_ != NULL) { |
307 size_animation_.Stop(); | 292 size_animation_.Stop(); |
308 | |
309 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack | 293 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack |
310 // triggered by the popup receiving a message (e.g. LBUTTONUP), and | 294 // triggered by the popup receiving a message (e.g. LBUTTONUP), and |
311 // destroying the popup would cause us to read garbage when we unwind back | 295 // destroying the popup would cause us to read garbage when we unwind back |
312 // to that level. | 296 // to that level. |
313 popup_->Close(); // This will eventually delete the popup. | 297 popup_->Close(); // This will eventually delete the popup. |
314 popup_.reset(); | 298 popup_.reset(); |
315 } | 299 } |
316 return; | 300 return; |
317 } | 301 } |
318 | 302 |
319 // Update the match cached by each row, in the process of doing so make sure | 303 // Update the match cached by each row, in the process of doing so make sure |
320 // we have enough row views. | 304 // we have enough row views. |
321 size_t child_rv_count = child_count(); | 305 size_t child_rv_count = child_count(); |
322 if (opt_in_view_) { | 306 if (opt_in_view_) { |
323 DCHECK_GT(child_rv_count, 0u); | 307 DCHECK_GT(child_rv_count, 0u); |
324 child_rv_count--; | 308 child_rv_count--; |
325 } | 309 } |
326 const size_t result_size = model_->result().size(); | 310 for (size_t i = 0; i < model_->result().size(); ++i) { |
327 for (size_t i = 0; i < result_size; ++i) { | 311 AutocompleteResultView* result_view; |
328 AutocompleteResultView* view = static_cast<AutocompleteResultView*>( | 312 if (i >= child_rv_count) { |
329 child_at(i)); | 313 result_view = |
330 view->SetMatch(GetMatchAtIndex(i)); | 314 CreateResultView(this, i, result_font_, result_bold_font_); |
331 view->SetVisible(true); | 315 AddChildViewAt(result_view, static_cast<int>(i)); |
| 316 } else { |
| 317 result_view = static_cast<AutocompleteResultView*>(child_at(i)); |
| 318 result_view->SetVisible(true); |
| 319 } |
| 320 result_view->SetMatch(GetMatchAtIndex(i)); |
332 } | 321 } |
333 for (size_t i = result_size; i < child_rv_count; ++i) | 322 for (size_t i = model_->result().size(); i < child_rv_count; ++i) |
334 child_at(i)->SetVisible(false); | 323 child_at(i)->SetVisible(false); |
335 | 324 |
336 PromoCounter* counter = profile_->GetInstantPromoCounter(); | 325 PromoCounter* counter = profile_->GetInstantPromoCounter(); |
337 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { | 326 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { |
338 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); | 327 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); |
339 AddChildView(opt_in_view_); | 328 AddChildView(opt_in_view_); |
340 } else if (opt_in_view_ && (!counter || | 329 } else if (opt_in_view_ && (!counter || |
341 !counter->ShouldShow(base::Time::Now()))) { | 330 !counter->ShouldShow(base::Time::Now()))) { |
342 delete opt_in_view_; | 331 delete opt_in_view_; |
343 opt_in_view_ = NULL; | 332 opt_in_view_ = NULL; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 } | 390 } |
402 | 391 |
403 void AutocompletePopupContentsView::OnDragCanceled() { | 392 void AutocompletePopupContentsView::OnDragCanceled() { |
404 ignore_mouse_drag_ = true; | 393 ignore_mouse_drag_ = true; |
405 } | 394 } |
406 | 395 |
407 //////////////////////////////////////////////////////////////////////////////// | 396 //////////////////////////////////////////////////////////////////////////////// |
408 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: | 397 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: |
409 | 398 |
410 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { | 399 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { |
411 return index == model_->selected_line(); | 400 return HasMatchAt(index) ? index == model_->selected_line() : false; |
412 } | 401 } |
413 | 402 |
414 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { | 403 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { |
415 return index == model_->hovered_line(); | 404 return HasMatchAt(index) ? index == model_->hovered_line() : false; |
416 } | 405 } |
417 | 406 |
418 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( | 407 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( |
419 size_t index) const { | 408 size_t index) const { |
420 if (!HasMatchAt(index)) | 409 if (!HasMatchAt(index)) |
421 return NULL; | 410 return NULL; |
422 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); | 411 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); |
423 } | 412 } |
424 | 413 |
425 //////////////////////////////////////////////////////////////////////////////// | 414 //////////////////////////////////////////////////////////////////////////////// |
(...skipping 15 matching lines...) Expand all Loading... |
441 // Size our children to the available content area. | 430 // Size our children to the available content area. |
442 LayoutChildren(); | 431 LayoutChildren(); |
443 | 432 |
444 // 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 |
445 // won't implicitly require painting until we ask for one. | 434 // won't implicitly require painting until we ask for one. |
446 SchedulePaint(); | 435 SchedulePaint(); |
447 } | 436 } |
448 | 437 |
449 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( | 438 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( |
450 const gfx::Point& point) { | 439 const gfx::Point& point) { |
451 // 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 |
452 // any descendants of the opt-in view get mouse events. | 441 // any descendants of the opt-in view get mouse events. |
453 if (!opt_in_view_) | 442 if (!opt_in_view_) |
454 return this; | 443 return this; |
455 | 444 |
456 views::View* child = views::View::GetEventHandlerForPoint(point); | 445 views::View* child = views::View::GetEventHandlerForPoint(point); |
457 views::View* ancestor = child; | 446 views::View* ancestor = child; |
458 while (ancestor && ancestor != opt_in_view_) | 447 while (ancestor && ancestor != opt_in_view_) |
459 ancestor = ancestor->parent(); | 448 ancestor = ancestor->parent(); |
460 return ancestor ? child : this; | 449 return ancestor ? child : this; |
461 } | 450 } |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 void AutocompletePopupContentsView::OpenIndex( | 641 void AutocompletePopupContentsView::OpenIndex( |
653 size_t index, | 642 size_t index, |
654 WindowOpenDisposition disposition) { | 643 WindowOpenDisposition disposition) { |
655 if (!HasMatchAt(index)) | 644 if (!HasMatchAt(index)) |
656 return; | 645 return; |
657 | 646 |
658 // 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 |
659 // 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 |
660 // make sure it stays alive until the call completes. | 649 // make sure it stays alive until the call completes. |
661 AutocompleteMatch match = model_->result().match_at(index); | 650 AutocompleteMatch match = model_->result().match_at(index); |
| 651 string16 keyword; |
| 652 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); |
662 omnibox_view_->OpenMatch(match, disposition, GURL(), index, | 653 omnibox_view_->OpenMatch(match, disposition, GURL(), index, |
663 match.keyword); | 654 is_keyword_hint ? string16() : keyword); |
664 } | 655 } |
665 | 656 |
666 size_t AutocompletePopupContentsView::GetIndexForPoint( | 657 size_t AutocompletePopupContentsView::GetIndexForPoint( |
667 const gfx::Point& point) { | 658 const gfx::Point& point) { |
668 if (!HitTest(point)) | 659 if (!HitTest(point)) |
669 return AutocompletePopupModel::kNoMatch; | 660 return AutocompletePopupModel::kNoMatch; |
670 | 661 |
671 int nb_match = model_->result().size(); | 662 int nb_match = model_->result().size(); |
672 DCHECK(nb_match <= child_count()); | 663 DCHECK(nb_match <= child_count()); |
673 for (int i = 0; i < nb_match; ++i) { | 664 for (int i = 0; i < nb_match; ++i) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 opt_in_view_ = NULL; | 699 opt_in_view_ = NULL; |
709 PromoCounter* counter = profile_->GetInstantPromoCounter(); | 700 PromoCounter* counter = profile_->GetInstantPromoCounter(); |
710 DCHECK(counter); | 701 DCHECK(counter); |
711 counter->Hide(); | 702 counter->Hide(); |
712 if (opt_in) { | 703 if (opt_in) { |
713 browser::ShowInstantConfirmDialogIfNecessary( | 704 browser::ShowInstantConfirmDialogIfNecessary( |
714 location_bar_->GetWidget()->GetNativeWindow(), profile_); | 705 location_bar_->GetWidget()->GetNativeWindow(), profile_); |
715 } | 706 } |
716 UpdatePopupAppearance(); | 707 UpdatePopupAppearance(); |
717 } | 708 } |
OLD | NEW |