Chromium Code Reviews| 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 "views/widget/native_widget_win.h" | 44 #include "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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 ignore_mouse_drag_(false), | 225 ignore_mouse_drag_(false), |
| 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 bubble_border_ = bubble_border; | 231 bubble_border_ = bubble_border; |
| 231 set_border(bubble_border); | 232 set_border(bubble_border); |
| 232 // The contents is owned by the LocationBarView. | 233 // The contents is owned by the LocationBarView. |
| 233 set_parent_owned(false); | 234 set_parent_owned(false); |
| 235 | |
| 236 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { | |
| 237 AutocompleteResultView* result_view = | |
| 238 CreateResultView(this, i, result_font_, result_bold_font_); | |
| 239 result_view->SetVisible(false); | |
| 240 result_view->set_popup_model(model_.get()); | |
| 241 AddChildViewAt(result_view, static_cast<int>(i)); | |
| 242 } | |
| 234 } | 243 } |
| 235 | 244 |
| 236 AutocompletePopupContentsView::~AutocompletePopupContentsView() { | 245 AutocompletePopupContentsView::~AutocompletePopupContentsView() { |
| 237 // 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 |
| 238 // 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 |
| 239 // which case there's nothing we need to do. | 248 // which case there's nothing we need to do. |
| 240 } | 249 } |
| 241 | 250 |
| 242 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { | 251 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { |
| 243 if (!size_animation_.is_animating()) | 252 if (!size_animation_.is_animating()) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 255 return current_frame_bounds; | 264 return current_frame_bounds; |
| 256 } | 265 } |
| 257 | 266 |
| 258 void AutocompletePopupContentsView::LayoutChildren() { | 267 void AutocompletePopupContentsView::LayoutChildren() { |
| 259 gfx::Rect contents_rect = GetContentsBounds(); | 268 gfx::Rect contents_rect = GetContentsBounds(); |
| 260 int top = contents_rect.y(); | 269 int top = contents_rect.y(); |
| 261 for (int i = 0; i < child_count(); ++i) { | 270 for (int i = 0; i < child_count(); ++i) { |
| 262 View* v = child_at(i); | 271 View* v = child_at(i); |
| 263 if (v->IsVisible()) { | 272 if (v->IsVisible()) { |
| 264 v->SetBounds(contents_rect.x(), top, contents_rect.width(), | 273 v->SetBounds(contents_rect.x(), top, contents_rect.width(), |
| 265 v->GetPreferredSize().height()); | 274 v->GetPreferredSize().height()); |
|
Peter Kasting
2011/12/15 22:56:04
Nit: This indentation was fine.
| |
| 266 top = v->bounds().bottom(); | 275 top = v->bounds().bottom(); |
| 267 } | 276 } |
| 268 } | 277 } |
| 269 } | 278 } |
| 270 | 279 |
| 271 //////////////////////////////////////////////////////////////////////////////// | 280 //////////////////////////////////////////////////////////////////////////////// |
| 272 // AutocompletePopupContentsView, AutocompletePopupView overrides: | 281 // AutocompletePopupContentsView, AutocompletePopupView overrides: |
| 273 | 282 |
| 274 bool AutocompletePopupContentsView::IsOpen() const { | 283 bool AutocompletePopupContentsView::IsOpen() const { |
| 275 return (popup_ != NULL); | 284 return (popup_ != NULL); |
| 276 } | 285 } |
| 277 | 286 |
| 278 void AutocompletePopupContentsView::InvalidateLine(size_t line) { | 287 void AutocompletePopupContentsView::InvalidateLine(size_t line) { |
| 279 child_at(static_cast<int>(line))->SchedulePaint(); | 288 AutocompleteResultView* result = static_cast<AutocompleteResultView*>( |
| 289 child_at(static_cast<int>(line))); | |
| 290 result->SchedulePaint(); | |
| 291 | |
| 292 if (HasMatchAt(line) && GetMatchAtIndex(line).associated_keyword.get()) | |
| 293 result->ShowKeyword( | |
| 294 model_->selected_line_state() == AutocompletePopupModel::KEYWORD); | |
| 280 } | 295 } |
| 281 | 296 |
| 282 void AutocompletePopupContentsView::UpdatePopupAppearance() { | 297 void AutocompletePopupContentsView::UpdatePopupAppearance() { |
| 283 if (model_->result().empty()) { | 298 if (model_->result().empty()) { |
| 284 // No matches, close any existing popup. | 299 // No matches, close any existing popup. |
| 285 if (popup_ != NULL) { | 300 if (popup_ != NULL) { |
| 286 size_animation_.Stop(); | 301 size_animation_.Stop(); |
| 302 | |
| 287 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack | 303 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack |
| 288 // triggered by the popup receiving a message (e.g. LBUTTONUP), and | 304 // triggered by the popup receiving a message (e.g. LBUTTONUP), and |
| 289 // destroying the popup would cause us to read garbage when we unwind back | 305 // destroying the popup would cause us to read garbage when we unwind back |
| 290 // to that level. | 306 // to that level. |
| 291 popup_->Close(); // This will eventually delete the popup. | 307 popup_->Close(); // This will eventually delete the popup. |
| 292 popup_.reset(); | 308 popup_.reset(); |
| 293 } | 309 } |
| 294 return; | 310 return; |
| 295 } | 311 } |
| 296 | 312 |
| 297 // Update the match cached by each row, in the process of doing so make sure | 313 // Update the match cached by each row, in the process of doing so make sure |
| 298 // we have enough row views. | 314 // we have enough row views. |
| 299 size_t child_rv_count = child_count(); | 315 size_t child_rv_count = child_count(); |
| 300 if (opt_in_view_) { | 316 if (opt_in_view_) { |
| 301 DCHECK_GT(child_rv_count, 0u); | 317 DCHECK_GT(child_rv_count, 0u); |
| 302 child_rv_count--; | 318 child_rv_count--; |
| 303 } | 319 } |
| 304 for (size_t i = 0; i < model_->result().size(); ++i) { | 320 const size_t result_size = model_->result().size(); |
| 305 AutocompleteResultView* result_view; | 321 for (size_t i = 0; i < result_size; ++i) { |
| 306 if (i >= child_rv_count) { | 322 const AutocompleteMatch& match = GetMatchAtIndex(i); |
| 307 result_view = | 323 AutocompleteResultView* view = static_cast<AutocompleteResultView*>( |
| 308 CreateResultView(this, i, result_font_, result_bold_font_); | 324 child_at(i)); |
| 309 AddChildViewAt(result_view, static_cast<int>(i)); | 325 view->SetMatch(match); |
| 310 } else { | 326 view->SetVisible(true); |
| 311 result_view = static_cast<AutocompleteResultView*>(child_at(i)); | |
| 312 result_view->SetVisible(true); | |
| 313 } | |
| 314 result_view->SetMatch(GetMatchAtIndex(i)); | |
| 315 } | 327 } |
| 316 for (size_t i = model_->result().size(); i < child_rv_count; ++i) | 328 for (size_t i = result_size; i < child_rv_count; ++i) |
| 317 child_at(i)->SetVisible(false); | 329 child_at(i)->SetVisible(false); |
| 318 | 330 |
| 319 PromoCounter* counter = profile_->GetInstantPromoCounter(); | 331 PromoCounter* counter = profile_->GetInstantPromoCounter(); |
| 320 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { | 332 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { |
| 321 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); | 333 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); |
| 322 AddChildView(opt_in_view_); | 334 AddChildView(opt_in_view_); |
| 323 } else if (opt_in_view_ && (!counter || | 335 } else if (opt_in_view_ && (!counter || |
| 324 !counter->ShouldShow(base::Time::Now()))) { | 336 !counter->ShouldShow(base::Time::Now()))) { |
| 325 delete opt_in_view_; | 337 delete opt_in_view_; |
| 326 opt_in_view_ = NULL; | 338 opt_in_view_ = NULL; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 } | 390 } |
| 379 | 391 |
| 380 void AutocompletePopupContentsView::OnDragCanceled() { | 392 void AutocompletePopupContentsView::OnDragCanceled() { |
| 381 ignore_mouse_drag_ = true; | 393 ignore_mouse_drag_ = true; |
| 382 } | 394 } |
| 383 | 395 |
| 384 //////////////////////////////////////////////////////////////////////////////// | 396 //////////////////////////////////////////////////////////////////////////////// |
| 385 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: | 397 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: |
| 386 | 398 |
| 387 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { | 399 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { |
| 388 return HasMatchAt(index) ? index == model_->selected_line() : false; | 400 return index == model_->selected_line(); |
| 389 } | 401 } |
| 390 | 402 |
| 391 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { | 403 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { |
| 392 return HasMatchAt(index) ? index == model_->hovered_line() : false; | 404 return index == model_->hovered_line(); |
| 393 } | 405 } |
| 394 | 406 |
| 395 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( | 407 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( |
| 396 size_t index) const { | 408 size_t index) const { |
| 397 if (!HasMatchAt(index)) | 409 if (!HasMatchAt(index)) |
| 398 return NULL; | 410 return NULL; |
| 399 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); | 411 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); |
| 400 } | 412 } |
| 401 | 413 |
| 402 //////////////////////////////////////////////////////////////////////////////// | 414 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 418 // Size our children to the available content area. | 430 // Size our children to the available content area. |
| 419 LayoutChildren(); | 431 LayoutChildren(); |
| 420 | 432 |
| 421 // 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 |
| 422 // won't implicitly require painting until we ask for one. | 434 // won't implicitly require painting until we ask for one. |
| 423 SchedulePaint(); | 435 SchedulePaint(); |
| 424 } | 436 } |
| 425 | 437 |
| 426 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( | 438 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( |
| 427 const gfx::Point& point) { | 439 const gfx::Point& point) { |
| 428 // If there is no opt in view, then we want all mouse events. Otherwise let | 440 views::View* child = views::View::GetEventHandlerForPoint(point); |
| 429 // any descendants of the opt-in view get mouse events. | 441 |
| 430 if (!opt_in_view_) | 442 // If there is no opt in view, and the mouse isn't over a keyword button, |
| 443 // then we want all mouse events. Otherwise let any descendants of the | |
| 444 // opt-in view get mouse events. | |
| 445 if (child->id() == AutocompleteResultView::VIEW_ID_KEYWORD) | |
| 446 return child; | |
| 447 else if (!opt_in_view_) | |
|
Peter Kasting
2011/12/15 22:56:04
Nit: No else after return
| |
| 431 return this; | 448 return this; |
| 432 | 449 |
| 433 views::View* child = views::View::GetEventHandlerForPoint(point); | |
| 434 views::View* ancestor = child; | 450 views::View* ancestor = child; |
| 435 while (ancestor && ancestor != opt_in_view_) | 451 while (ancestor && ancestor != opt_in_view_) |
| 436 ancestor = ancestor->parent(); | 452 ancestor = ancestor->parent(); |
| 437 return ancestor ? child : this; | 453 return ancestor ? child : this; |
| 438 } | 454 } |
| 439 | 455 |
| 440 bool AutocompletePopupContentsView::OnMousePressed( | 456 bool AutocompletePopupContentsView::OnMousePressed( |
| 441 const views::MouseEvent& event) { | 457 const views::MouseEvent& event) { |
| 442 ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header. | 458 ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header. |
| 443 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) { | 459 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 629 void AutocompletePopupContentsView::OpenIndex( | 645 void AutocompletePopupContentsView::OpenIndex( |
| 630 size_t index, | 646 size_t index, |
| 631 WindowOpenDisposition disposition) { | 647 WindowOpenDisposition disposition) { |
| 632 if (!HasMatchAt(index)) | 648 if (!HasMatchAt(index)) |
| 633 return; | 649 return; |
| 634 | 650 |
| 635 // OpenMatch() may close the popup, which will clear the result set and, by | 651 // OpenMatch() may close the popup, which will clear the result set and, by |
| 636 // extension, |match| and its contents. So copy the relevant match out to | 652 // extension, |match| and its contents. So copy the relevant match out to |
| 637 // make sure it stays alive until the call completes. | 653 // make sure it stays alive until the call completes. |
| 638 AutocompleteMatch match = model_->result().match_at(index); | 654 AutocompleteMatch match = model_->result().match_at(index); |
| 639 string16 keyword; | |
| 640 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); | |
| 641 omnibox_view_->OpenMatch(match, disposition, GURL(), index, | 655 omnibox_view_->OpenMatch(match, disposition, GURL(), index, |
| 642 is_keyword_hint ? string16() : keyword); | 656 match.keyword); |
| 643 } | 657 } |
| 644 | 658 |
| 645 size_t AutocompletePopupContentsView::GetIndexForPoint( | 659 size_t AutocompletePopupContentsView::GetIndexForPoint( |
| 646 const gfx::Point& point) { | 660 const gfx::Point& point) { |
| 647 if (!HitTest(point)) | 661 if (!HitTest(point)) |
| 648 return AutocompletePopupModel::kNoMatch; | 662 return AutocompletePopupModel::kNoMatch; |
| 649 | 663 |
| 650 int nb_match = model_->result().size(); | 664 int nb_match = model_->result().size(); |
| 651 DCHECK(nb_match <= child_count()); | 665 DCHECK(nb_match <= child_count()); |
| 652 for (int i = 0; i < nb_match; ++i) { | 666 for (int i = 0; i < nb_match; ++i) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 opt_in_view_ = NULL; | 701 opt_in_view_ = NULL; |
| 688 PromoCounter* counter = profile_->GetInstantPromoCounter(); | 702 PromoCounter* counter = profile_->GetInstantPromoCounter(); |
| 689 DCHECK(counter); | 703 DCHECK(counter); |
| 690 counter->Hide(); | 704 counter->Hide(); |
| 691 if (opt_in) { | 705 if (opt_in) { |
| 692 browser::ShowInstantConfirmDialogIfNecessary( | 706 browser::ShowInstantConfirmDialogIfNecessary( |
| 693 location_bar_->GetWidget()->GetNativeWindow(), profile_); | 707 location_bar_->GetWidget()->GetNativeWindow(), profile_); |
| 694 } | 708 } |
| 695 UpdatePopupAppearance(); | 709 UpdatePopupAppearance(); |
| 696 } | 710 } |
| OLD | NEW |