| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" | 5 #include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" |
| 6 | 6 |
| 7 #include "app/bidi_line_iterator.h" | 7 #include "app/bidi_line_iterator.h" |
| 8 #include "app/gfx/canvas.h" | 8 #include "app/gfx/canvas.h" |
| 9 #include "app/gfx/color_utils.h" | 9 #include "app/gfx/color_utils.h" |
| 10 #include "app/gfx/insets.h" | 10 #include "app/gfx/insets.h" |
| 11 #include "app/gfx/path.h" | 11 #include "app/gfx/path.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 117 |
| 118 // Updates the match used to paint the contents of this result view. We copy | 118 // Updates the match used to paint the contents of this result view. We copy |
| 119 // the match so that we can continue to paint the last result even after the | 119 // the match so that we can continue to paint the last result even after the |
| 120 // model has changed. | 120 // model has changed. |
| 121 void set_match(const AutocompleteMatch& match) { match_ = match; } | 121 void set_match(const AutocompleteMatch& match) { match_ = match; } |
| 122 | 122 |
| 123 // Overridden from views::View: | 123 // Overridden from views::View: |
| 124 virtual void Paint(gfx::Canvas* canvas); | 124 virtual void Paint(gfx::Canvas* canvas); |
| 125 virtual void Layout(); | 125 virtual void Layout(); |
| 126 virtual gfx::Size GetPreferredSize(); | 126 virtual gfx::Size GetPreferredSize(); |
| 127 virtual void OnMouseEntered(const views::MouseEvent& event); | |
| 128 virtual void OnMouseMoved(const views::MouseEvent& event); | |
| 129 virtual void OnMouseExited(const views::MouseEvent& event); | |
| 130 virtual bool OnMousePressed(const views::MouseEvent& event); | |
| 131 virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); | |
| 132 virtual bool OnMouseDragged(const views::MouseEvent& event); | |
| 133 | 127 |
| 134 private: | 128 private: |
| 135 ResultViewState GetState() const; | 129 ResultViewState GetState() const; |
| 136 | 130 |
| 137 SkBitmap* GetIcon() const; | 131 SkBitmap* GetIcon() const; |
| 138 | 132 |
| 139 // Draws the specified |text| into the canvas, using highlighting provided by | 133 // Draws the specified |text| into the canvas, using highlighting provided by |
| 140 // |classifications|. If |force_dim| is true, ACMatchClassification::DIM is | 134 // |classifications|. If |force_dim| is true, ACMatchClassification::DIM is |
| 141 // added to all of the classifications. Returns the x position to the right | 135 // added to all of the classifications. Returns the x position to the right |
| 142 // of the string. | 136 // of the string. |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 std::max(0, bounds().right() - text_x - kRowRightPadding), | 373 std::max(0, bounds().right() - text_x - kRowRightPadding), |
| 380 font_.height()); | 374 font_.height()); |
| 381 } | 375 } |
| 382 | 376 |
| 383 gfx::Size AutocompleteResultView::GetPreferredSize() { | 377 gfx::Size AutocompleteResultView::GetPreferredSize() { |
| 384 int text_height = font_.height() + 2 * kTextVerticalPadding; | 378 int text_height = font_.height() + 2 * kTextVerticalPadding; |
| 385 int icon_height = icon_size_ + 2 * kIconVerticalPadding; | 379 int icon_height = icon_size_ + 2 * kIconVerticalPadding; |
| 386 return gfx::Size(0, std::max(icon_height, text_height)); | 380 return gfx::Size(0, std::max(icon_height, text_height)); |
| 387 } | 381 } |
| 388 | 382 |
| 389 void AutocompleteResultView::OnMouseEntered(const views::MouseEvent& event) { | |
| 390 model_->SetHoveredLine(model_index_); | |
| 391 } | |
| 392 | |
| 393 void AutocompleteResultView::OnMouseMoved(const views::MouseEvent& event) { | |
| 394 model_->SetHoveredLine(model_index_); | |
| 395 if (event.IsLeftMouseButton()) | |
| 396 model_->SetSelectedLine(model_index_, false); | |
| 397 } | |
| 398 | |
| 399 void AutocompleteResultView::OnMouseExited(const views::MouseEvent& event) { | |
| 400 model_->SetHoveredLine(AutocompletePopupModel::kNoMatch); | |
| 401 } | |
| 402 | |
| 403 bool AutocompleteResultView::OnMousePressed(const views::MouseEvent& event) { | |
| 404 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) { | |
| 405 model_->SetHoveredLine(model_index_); | |
| 406 if (event.IsLeftMouseButton()) | |
| 407 model_->SetSelectedLine(model_index_, false); | |
| 408 } | |
| 409 return true; | |
| 410 } | |
| 411 | |
| 412 void AutocompleteResultView::OnMouseReleased(const views::MouseEvent& event, | |
| 413 bool canceled) { | |
| 414 if (canceled) | |
| 415 return; | |
| 416 if (event.IsOnlyMiddleMouseButton()) | |
| 417 model_->OpenIndex(model_index_, NEW_BACKGROUND_TAB); | |
| 418 else if (event.IsOnlyLeftMouseButton()) | |
| 419 model_->OpenIndex(model_index_, CURRENT_TAB); | |
| 420 } | |
| 421 | |
| 422 bool AutocompleteResultView::OnMouseDragged(const views::MouseEvent& event) { | |
| 423 // TODO(beng): move all message handling into the contents view and override | |
| 424 // GetViewForPoint. | |
| 425 return false; | |
| 426 } | |
| 427 | 383 |
| 428 ResultViewState AutocompleteResultView::GetState() const { | 384 ResultViewState AutocompleteResultView::GetState() const { |
| 429 if (model_->IsSelectedIndex(model_index_)) | 385 if (model_->IsSelectedIndex(model_index_)) |
| 430 return SELECTED; | 386 return SELECTED; |
| 431 return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; | 387 return model_->IsHoveredIndex(model_index_) ? HOVERED : NORMAL; |
| 432 } | 388 } |
| 433 | 389 |
| 434 SkBitmap* AutocompleteResultView::GetIcon() const { | 390 SkBitmap* AutocompleteResultView::GetIcon() const { |
| 435 bool selected = model_->IsSelectedIndex(model_index_); | 391 bool selected = model_->IsSelectedIndex(model_index_); |
| 436 if (match_.starred) | 392 if (match_.starred) |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: | 667 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: |
| 712 | 668 |
| 713 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { | 669 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { |
| 714 return HasMatchAt(index) ? index == model_->selected_line() : false; | 670 return HasMatchAt(index) ? index == model_->selected_line() : false; |
| 715 } | 671 } |
| 716 | 672 |
| 717 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { | 673 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { |
| 718 return HasMatchAt(index) ? index == model_->hovered_line() : false; | 674 return HasMatchAt(index) ? index == model_->hovered_line() : false; |
| 719 } | 675 } |
| 720 | 676 |
| 721 void AutocompletePopupContentsView::OpenIndex( | |
| 722 size_t index, | |
| 723 WindowOpenDisposition disposition) { | |
| 724 if (!HasMatchAt(index)) | |
| 725 return; | |
| 726 | |
| 727 const AutocompleteMatch& match = model_->result().match_at(index); | |
| 728 // OpenURL() may close the popup, which will clear the result set and, by | |
| 729 // extension, |match| and its contents. So copy the relevant strings out to | |
| 730 // make sure they stay alive until the call completes. | |
| 731 const GURL url(match.destination_url); | |
| 732 std::wstring keyword; | |
| 733 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); | |
| 734 edit_view_->OpenURL(url, disposition, match.transition, GURL(), index, | |
| 735 is_keyword_hint ? std::wstring() : keyword); | |
| 736 } | |
| 737 | |
| 738 void AutocompletePopupContentsView::SetHoveredLine(size_t index) { | |
| 739 if (HasMatchAt(index)) | |
| 740 model_->SetHoveredLine(index); | |
| 741 } | |
| 742 | |
| 743 void AutocompletePopupContentsView::SetSelectedLine(size_t index, | |
| 744 bool revert_to_default) { | |
| 745 if (HasMatchAt(index)) | |
| 746 model_->SetSelectedLine(index, revert_to_default); | |
| 747 } | |
| 748 | |
| 749 //////////////////////////////////////////////////////////////////////////////// | 677 //////////////////////////////////////////////////////////////////////////////// |
| 750 // AutocompletePopupContentsView, AnimationDelegate implementation: | 678 // AutocompletePopupContentsView, AnimationDelegate implementation: |
| 751 | 679 |
| 752 void AutocompletePopupContentsView::AnimationProgressed( | 680 void AutocompletePopupContentsView::AnimationProgressed( |
| 753 const Animation* animation) { | 681 const Animation* animation) { |
| 754 // We should only be running the animation when the popup is already visible. | 682 // We should only be running the animation when the popup is already visible. |
| 755 DCHECK(popup_ != NULL); | 683 DCHECK(popup_ != NULL); |
| 756 popup_->SetBounds(GetPopupBounds()); | 684 popup_->SetBounds(GetPopupBounds()); |
| 757 } | 685 } |
| 758 | 686 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 v->SetBounds(contents_rect.x(), top, contents_rect.width(), | 740 v->SetBounds(contents_rect.x(), top, contents_rect.width(), |
| 813 v->GetPreferredSize().height()); | 741 v->GetPreferredSize().height()); |
| 814 top = v->bounds().bottom(); | 742 top = v->bounds().bottom(); |
| 815 } | 743 } |
| 816 | 744 |
| 817 // We need to manually schedule a paint here since we are a layered window and | 745 // We need to manually schedule a paint here since we are a layered window and |
| 818 // won't implicitly require painting until we ask for one. | 746 // won't implicitly require painting until we ask for one. |
| 819 SchedulePaint(); | 747 SchedulePaint(); |
| 820 } | 748 } |
| 821 | 749 |
| 750 |
| 751 void AutocompletePopupContentsView::OnMouseEntered( |
| 752 const views::MouseEvent& event) { |
| 753 model_->SetHoveredLine(GetIndexForPoint(event.location())); |
| 754 } |
| 755 |
| 756 void AutocompletePopupContentsView::OnMouseMoved( |
| 757 const views::MouseEvent& event) { |
| 758 model_->SetHoveredLine(GetIndexForPoint(event.location())); |
| 759 } |
| 760 |
| 761 void AutocompletePopupContentsView::OnMouseExited( |
| 762 const views::MouseEvent& event) { |
| 763 model_->SetHoveredLine(AutocompletePopupModel::kNoMatch); |
| 764 } |
| 765 |
| 766 bool AutocompletePopupContentsView::OnMousePressed( |
| 767 const views::MouseEvent& event) { |
| 768 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) { |
| 769 int index = GetIndexForPoint(event.location()); |
| 770 model_->SetHoveredLine(index); |
| 771 if (HasMatchAt(index) && event.IsLeftMouseButton()) |
| 772 model_->SetSelectedLine(index, false); |
| 773 } |
| 774 return true; |
| 775 } |
| 776 |
| 777 void AutocompletePopupContentsView::OnMouseReleased( |
| 778 const views::MouseEvent& event, |
| 779 bool canceled) { |
| 780 if (canceled) |
| 781 return; |
| 782 int index = GetIndexForPoint(event.location()); |
| 783 if (index == AutocompletePopupModel::kNoMatch) |
| 784 return; |
| 785 if (event.IsOnlyMiddleMouseButton()) |
| 786 OpenIndex(index, NEW_BACKGROUND_TAB); |
| 787 else if (event.IsOnlyLeftMouseButton()) |
| 788 OpenIndex(index, CURRENT_TAB); |
| 789 } |
| 790 |
| 791 bool AutocompletePopupContentsView::OnMouseDragged( |
| 792 const views::MouseEvent& event) { |
| 793 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) { |
| 794 int index = GetIndexForPoint(event.location()); |
| 795 model_->SetHoveredLine(index); |
| 796 if (HasMatchAt(index) && event.IsLeftMouseButton()) |
| 797 model_->SetSelectedLine(index, false); |
| 798 } |
| 799 return true; |
| 800 } |
| 801 |
| 802 views::View* AutocompletePopupContentsView::GetViewForPoint( |
| 803 const gfx::Point& /*point*/) { |
| 804 // This View takes control of the mouse events, so it should be considered the |
| 805 // active view for any point inside of it. |
| 806 return this; |
| 807 } |
| 808 |
| 809 |
| 822 //////////////////////////////////////////////////////////////////////////////// | 810 //////////////////////////////////////////////////////////////////////////////// |
| 823 // AutocompletePopupContentsView, private: | 811 // AutocompletePopupContentsView, private: |
| 824 | 812 |
| 825 bool AutocompletePopupContentsView::HasMatchAt(size_t index) const { | 813 bool AutocompletePopupContentsView::HasMatchAt(size_t index) const { |
| 826 return index < model_->result().size(); | 814 return index < model_->result().size(); |
| 827 } | 815 } |
| 828 | 816 |
| 829 const AutocompleteMatch& AutocompletePopupContentsView::GetMatchAtIndex( | 817 const AutocompleteMatch& AutocompletePopupContentsView::GetMatchAtIndex( |
| 830 size_t index) const { | 818 size_t index) const { |
| 831 return model_->result().match_at(index); | 819 return model_->result().match_at(index); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 | 862 |
| 875 void AutocompletePopupContentsView::MakeCanvasTransparent( | 863 void AutocompletePopupContentsView::MakeCanvasTransparent( |
| 876 gfx::Canvas* canvas) { | 864 gfx::Canvas* canvas) { |
| 877 // Allow the window blur effect to show through the popup background. | 865 // Allow the window blur effect to show through the popup background. |
| 878 SkAlpha alpha = GetThemeProvider()->ShouldUseNativeFrame() ? | 866 SkAlpha alpha = GetThemeProvider()->ShouldUseNativeFrame() ? |
| 879 kGlassPopupAlpha : kOpaquePopupAlpha; | 867 kGlassPopupAlpha : kOpaquePopupAlpha; |
| 880 canvas->drawColor(SkColorSetA(GetColor(NORMAL, BACKGROUND), alpha), | 868 canvas->drawColor(SkColorSetA(GetColor(NORMAL, BACKGROUND), alpha), |
| 881 SkXfermode::kDstIn_Mode); | 869 SkXfermode::kDstIn_Mode); |
| 882 } | 870 } |
| 883 | 871 |
| 872 void AutocompletePopupContentsView::OpenIndex( |
| 873 size_t index, |
| 874 WindowOpenDisposition disposition) { |
| 875 if (!HasMatchAt(index)) |
| 876 return; |
| 877 |
| 878 const AutocompleteMatch& match = model_->result().match_at(index); |
| 879 // OpenURL() may close the popup, which will clear the result set and, by |
| 880 // extension, |match| and its contents. So copy the relevant strings out to |
| 881 // make sure they stay alive until the call completes. |
| 882 const GURL url(match.destination_url); |
| 883 std::wstring keyword; |
| 884 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); |
| 885 edit_view_->OpenURL(url, disposition, match.transition, GURL(), index, |
| 886 is_keyword_hint ? std::wstring() : keyword); |
| 887 } |
| 888 |
| 889 int AutocompletePopupContentsView::GetIndexForPoint(const gfx::Point& point) { |
| 890 if (!HitTest(point)) |
| 891 return AutocompletePopupModel::kNoMatch; |
| 892 |
| 893 int nb_match = model_->result().size(); |
| 894 DCHECK(nb_match <= GetChildViewCount()); |
| 895 for (int i = 0; i < nb_match; ++i) { |
| 896 views::View* child = GetChildViewAt(i); |
| 897 gfx::Point point_in_child_coords(point); |
| 898 View::ConvertPointToView(this, child, &point_in_child_coords); |
| 899 if (child->HitTest(point_in_child_coords)) |
| 900 return i; |
| 901 } |
| 902 return AutocompletePopupModel::kNoMatch; |
| 903 } |
| 904 |
| 884 // static | 905 // static |
| 885 AutocompletePopupView* AutocompletePopupView::CreatePopupView( | 906 AutocompletePopupView* AutocompletePopupView::CreatePopupView( |
| 886 const gfx::Font& font, | 907 const gfx::Font& font, |
| 887 AutocompleteEditView* edit_view, | 908 AutocompleteEditView* edit_view, |
| 888 AutocompleteEditModel* edit_model, | 909 AutocompleteEditModel* edit_model, |
| 889 Profile* profile, | 910 Profile* profile, |
| 890 const BubblePositioner* bubble_positioner) { | 911 const BubblePositioner* bubble_positioner) { |
| 891 return new AutocompletePopupContentsView(font, edit_view, edit_model, | 912 return new AutocompletePopupContentsView(font, edit_view, edit_model, |
| 892 profile, bubble_positioner); | 913 profile, bubble_positioner); |
| 893 } | 914 } |
| OLD | NEW |