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