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