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