| 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/wrench_menu.h" | 5 #include "chrome/browser/ui/views/wrench_menu.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "chrome/app/chrome_command_ids.h" | 13 #include "chrome/app/chrome_command_ids.h" |
| 14 #include "chrome/browser/bookmarks/bookmark_model.h" | 14 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 15 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | 15 #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| 16 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/search/search.h" | 18 #include "chrome/browser/search/search.h" |
| 19 #include "chrome/browser/ui/browser.h" | 19 #include "chrome/browser/ui/browser.h" |
| 20 #include "chrome/browser/ui/browser_window.h" | 20 #include "chrome/browser/ui/browser_window.h" |
| 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 22 #include "chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h" |
| 22 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" | 23 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" |
| 24 #include "chrome/browser/ui/views/recent_tabs_menu_model_delegate.h" |
| 23 #include "chrome/browser/ui/views/wrench_menu_observer.h" | 25 #include "chrome/browser/ui/views/wrench_menu_observer.h" |
| 24 #include "content/public/browser/host_zoom_map.h" | 26 #include "content/public/browser/host_zoom_map.h" |
| 25 #include "content/public/browser/notification_observer.h" | 27 #include "content/public/browser/notification_observer.h" |
| 26 #include "content/public/browser/notification_registrar.h" | 28 #include "content/public/browser/notification_registrar.h" |
| 27 #include "content/public/browser/notification_source.h" | 29 #include "content/public/browser/notification_source.h" |
| 28 #include "content/public/browser/notification_types.h" | 30 #include "content/public/browser/notification_types.h" |
| 29 #include "content/public/browser/user_metrics.h" | 31 #include "content/public/browser/user_metrics.h" |
| 30 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
| 31 #include "grit/chromium_strings.h" | 33 #include "grit/chromium_strings.h" |
| 32 #include "grit/generated_resources.h" | 34 #include "grit/generated_resources.h" |
| 33 #include "grit/theme_resources.h" | 35 #include "grit/theme_resources.h" |
| 34 #include "third_party/skia/include/core/SkCanvas.h" | 36 #include "third_party/skia/include/core/SkCanvas.h" |
| 35 #include "third_party/skia/include/core/SkPaint.h" | 37 #include "third_party/skia/include/core/SkPaint.h" |
| 36 #include "ui/base/l10n/l10n_util.h" | 38 #include "ui/base/l10n/l10n_util.h" |
| 37 #include "ui/base/layout.h" | 39 #include "ui/base/layout.h" |
| 38 #include "ui/base/resource/resource_bundle.h" | 40 #include "ui/base/resource/resource_bundle.h" |
| 39 #include "ui/gfx/canvas.h" | 41 #include "ui/gfx/canvas.h" |
| 40 #include "ui/gfx/image/canvas_image_source.h" | 42 #include "ui/gfx/image/canvas_image_source.h" |
| 41 #include "ui/gfx/image/image.h" | 43 #include "ui/gfx/image/image.h" |
| 42 #include "ui/gfx/skia_util.h" | 44 #include "ui/gfx/skia_util.h" |
| 43 #include "ui/gfx/text_utils.h" | 45 #include "ui/gfx/text_utils.h" |
| 44 #include "ui/views/background.h" | 46 #include "ui/views/background.h" |
| 45 #include "ui/views/controls/button/image_button.h" | 47 #include "ui/views/controls/button/image_button.h" |
| 46 #include "ui/views/controls/button/label_button.h" | 48 #include "ui/views/controls/button/label_button.h" |
| 47 #include "ui/views/controls/button/menu_button.h" | 49 #include "ui/views/controls/button/menu_button.h" |
| 48 #include "ui/views/controls/label.h" | 50 #include "ui/views/controls/label.h" |
| 49 #include "ui/views/controls/menu/menu_config.h" | 51 #include "ui/views/controls/menu/menu_config.h" |
| 50 #include "ui/views/controls/menu/menu_item_view.h" | 52 #include "ui/views/controls/menu/menu_item_view.h" |
| 53 #include "ui/views/controls/menu/menu_model_adapter.h" |
| 51 #include "ui/views/controls/menu/menu_runner.h" | 54 #include "ui/views/controls/menu/menu_runner.h" |
| 52 #include "ui/views/controls/menu/menu_scroll_view_container.h" | 55 #include "ui/views/controls/menu/menu_scroll_view_container.h" |
| 53 #include "ui/views/controls/menu/submenu_view.h" | 56 #include "ui/views/controls/menu/submenu_view.h" |
| 54 #include "ui/views/widget/widget.h" | 57 #include "ui/views/widget/widget.h" |
| 55 | 58 |
| 56 #if defined(USE_AURA) | 59 #if defined(USE_AURA) |
| 57 #include "ui/native_theme/native_theme_aura.h" | 60 #include "ui/native_theme/native_theme_aura.h" |
| 58 #endif | 61 #endif |
| 59 | 62 |
| 60 using content::HostZoomMap; | 63 using content::HostZoomMap; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 79 const SkColor kTouchButtonText = 0xff5a5a5a; | 82 const SkColor kTouchButtonText = 0xff5a5a5a; |
| 80 | 83 |
| 81 // Horizontal padding on the edges of the buttons. | 84 // Horizontal padding on the edges of the buttons. |
| 82 const int kHorizontalPadding = 6; | 85 const int kHorizontalPadding = 6; |
| 83 // Horizontal padding for a touch enabled menu. | 86 // Horizontal padding for a touch enabled menu. |
| 84 const int kHorizontalTouchPadding = 15; | 87 const int kHorizontalTouchPadding = 15; |
| 85 | 88 |
| 86 // Menu items which have embedded buttons should have this height in pixel. | 89 // Menu items which have embedded buttons should have this height in pixel. |
| 87 const int kMenuItemContainingButtonsHeight = 43; | 90 const int kMenuItemContainingButtonsHeight = 43; |
| 88 | 91 |
| 92 // First ID to use for the items in the recent tabs submenu, must be more than |
| 93 // maximum possible number of items in wrench menu and all its submenus except |
| 94 // recent babs submenu. |
| 95 const int kFirstRecentTabsCommandId = 200; |
| 96 |
| 97 // First ID to use for the items representing bookmarks in the bookmark menu, |
| 98 // must be more than kFirstRecentTabsCommandId + maximum possible number of |
| 99 // items in recent tabs submenu. |
| 100 const int kFirstBookmarkCommandId = 400; |
| 101 |
| 89 // Subclass of ImageButton whose preferred size includes the size of the border. | 102 // Subclass of ImageButton whose preferred size includes the size of the border. |
| 90 class FullscreenButton : public ImageButton { | 103 class FullscreenButton : public ImageButton { |
| 91 public: | 104 public: |
| 92 explicit FullscreenButton(views::ButtonListener* listener) | 105 explicit FullscreenButton(views::ButtonListener* listener) |
| 93 : ImageButton(listener) { } | 106 : ImageButton(listener) { } |
| 94 | 107 |
| 95 // Overridden from ImageButton. | 108 // Overridden from ImageButton. |
| 96 virtual gfx::Size GetPreferredSize() OVERRIDE { | 109 virtual gfx::Size GetPreferredSize() OVERRIDE { |
| 97 gfx::Size pref = ImageButton::GetPreferredSize(); | 110 gfx::Size pref = ImageButton::GetPreferredSize(); |
| 98 if (border()) { | 111 if (border()) { |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 LabelButton* decrement_button_; | 762 LabelButton* decrement_button_; |
| 750 | 763 |
| 751 ImageButton* fullscreen_button_; | 764 ImageButton* fullscreen_button_; |
| 752 | 765 |
| 753 // Width given to |zoom_label_|. This is the width at 100%. | 766 // Width given to |zoom_label_|. This is the width at 100%. |
| 754 int zoom_label_width_; | 767 int zoom_label_width_; |
| 755 | 768 |
| 756 DISALLOW_COPY_AND_ASSIGN(ZoomView); | 769 DISALLOW_COPY_AND_ASSIGN(ZoomView); |
| 757 }; | 770 }; |
| 758 | 771 |
| 759 // RecentTabsMenuModelDelegate ------------------------------------------------- | |
| 760 | |
| 761 // Provides the ui::MenuModelDelegate implementation for RecentTabsSubMenuModel | |
| 762 // items. | |
| 763 class WrenchMenu::RecentTabsMenuModelDelegate : public ui::MenuModelDelegate { | |
| 764 public: | |
| 765 RecentTabsMenuModelDelegate(ui::MenuModel* model, | |
| 766 views::MenuItemView* menu_item) | |
| 767 : model_(model), | |
| 768 menu_item_(menu_item) { | |
| 769 model_->SetMenuModelDelegate(this); | |
| 770 } | |
| 771 | |
| 772 virtual ~RecentTabsMenuModelDelegate() { | |
| 773 model_->SetMenuModelDelegate(NULL); | |
| 774 } | |
| 775 | |
| 776 // ui::MenuModelDelegate implementation: | |
| 777 virtual void OnIconChanged(int index) OVERRIDE { | |
| 778 // |index| specifies position in children items of |menu_item_| starting at | |
| 779 // 0, its corresponding command id as used in the children menu item views | |
| 780 // follows that of the parent menu item view |menu_item_|. | |
| 781 int command_id = menu_item_->GetCommand() + 1 + index; | |
| 782 views::MenuItemView* item = menu_item_->GetMenuItemByID(command_id); | |
| 783 DCHECK(item); | |
| 784 gfx::Image icon; | |
| 785 if (model_->GetIconAt(index, &icon)) | |
| 786 item->SetIcon(*icon.ToImageSkia()); | |
| 787 } | |
| 788 | |
| 789 // Return the specific menu width of recent tab menu item if |command_id| | |
| 790 // refers to one of recent tabs menu items, else return -1. | |
| 791 int GetMaxWidthForMenu(MenuItemView* menu) { | |
| 792 views::SubmenuView* submenu = menu_item_->GetSubmenu(); | |
| 793 if (!submenu) | |
| 794 return -1; | |
| 795 const int kMaxMenuItemWidth = 320; | |
| 796 return menu->GetCommand() >= menu_item_->GetCommand() && | |
| 797 menu->GetCommand() <= | |
| 798 menu_item_->GetCommand() + submenu->GetMenuItemCount() ? | |
| 799 kMaxMenuItemWidth : -1; | |
| 800 } | |
| 801 | |
| 802 const gfx::Font* GetLabelFontAt(int index) const { | |
| 803 return model_->GetLabelFontAt(index); | |
| 804 } | |
| 805 | |
| 806 bool GetForegroundColor(int command_id, | |
| 807 bool is_hovered, | |
| 808 SkColor* override_color) const { | |
| 809 // The items for which we get a font, should be shown in black. | |
| 810 if (GetLabelFontAt(command_id)) { | |
| 811 *override_color = SK_ColorBLACK; | |
| 812 return true; | |
| 813 } | |
| 814 return false; | |
| 815 } | |
| 816 | |
| 817 private: | |
| 818 ui::MenuModel* model_; | |
| 819 views::MenuItemView* menu_item_; | |
| 820 | |
| 821 DISALLOW_COPY_AND_ASSIGN(RecentTabsMenuModelDelegate); | |
| 822 }; | |
| 823 | |
| 824 // WrenchMenu ------------------------------------------------------------------ | 772 // WrenchMenu ------------------------------------------------------------------ |
| 825 | 773 |
| 826 WrenchMenu::WrenchMenu(Browser* browser, | 774 WrenchMenu::WrenchMenu(Browser* browser, |
| 827 bool use_new_menu, | 775 bool use_new_menu, |
| 828 bool supports_new_separators) | 776 bool supports_new_separators) |
| 829 : root_(NULL), | 777 : root_(NULL), |
| 830 browser_(browser), | 778 browser_(browser), |
| 831 selected_menu_model_(NULL), | 779 selected_menu_model_(NULL), |
| 832 selected_index_(0), | 780 selected_index_(0), |
| 833 bookmark_menu_(NULL), | 781 bookmark_menu_(NULL), |
| 834 feedback_menu_item_(NULL), | 782 feedback_menu_item_(NULL), |
| 835 first_bookmark_command_id_(0), | |
| 836 first_recent_tabs_command_id_(-1), | |
| 837 last_recent_tabs_command_id_(-1), | |
| 838 use_new_menu_(use_new_menu), | 783 use_new_menu_(use_new_menu), |
| 839 supports_new_separators_(supports_new_separators) { | 784 supports_new_separators_(supports_new_separators) { |
| 840 registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED, | 785 registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED, |
| 841 content::Source<Profile>(browser_->profile())); | 786 content::Source<Profile>(browser_->profile())); |
| 842 } | 787 } |
| 843 | 788 |
| 844 WrenchMenu::~WrenchMenu() { | 789 WrenchMenu::~WrenchMenu() { |
| 845 if (bookmark_menu_delegate_.get()) { | 790 if (bookmark_menu_delegate_.get()) { |
| 846 BookmarkModel* model = BookmarkModelFactory::GetForProfile( | 791 BookmarkModel* model = BookmarkModelFactory::GetForProfile( |
| 847 browser_->profile()); | 792 browser_->profile()); |
| 848 if (model) | 793 if (model) |
| 849 model->RemoveObserver(this); | 794 model->RemoveObserver(this); |
| 850 } | 795 } |
| 851 FOR_EACH_OBSERVER(WrenchMenuObserver, observer_list_, WrenchMenuDestroyed()); | 796 FOR_EACH_OBSERVER(WrenchMenuObserver, observer_list_, WrenchMenuDestroyed()); |
| 852 } | 797 } |
| 853 | 798 |
| 854 void WrenchMenu::Init(ui::MenuModel* model) { | 799 void WrenchMenu::Init(ui::MenuModel* model) { |
| 855 DCHECK(!root_); | 800 DCHECK(!root_); |
| 856 root_ = new MenuItemView(this); | 801 root_ = new MenuItemView(this); |
| 857 root_->set_has_icons(true); // We have checks, radios and icons, set this | 802 root_->set_has_icons(true); // We have checks, radios and icons, set this |
| 858 // so we get the taller menu style. | 803 // so we get the taller menu style. |
| 859 int next_id = 1; | 804 int next_id = 1; |
| 860 PopulateMenu(root_, model, &next_id); | 805 PopulateMenu(root_, model, &next_id); |
| 861 first_bookmark_command_id_ = next_id + 1; | 806 DCHECK_LT(next_id, kFirstRecentTabsCommandId); |
| 862 menu_runner_.reset(new views::MenuRunner(root_)); | 807 menu_runner_.reset(new views::MenuRunner(root_)); |
| 863 } | 808 } |
| 864 | 809 |
| 865 void WrenchMenu::RunMenu(views::MenuButton* host) { | 810 void WrenchMenu::RunMenu(views::MenuButton* host) { |
| 866 gfx::Point screen_loc; | 811 gfx::Point screen_loc; |
| 867 views::View::ConvertPointToScreen(host, &screen_loc); | 812 views::View::ConvertPointToScreen(host, &screen_loc); |
| 868 gfx::Rect bounds(screen_loc, host->size()); | 813 gfx::Rect bounds(screen_loc, host->size()); |
| 869 content::RecordAction(UserMetricsAction("ShowAppMenu")); | 814 content::RecordAction(UserMetricsAction("ShowAppMenu")); |
| 870 if (menu_runner_->RunMenuAt(host->GetWidget(), host, bounds, | 815 if (menu_runner_->RunMenuAt(host->GetWidget(), host, bounds, |
| 871 MenuItemView::TOPRIGHT, ui::MENU_SOURCE_NONE, | 816 MenuItemView::TOPRIGHT, ui::MENU_SOURCE_NONE, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 898 } | 843 } |
| 899 | 844 |
| 900 void WrenchMenu::AddObserver(WrenchMenuObserver* observer) { | 845 void WrenchMenu::AddObserver(WrenchMenuObserver* observer) { |
| 901 observer_list_.AddObserver(observer); | 846 observer_list_.AddObserver(observer); |
| 902 } | 847 } |
| 903 | 848 |
| 904 void WrenchMenu::RemoveObserver(WrenchMenuObserver* observer) { | 849 void WrenchMenu::RemoveObserver(WrenchMenuObserver* observer) { |
| 905 observer_list_.RemoveObserver(observer); | 850 observer_list_.RemoveObserver(observer); |
| 906 } | 851 } |
| 907 | 852 |
| 908 const gfx::Font* WrenchMenu::GetLabelFont(int index) const { | 853 const gfx::Font* WrenchMenu::GetLabelFont(int id) const { |
| 909 if (is_recent_tabs_command(index)) { | 854 return IsRecentTabsCommand(id) ? |
| 910 return recent_tabs_menu_model_delegate_->GetLabelFontAt( | 855 recent_tabs_menu_model_delegate_->GetLabelFontAt(id) : NULL; |
| 911 index - first_recent_tabs_command_id_); | |
| 912 } | |
| 913 return NULL; | |
| 914 } | 856 } |
| 915 | 857 |
| 916 bool WrenchMenu::GetForegroundColor(int command_id, | 858 bool WrenchMenu::GetForegroundColor(int command_id, |
| 917 bool is_hovered, | 859 bool is_hovered, |
| 918 SkColor* override_color) const { | 860 SkColor* override_color) const { |
| 919 if (is_recent_tabs_command(command_id)) { | 861 if (IsRecentTabsCommand(command_id)) { |
| 920 return recent_tabs_menu_model_delegate_->GetForegroundColor( | 862 return recent_tabs_menu_model_delegate_->GetForegroundColor( |
| 921 command_id - first_recent_tabs_command_id_, | 863 command_id, |
| 922 is_hovered, | 864 is_hovered, |
| 923 override_color); | 865 override_color); |
| 924 } | 866 } |
| 925 return false; | 867 return false; |
| 926 } | 868 } |
| 927 | 869 |
| 928 string16 WrenchMenu::GetTooltipText(int id, | 870 string16 WrenchMenu::GetTooltipText(int id, |
| 929 const gfx::Point& p) const { | 871 const gfx::Point& p) const { |
| 930 return is_bookmark_command(id) ? | 872 return IsBookmarkCommand(id) ? |
| 931 bookmark_menu_delegate_->GetTooltipText(id, p) : string16(); | 873 bookmark_menu_delegate_->GetTooltipText(id, p) : string16(); |
| 932 } | 874 } |
| 933 | 875 |
| 934 bool WrenchMenu::IsTriggerableEvent(views::MenuItemView* menu, | 876 bool WrenchMenu::IsTriggerableEvent(views::MenuItemView* menu, |
| 935 const ui::Event& e) { | 877 const ui::Event& e) { |
| 936 return is_bookmark_command(menu->GetCommand()) ? | 878 return IsBookmarkCommand(menu->GetCommand()) ? |
| 937 bookmark_menu_delegate_->IsTriggerableEvent(menu, e) : | 879 bookmark_menu_delegate_->IsTriggerableEvent(menu, e) : |
| 938 MenuDelegate::IsTriggerableEvent(menu, e); | 880 MenuDelegate::IsTriggerableEvent(menu, e); |
| 939 } | 881 } |
| 940 | 882 |
| 941 bool WrenchMenu::GetDropFormats( | 883 bool WrenchMenu::GetDropFormats( |
| 942 MenuItemView* menu, | 884 MenuItemView* menu, |
| 943 int* formats, | 885 int* formats, |
| 944 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { | 886 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
| 945 CreateBookmarkMenu(); | 887 CreateBookmarkMenu(); |
| 946 return bookmark_menu_delegate_.get() && | 888 return bookmark_menu_delegate_.get() && |
| (...skipping 10 matching lines...) Expand all Loading... |
| 957 const ui::OSExchangeData& data) { | 899 const ui::OSExchangeData& data) { |
| 958 CreateBookmarkMenu(); | 900 CreateBookmarkMenu(); |
| 959 return bookmark_menu_delegate_.get() && | 901 return bookmark_menu_delegate_.get() && |
| 960 bookmark_menu_delegate_->CanDrop(menu, data); | 902 bookmark_menu_delegate_->CanDrop(menu, data); |
| 961 } | 903 } |
| 962 | 904 |
| 963 int WrenchMenu::GetDropOperation( | 905 int WrenchMenu::GetDropOperation( |
| 964 MenuItemView* item, | 906 MenuItemView* item, |
| 965 const ui::DropTargetEvent& event, | 907 const ui::DropTargetEvent& event, |
| 966 DropPosition* position) { | 908 DropPosition* position) { |
| 967 return is_bookmark_command(item->GetCommand()) ? | 909 return IsBookmarkCommand(item->GetCommand()) ? |
| 968 bookmark_menu_delegate_->GetDropOperation(item, event, position) : | 910 bookmark_menu_delegate_->GetDropOperation(item, event, position) : |
| 969 ui::DragDropTypes::DRAG_NONE; | 911 ui::DragDropTypes::DRAG_NONE; |
| 970 } | 912 } |
| 971 | 913 |
| 972 int WrenchMenu::OnPerformDrop(MenuItemView* menu, | 914 int WrenchMenu::OnPerformDrop(MenuItemView* menu, |
| 973 DropPosition position, | 915 DropPosition position, |
| 974 const ui::DropTargetEvent& event) { | 916 const ui::DropTargetEvent& event) { |
| 975 if (!is_bookmark_command(menu->GetCommand())) | 917 if (!IsBookmarkCommand(menu->GetCommand())) |
| 976 return ui::DragDropTypes::DRAG_NONE; | 918 return ui::DragDropTypes::DRAG_NONE; |
| 977 | 919 |
| 978 int result = bookmark_menu_delegate_->OnPerformDrop(menu, position, event); | 920 int result = bookmark_menu_delegate_->OnPerformDrop(menu, position, event); |
| 979 return result; | 921 return result; |
| 980 } | 922 } |
| 981 | 923 |
| 982 bool WrenchMenu::ShowContextMenu(MenuItemView* source, | 924 bool WrenchMenu::ShowContextMenu(MenuItemView* source, |
| 983 int id, | 925 int id, |
| 984 const gfx::Point& p, | 926 const gfx::Point& p, |
| 985 ui::MenuSourceType source_type) { | 927 ui::MenuSourceType source_type) { |
| 986 return is_bookmark_command(id) ? | 928 return IsBookmarkCommand(id) ? |
| 987 bookmark_menu_delegate_->ShowContextMenu(source, id, p, | 929 bookmark_menu_delegate_->ShowContextMenu(source, id, p, |
| 988 source_type) : | 930 source_type) : |
| 989 false; | 931 false; |
| 990 } | 932 } |
| 991 | 933 |
| 992 bool WrenchMenu::CanDrag(MenuItemView* menu) { | 934 bool WrenchMenu::CanDrag(MenuItemView* menu) { |
| 993 return is_bookmark_command(menu->GetCommand()) ? | 935 return IsBookmarkCommand(menu->GetCommand()) ? |
| 994 bookmark_menu_delegate_->CanDrag(menu) : false; | 936 bookmark_menu_delegate_->CanDrag(menu) : false; |
| 995 } | 937 } |
| 996 | 938 |
| 997 void WrenchMenu::WriteDragData(MenuItemView* sender, | 939 void WrenchMenu::WriteDragData(MenuItemView* sender, |
| 998 ui::OSExchangeData* data) { | 940 ui::OSExchangeData* data) { |
| 999 DCHECK(is_bookmark_command(sender->GetCommand())); | 941 DCHECK(IsBookmarkCommand(sender->GetCommand())); |
| 1000 return bookmark_menu_delegate_->WriteDragData(sender, data); | 942 return bookmark_menu_delegate_->WriteDragData(sender, data); |
| 1001 } | 943 } |
| 1002 | 944 |
| 1003 int WrenchMenu::GetDragOperations(MenuItemView* sender) { | 945 int WrenchMenu::GetDragOperations(MenuItemView* sender) { |
| 1004 return is_bookmark_command(sender->GetCommand()) ? | 946 return IsBookmarkCommand(sender->GetCommand()) ? |
| 1005 bookmark_menu_delegate_->GetDragOperations(sender) : | 947 bookmark_menu_delegate_->GetDragOperations(sender) : |
| 1006 MenuDelegate::GetDragOperations(sender); | 948 MenuDelegate::GetDragOperations(sender); |
| 1007 } | 949 } |
| 1008 | 950 |
| 1009 int WrenchMenu::GetMaxWidthForMenu(MenuItemView* menu) { | 951 int WrenchMenu::GetMaxWidthForMenu(MenuItemView* menu) { |
| 1010 if (is_bookmark_command(menu->GetCommand())) | 952 if (IsBookmarkCommand(menu->GetCommand())) |
| 1011 return bookmark_menu_delegate_->GetMaxWidthForMenu(menu); | 953 return bookmark_menu_delegate_->GetMaxWidthForMenu(menu); |
| 1012 int max_width = -1; | 954 int max_width = -1; |
| 1013 // If recent tabs menu is available, it will decide if |menu| is one of recent | 955 // If recent tabs menu is available, it will decide if |menu| is one of recent |
| 1014 // tabs; if yes, it would return the menu width for recent tabs. | 956 // tabs; if yes, it would return the menu width for recent tabs. |
| 1015 // otherwise, it would return -1. | 957 // otherwise, it would return -1. |
| 1016 if (recent_tabs_menu_model_delegate_.get()) | 958 if (recent_tabs_menu_model_delegate_.get()) |
| 1017 max_width = recent_tabs_menu_model_delegate_->GetMaxWidthForMenu(menu); | 959 max_width = recent_tabs_menu_model_delegate_->GetMaxWidthForMenu(menu); |
| 1018 if (max_width == -1) | 960 if (max_width == -1) |
| 1019 max_width = MenuDelegate::GetMaxWidthForMenu(menu); | 961 max_width = MenuDelegate::GetMaxWidthForMenu(menu); |
| 1020 return max_width; | 962 return max_width; |
| 1021 } | 963 } |
| 1022 | 964 |
| 1023 bool WrenchMenu::IsItemChecked(int id) const { | 965 bool WrenchMenu::IsItemChecked(int id) const { |
| 1024 if (is_bookmark_command(id)) | 966 if (IsBookmarkCommand(id)) |
| 1025 return false; | 967 return false; |
| 1026 | 968 |
| 1027 const Entry& entry = id_to_entry_.find(id)->second; | 969 const Entry& entry = id_to_entry_.find(id)->second; |
| 1028 return entry.first->IsItemCheckedAt(entry.second); | 970 return entry.first->IsItemCheckedAt(entry.second); |
| 1029 } | 971 } |
| 1030 | 972 |
| 1031 bool WrenchMenu::IsCommandEnabled(int id) const { | 973 bool WrenchMenu::IsCommandEnabled(int id) const { |
| 1032 if (is_bookmark_command(id)) | 974 if (IsBookmarkCommand(id)) |
| 1033 return true; | 975 return true; |
| 1034 | 976 |
| 1035 if (id == 0) | 977 if (id == 0) |
| 1036 return false; // The root item. | 978 return false; // The root item. |
| 1037 | 979 |
| 1038 const Entry& entry = id_to_entry_.find(id)->second; | 980 const Entry& entry = id_to_entry_.find(id)->second; |
| 1039 int command_id = entry.first->GetCommandIdAt(entry.second); | 981 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 1040 // The items representing the cut menu (cut/copy/paste) and zoom menu | 982 // The items representing the cut menu (cut/copy/paste) and zoom menu |
| 1041 // (increment/decrement/reset) are always enabled. The child views of these | 983 // (increment/decrement/reset) are always enabled. The child views of these |
| 1042 // items enabled state updates appropriately. | 984 // items enabled state updates appropriately. |
| 1043 return command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS || | 985 return command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS || |
| 1044 entry.first->IsEnabledAt(entry.second); | 986 entry.first->IsEnabledAt(entry.second); |
| 1045 } | 987 } |
| 1046 | 988 |
| 1047 void WrenchMenu::ExecuteCommand(int id, int mouse_event_flags) { | 989 void WrenchMenu::ExecuteCommand(int id, int mouse_event_flags) { |
| 1048 if (is_bookmark_command(id)) { | 990 if (IsBookmarkCommand(id)) { |
| 1049 bookmark_menu_delegate_->ExecuteCommand(id, mouse_event_flags); | 991 bookmark_menu_delegate_->ExecuteCommand(id, mouse_event_flags); |
| 1050 return; | 992 return; |
| 1051 } | 993 } |
| 1052 | 994 |
| 1053 // Not a bookmark | 995 // Not a bookmark |
| 1054 const Entry& entry = id_to_entry_.find(id)->second; | 996 const Entry& entry = id_to_entry_.find(id)->second; |
| 1055 int command_id = entry.first->GetCommandIdAt(entry.second); | 997 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 1056 | 998 |
| 1057 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { | 999 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { |
| 1058 // These items are represented by child views. If ExecuteCommand is invoked | 1000 // These items are represented by child views. If ExecuteCommand is invoked |
| 1059 // it means the user clicked on the area around the buttons and we should | 1001 // it means the user clicked on the area around the buttons and we should |
| 1060 // not do anyting. | 1002 // not do anyting. |
| 1061 return; | 1003 return; |
| 1062 } | 1004 } |
| 1063 | 1005 |
| 1064 return entry.first->ActivatedAt(entry.second, mouse_event_flags); | 1006 return entry.first->ActivatedAt(entry.second, mouse_event_flags); |
| 1065 } | 1007 } |
| 1066 | 1008 |
| 1067 bool WrenchMenu::GetAccelerator(int id, ui::Accelerator* accelerator) { | 1009 bool WrenchMenu::GetAccelerator(int id, ui::Accelerator* accelerator) { |
| 1068 if (is_bookmark_command(id)) | 1010 if (IsBookmarkCommand(id)) |
| 1069 return false; | 1011 return false; |
| 1070 IDToEntry::iterator ix = id_to_entry_.find(id); | 1012 IDToEntry::iterator ix = id_to_entry_.find(id); |
| 1071 if (ix == id_to_entry_.end()) { | 1013 if (ix == id_to_entry_.end()) { |
| 1072 // There is no entry for this id. | 1014 // There is no entry for this id. |
| 1073 return false; | 1015 return false; |
| 1074 } | 1016 } |
| 1075 | 1017 |
| 1076 const Entry& entry = ix->second; | 1018 const Entry& entry = ix->second; |
| 1077 int command_id = entry.first->GetCommandIdAt(entry.second); | 1019 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 1078 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { | 1020 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1101 if (menu->HasSubmenu() && feedback_menu_item_ && | 1043 if (menu->HasSubmenu() && feedback_menu_item_ && |
| 1102 feedback_menu_item_->IsSelected()) { | 1044 feedback_menu_item_->IsSelected()) { |
| 1103 // It's okay to just turn off the animation and no to take care the | 1045 // It's okay to just turn off the animation and no to take care the |
| 1104 // animation back because the menu widget will be recreated next time | 1046 // animation back because the menu widget will be recreated next time |
| 1105 // it's opened. See ToolbarView::RunMenu() and Init() of this class. | 1047 // it's opened. See ToolbarView::RunMenu() and Init() of this class. |
| 1106 menu->GetSubmenu()->GetWidget()-> | 1048 menu->GetSubmenu()->GetWidget()-> |
| 1107 SetVisibilityChangedAnimationsEnabled(false); | 1049 SetVisibilityChangedAnimationsEnabled(false); |
| 1108 } | 1050 } |
| 1109 } | 1051 } |
| 1110 | 1052 |
| 1053 void WrenchMenu::OnItemAdded(MenuItemView* parent, |
| 1054 int menu_index, |
| 1055 ui::MenuModel* model, |
| 1056 int model_index, |
| 1057 int item_id) { |
| 1058 int id = item_id; |
| 1059 AddMenuItem(parent, menu_index, model, |
| 1060 model_index, model->GetTypeAt(model_index), |
| 1061 &id, 0); |
| 1062 } |
| 1063 |
| 1064 void WrenchMenu::OnItemRemoved(MenuItemView* parent, int menu_index, |
| 1065 int item_id) { |
| 1066 parent->RemoveMenuItemAt(menu_index); |
| 1067 id_to_entry_.erase(item_id); |
| 1068 } |
| 1069 |
| 1070 void WrenchMenu::UpdateMapOfMenuItemIdAndModel(ui::MenuModel* model, |
| 1071 std::vector<int>& item_ids) { |
| 1072 for (int i = 0; i < static_cast<int>(item_ids.size()); ++i) { |
| 1073 int id = item_ids[i]; |
| 1074 CHECK(id_to_entry_[id].first == model); // kk |
| 1075 if (id_to_entry_[id].second != i) |
| 1076 { |
| 1077 LOG(ERROR) << "kk chnged: map[" << id << "] = {" << id_to_entry_[id].first << ",
" << id_to_entry_[id].second << "}, idx=" << i; |
| 1078 id_to_entry_[id].second = i; |
| 1079 } |
| 1080 } |
| 1081 |
| 1082 //#if defined(DEBUG) // kk |
| 1083 // Verify that all mappings between id and index is unique i.e. 1-1. |
| 1084 std::vector<bool> id_exists; |
| 1085 id_exists.resize(model->GetItemCount(), false); |
| 1086 for (IDToEntry::const_iterator iter = id_to_entry_.begin(); |
| 1087 iter != id_to_entry_.end(); ++iter) { |
| 1088 const Entry& entry = iter->second; |
| 1089 if (entry.first != model) |
| 1090 continue; |
| 1091 CHECK(!id_exists[entry.second]) // kk |
| 1092 << "id_to_map[" << iter->first << "].index = " << entry.second |
| 1093 << " already exists!"; |
| 1094 LOG(ERROR) << "id_to_map[" << iter->first << "].index = " << entry.second; |
| 1095 id_exists[entry.second] = true; |
| 1096 } |
| 1097 // #endif // defined(DEBUG) // kk |
| 1098 } |
| 1099 |
| 1111 void WrenchMenu::BookmarkModelChanged() { | 1100 void WrenchMenu::BookmarkModelChanged() { |
| 1112 DCHECK(bookmark_menu_delegate_.get()); | 1101 DCHECK(bookmark_menu_delegate_.get()); |
| 1113 if (!bookmark_menu_delegate_->is_mutating_model()) | 1102 if (!bookmark_menu_delegate_->is_mutating_model()) |
| 1114 root_->Cancel(); | 1103 root_->Cancel(); |
| 1115 } | 1104 } |
| 1116 | 1105 |
| 1117 void WrenchMenu::Observe(int type, | 1106 void WrenchMenu::Observe(int type, |
| 1118 const content::NotificationSource& source, | 1107 const content::NotificationSource& source, |
| 1119 const content::NotificationDetails& details) { | 1108 const content::NotificationDetails& details) { |
| 1120 switch (type) { | 1109 switch (type) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1133 int* next_id) { | 1122 int* next_id) { |
| 1134 for (int i = 0, max = model->GetItemCount(); i < max; ++i) { | 1123 for (int i = 0, max = model->GetItemCount(); i < max; ++i) { |
| 1135 // The button container menu items have a special height which we have to | 1124 // The button container menu items have a special height which we have to |
| 1136 // use instead of the normal height. | 1125 // use instead of the normal height. |
| 1137 int height = 0; | 1126 int height = 0; |
| 1138 if (use_new_menu_ && | 1127 if (use_new_menu_ && |
| 1139 (model->GetCommandIdAt(i) == IDC_CUT || | 1128 (model->GetCommandIdAt(i) == IDC_CUT || |
| 1140 model->GetCommandIdAt(i) == IDC_ZOOM_MINUS)) | 1129 model->GetCommandIdAt(i) == IDC_ZOOM_MINUS)) |
| 1141 height = kMenuItemContainingButtonsHeight; | 1130 height = kMenuItemContainingButtonsHeight; |
| 1142 | 1131 |
| 1143 MenuItemView* item = AppendMenuItem( | 1132 // Add the menu item at the end. |
| 1144 parent, model, i, model->GetTypeAt(i), next_id, height); | 1133 int menu_index = parent->HasSubmenu() ? |
| 1134 parent->GetSubmenu()->child_count() : 0; |
| 1135 MenuItemView* item = AddMenuItem( |
| 1136 parent, menu_index, model, i, model->GetTypeAt(i), next_id, height); |
| 1145 | 1137 |
| 1146 if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { | 1138 if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { |
| 1147 bool is_recent_tabs_menu = | 1139 // Only populate submenus if it's not Recent Tabs submenu. |
| 1148 model->GetCommandIdAt(i) == IDC_RECENT_TABS_MENU; | 1140 // RecentTabsMenuModelDelegate will populate the Recent Tabs submenu |
| 1149 if (is_recent_tabs_menu) | 1141 // below; the submenu consists of both dynamic and constant items, which |
| 1150 first_recent_tabs_command_id_ = *next_id; | 1142 // require special handling of their Id's. |
| 1151 PopulateMenu(item, model->GetSubmenuModelAt(i), next_id); | 1143 if (model->GetCommandIdAt(i) != IDC_RECENT_TABS_MENU) |
| 1152 if (is_recent_tabs_menu) | 1144 PopulateMenu(item, model->GetSubmenuModelAt(i), next_id); |
| 1153 last_recent_tabs_command_id_ = *next_id - 1; | |
| 1154 } | 1145 } |
| 1155 | 1146 |
| 1156 const ui::NativeTheme* native_theme = GetNativeTheme(); | 1147 const ui::NativeTheme* native_theme = GetNativeTheme(); |
| 1157 | 1148 |
| 1158 switch (model->GetCommandIdAt(i)) { | 1149 switch (model->GetCommandIdAt(i)) { |
| 1159 case IDC_CUT: | 1150 case IDC_CUT: |
| 1160 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(i)); | 1151 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(i)); |
| 1161 DCHECK_LT(i + 2, max); | 1152 DCHECK_LT(i + 2, max); |
| 1162 DCHECK_EQ(IDC_COPY, model->GetCommandIdAt(i + 1)); | 1153 DCHECK_EQ(IDC_COPY, model->GetCommandIdAt(i + 1)); |
| 1163 DCHECK_EQ(IDC_PASTE, model->GetCommandIdAt(i + 2)); | 1154 DCHECK_EQ(IDC_PASTE, model->GetCommandIdAt(i + 2)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1185 #if defined(GOOGLE_CHROME_BUILD) | 1176 #if defined(GOOGLE_CHROME_BUILD) |
| 1186 case IDC_FEEDBACK: | 1177 case IDC_FEEDBACK: |
| 1187 DCHECK(!feedback_menu_item_); | 1178 DCHECK(!feedback_menu_item_); |
| 1188 feedback_menu_item_ = item; | 1179 feedback_menu_item_ = item; |
| 1189 break; | 1180 break; |
| 1190 #endif | 1181 #endif |
| 1191 | 1182 |
| 1192 case IDC_RECENT_TABS_MENU: | 1183 case IDC_RECENT_TABS_MENU: |
| 1193 DCHECK(!recent_tabs_menu_model_delegate_.get()); | 1184 DCHECK(!recent_tabs_menu_model_delegate_.get()); |
| 1194 recent_tabs_menu_model_delegate_.reset( | 1185 recent_tabs_menu_model_delegate_.reset( |
| 1195 new RecentTabsMenuModelDelegate(model->GetSubmenuModelAt(i), | 1186 new RecentTabsMenuModelDelegate( |
| 1196 item)); | 1187 this, |
| 1188 static_cast<RecentTabsSubMenuModel*>( |
| 1189 model->GetSubmenuModelAt(i)), |
| 1190 item, |
| 1191 kFirstRecentTabsCommandId, |
| 1192 kFirstBookmarkCommandId - 1)); |
| 1193 recent_tabs_menu_model_delegate_->PopulateMenu(); |
| 1197 break; | 1194 break; |
| 1198 | 1195 |
| 1199 default: | 1196 default: |
| 1200 break; | 1197 break; |
| 1201 } | 1198 } |
| 1202 } | 1199 } |
| 1203 } | 1200 } |
| 1204 | 1201 |
| 1205 MenuItemView* WrenchMenu::AppendMenuItem(MenuItemView* parent, | 1202 MenuItemView* WrenchMenu::AddMenuItem(MenuItemView* parent, |
| 1206 MenuModel* model, | 1203 int menu_index, |
| 1207 int index, | 1204 MenuModel* model, |
| 1208 MenuModel::ItemType menu_type, | 1205 int model_index, |
| 1209 int* next_id, | 1206 MenuModel::ItemType menu_type, |
| 1210 int height) { | 1207 int* next_id, |
| 1208 int height) { |
| 1211 int id = (*next_id)++; | 1209 int id = (*next_id)++; |
| 1212 | 1210 |
| 1211 DCHECK(id_to_entry_.find(id) == id_to_entry_.end()); |
| 1212 |
| 1213 id_to_entry_[id].first = model; | 1213 id_to_entry_[id].first = model; |
| 1214 id_to_entry_[id].second = index; | 1214 id_to_entry_[id].second = model_index; |
| 1215 | 1215 |
| 1216 MenuItemView* menu_item = NULL; | 1216 MenuItemView* menu_item = NULL; |
| 1217 if (height > 0) { | 1217 if (height > 0) { |
| 1218 // For menu items with a special menu height we use our special class to be | 1218 // For menu items with a special menu height we use our special class to be |
| 1219 // able to modify the item height. | 1219 // able to modify the item height. |
| 1220 menu_item = new ButtonContainerMenuItemView(parent, id, height); | 1220 menu_item = new ButtonContainerMenuItemView(parent, id, height); |
| 1221 parent->GetSubmenu()->AddChildView(menu_item); | 1221 parent->GetSubmenu()->AddChildViewAt(menu_item, menu_index); |
| 1222 } else { | 1222 } else { |
| 1223 // For all other cases we use the more generic way to add menu items. | 1223 // For all other cases we use the more generic way to add menu items. |
| 1224 menu_item = parent->AppendMenuItemFromModel(model, index, id); | 1224 menu_item = views::MenuModelAdapter::AddMenuItemFromModelAt( |
| 1225 model, model_index, parent, menu_index, id); |
| 1225 } | 1226 } |
| 1226 | 1227 |
| 1227 if (menu_item) { | 1228 if (menu_item) { |
| 1228 // Flush all buttons to the right side of the menu for the new menu type. | 1229 // Flush all buttons to the right side of the menu for the new menu type. |
| 1229 menu_item->set_use_right_margin(!use_new_menu_); | 1230 menu_item->set_use_right_margin(!use_new_menu_); |
| 1230 menu_item->SetVisible(model->IsVisibleAt(index)); | 1231 menu_item->SetVisible(model->IsVisibleAt(model_index)); |
| 1231 | 1232 |
| 1232 if (menu_type == MenuModel::TYPE_COMMAND && model->HasIcons()) { | 1233 if (menu_type == MenuModel::TYPE_COMMAND && model->HasIcons()) { |
| 1233 gfx::Image icon; | 1234 gfx::Image icon; |
| 1234 if (model->GetIconAt(index, &icon)) | 1235 if (model->GetIconAt(model_index, &icon)) |
| 1235 menu_item->SetIcon(*icon.ToImageSkia()); | 1236 menu_item->SetIcon(*icon.ToImageSkia()); |
| 1236 } | 1237 } |
| 1237 } | 1238 } |
| 1238 | 1239 |
| 1239 return menu_item; | 1240 return menu_item; |
| 1240 } | 1241 } |
| 1241 | 1242 |
| 1242 void WrenchMenu::CancelAndEvaluate(MenuModel* model, int index) { | 1243 void WrenchMenu::CancelAndEvaluate(MenuModel* model, int index) { |
| 1243 selected_menu_model_ = model; | 1244 selected_menu_model_ = model; |
| 1244 selected_index_ = index; | 1245 selected_index_ = index; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1256 | 1257 |
| 1257 model->AddObserver(this); | 1258 model->AddObserver(this); |
| 1258 | 1259 |
| 1259 // TODO(oshima): Replace with views only API. | 1260 // TODO(oshima): Replace with views only API. |
| 1260 views::Widget* parent = views::Widget::GetWidgetForNativeWindow( | 1261 views::Widget* parent = views::Widget::GetWidgetForNativeWindow( |
| 1261 browser_->window()->GetNativeWindow()); | 1262 browser_->window()->GetNativeWindow()); |
| 1262 bookmark_menu_delegate_.reset( | 1263 bookmark_menu_delegate_.reset( |
| 1263 new BookmarkMenuDelegate(browser_, | 1264 new BookmarkMenuDelegate(browser_, |
| 1264 browser_, | 1265 browser_, |
| 1265 parent, | 1266 parent, |
| 1266 first_bookmark_command_id_)); | 1267 kFirstBookmarkCommandId)); |
| 1267 bookmark_menu_delegate_->Init( | 1268 bookmark_menu_delegate_->Init( |
| 1268 this, bookmark_menu_, model->bookmark_bar_node(), 0, | 1269 this, bookmark_menu_, model->bookmark_bar_node(), 0, |
| 1269 BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS, | 1270 BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS, |
| 1270 bookmark_utils::LAUNCH_WRENCH_MENU); | 1271 bookmark_utils::LAUNCH_WRENCH_MENU); |
| 1271 } | 1272 } |
| 1273 |
| 1274 bool WrenchMenu::IsBookmarkCommand(int id) const { |
| 1275 return bookmark_menu_delegate_.get() && id >= kFirstBookmarkCommandId; |
| 1276 } |
| 1277 |
| 1278 bool WrenchMenu::IsRecentTabsCommand(int id) const { |
| 1279 return (recent_tabs_menu_model_delegate_.get() && |
| 1280 id >= kFirstRecentTabsCommandId && |
| 1281 id < kFirstBookmarkCommandId); |
| 1282 } |
| OLD | NEW |