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/bookmarks/bookmark_stats.h" | 16 #include "chrome/browser/bookmarks/bookmark_stats.h" |
17 #include "chrome/browser/chrome_notification_types.h" | 17 #include "chrome/browser/chrome_notification_types.h" |
18 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/search/search.h" | 19 #include "chrome/browser/search/search.h" |
20 #include "chrome/browser/ui/browser.h" | 20 #include "chrome/browser/ui/browser.h" |
21 #include "chrome/browser/ui/browser_window.h" | 21 #include "chrome/browser/ui/browser_window.h" |
22 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 22 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
23 #include "chrome/browser/ui/toolbar/wrench_menu_model.h" | |
24 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" | 23 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" |
25 #include "chrome/browser/ui/views/wrench_menu_observer.h" | 24 #include "chrome/browser/ui/views/wrench_menu_observer.h" |
26 #include "content/public/browser/host_zoom_map.h" | 25 #include "content/public/browser/host_zoom_map.h" |
27 #include "content/public/browser/notification_observer.h" | 26 #include "content/public/browser/notification_observer.h" |
28 #include "content/public/browser/notification_registrar.h" | 27 #include "content/public/browser/notification_registrar.h" |
29 #include "content/public/browser/notification_source.h" | 28 #include "content/public/browser/notification_source.h" |
30 #include "content/public/browser/notification_types.h" | 29 #include "content/public/browser/notification_types.h" |
31 #include "content/public/browser/user_metrics.h" | 30 #include "content/public/browser/user_metrics.h" |
32 #include "content/public/browser/web_contents.h" | 31 #include "content/public/browser/web_contents.h" |
33 #include "grit/chromium_strings.h" | 32 #include "grit/chromium_strings.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 const SkColor kTouchButtonText = 0xff5a5a5a; | 81 const SkColor kTouchButtonText = 0xff5a5a5a; |
83 | 82 |
84 // Horizontal padding on the edges of the buttons. | 83 // Horizontal padding on the edges of the buttons. |
85 const int kHorizontalPadding = 6; | 84 const int kHorizontalPadding = 6; |
86 // Horizontal padding for a touch enabled menu. | 85 // Horizontal padding for a touch enabled menu. |
87 const int kHorizontalTouchPadding = 15; | 86 const int kHorizontalTouchPadding = 15; |
88 | 87 |
89 // Menu items which have embedded buttons should have this height in pixel. | 88 // Menu items which have embedded buttons should have this height in pixel. |
90 const int kMenuItemContainingButtonsHeight = 43; | 89 const int kMenuItemContainingButtonsHeight = 43; |
91 | 90 |
92 // Returns true if |command_id| identifies a bookmark menu item. | |
93 bool IsBookmarkCommand(int command_id) { | |
94 return command_id >= WrenchMenuModel::kMinBookmarkCommandId && | |
95 command_id <= WrenchMenuModel::kMaxBookmarkCommandId; | |
96 } | |
97 | |
98 // Returns true if |command_id| identifies a recent tabs menu item. | |
99 bool IsRecentTabsCommand(int command_id) { | |
100 return command_id >= WrenchMenuModel::kMinRecentTabsCommandId && | |
101 command_id <= WrenchMenuModel::kMaxRecentTabsCommandId; | |
102 } | |
103 | |
104 // Subclass of ImageButton whose preferred size includes the size of the border. | 91 // Subclass of ImageButton whose preferred size includes the size of the border. |
105 class FullscreenButton : public ImageButton { | 92 class FullscreenButton : public ImageButton { |
106 public: | 93 public: |
107 explicit FullscreenButton(views::ButtonListener* listener) | 94 explicit FullscreenButton(views::ButtonListener* listener) |
108 : ImageButton(listener) { } | 95 : ImageButton(listener) { } |
109 | 96 |
110 // Overridden from ImageButton. | 97 // Overridden from ImageButton. |
111 virtual gfx::Size GetPreferredSize() OVERRIDE { | 98 virtual gfx::Size GetPreferredSize() OVERRIDE { |
112 gfx::Size pref = ImageButton::GetPreferredSize(); | 99 gfx::Size pref = ImageButton::GetPreferredSize(); |
113 if (border()) { | 100 if (border()) { |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 // WARNING: this may be NULL during shutdown. | 404 // WARNING: this may be NULL during shutdown. |
418 MenuModel* menu_model_; | 405 MenuModel* menu_model_; |
419 | 406 |
420 DISALLOW_COPY_AND_ASSIGN(WrenchMenuView); | 407 DISALLOW_COPY_AND_ASSIGN(WrenchMenuView); |
421 }; | 408 }; |
422 | 409 |
423 class ButtonContainerMenuItemView : public MenuItemView { | 410 class ButtonContainerMenuItemView : public MenuItemView { |
424 public: | 411 public: |
425 // Constructor for use with button containing menu items which have a | 412 // Constructor for use with button containing menu items which have a |
426 // different height then normal items. | 413 // different height then normal items. |
427 ButtonContainerMenuItemView(MenuItemView* parent, int command_id, int height) | 414 ButtonContainerMenuItemView(MenuItemView* parent, int id, int height) |
428 : MenuItemView(parent, command_id, MenuItemView::NORMAL), | 415 : MenuItemView(parent, id, MenuItemView::NORMAL), |
429 height_(height) { | 416 height_(height) { |
430 }; | 417 }; |
431 | 418 |
432 // Overridden from MenuItemView. | 419 // Overridden from MenuItemView. |
433 virtual gfx::Size GetChildPreferredSize() OVERRIDE { | 420 virtual gfx::Size GetChildPreferredSize() OVERRIDE { |
434 gfx::Size size = MenuItemView::GetChildPreferredSize(); | 421 gfx::Size size = MenuItemView::GetChildPreferredSize(); |
435 // When there is a height override given, we need to deduct our spacing | 422 // When there is a height override given, we need to deduct our spacing |
436 // above and below to get to the correct height to return here for the | 423 // above and below to get to the correct height to return here for the |
437 // child item. | 424 // child item. |
438 int height = height_ - GetTopMargin() - GetBottomMargin(); | 425 int height = height_ - GetTopMargin() - GetBottomMargin(); |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 menu_item_(menu_item) { | 757 menu_item_(menu_item) { |
771 model_->SetMenuModelDelegate(this); | 758 model_->SetMenuModelDelegate(this); |
772 } | 759 } |
773 | 760 |
774 virtual ~RecentTabsMenuModelDelegate() { | 761 virtual ~RecentTabsMenuModelDelegate() { |
775 model_->SetMenuModelDelegate(NULL); | 762 model_->SetMenuModelDelegate(NULL); |
776 } | 763 } |
777 | 764 |
778 // ui::MenuModelDelegate implementation: | 765 // ui::MenuModelDelegate implementation: |
779 virtual void OnIconChanged(int index) OVERRIDE { | 766 virtual void OnIconChanged(int index) OVERRIDE { |
780 int command_id = model_->GetCommandIdAt(index); | 767 // |index| specifies position in children items of |menu_item_| starting at |
| 768 // 0, its corresponding command id as used in the children menu item views |
| 769 // follows that of the parent menu item view |menu_item_|. |
| 770 int command_id = menu_item_->GetCommand() + 1 + index; |
781 views::MenuItemView* item = menu_item_->GetMenuItemByID(command_id); | 771 views::MenuItemView* item = menu_item_->GetMenuItemByID(command_id); |
782 DCHECK(item); | 772 DCHECK(item); |
783 gfx::Image icon; | 773 gfx::Image icon; |
784 if (model_->GetIconAt(index, &icon)) | 774 if (model_->GetIconAt(index, &icon)) |
785 item->SetIcon(*icon.ToImageSkia()); | 775 item->SetIcon(*icon.ToImageSkia()); |
786 } | 776 } |
787 | 777 |
788 // Return the specific menu width of recent tab menu item if |command_id| | 778 // Return the specific menu width of recent tab menu item if |command_id| |
789 // refers to one of recent tabs menu items, else return -1. | 779 // refers to one of recent tabs menu items, else return -1. |
790 int GetMaxWidthForMenu(MenuItemView* menu) { | 780 int GetMaxWidthForMenu(MenuItemView* menu) { |
791 views::SubmenuView* submenu = menu_item_->GetSubmenu(); | 781 views::SubmenuView* submenu = menu_item_->GetSubmenu(); |
792 if (!submenu) | 782 if (!submenu) |
793 return -1; | 783 return -1; |
794 const int kMaxMenuItemWidth = 320; | 784 const int kMaxMenuItemWidth = 320; |
795 return menu->GetCommand() == menu_item_->GetCommand() ? | 785 return menu->GetCommand() >= menu_item_->GetCommand() && |
| 786 menu->GetCommand() <= |
| 787 menu_item_->GetCommand() + submenu->GetMenuItemCount() ? |
796 kMaxMenuItemWidth : -1; | 788 kMaxMenuItemWidth : -1; |
797 } | 789 } |
798 | 790 |
799 const gfx::Font* GetLabelFontAt(int index) const { | 791 const gfx::Font* GetLabelFontAt(int index) const { |
800 return model_->GetLabelFontAt(index); | 792 return model_->GetLabelFontAt(index); |
801 } | 793 } |
802 | 794 |
803 bool GetForegroundColorAt(int index, | 795 bool GetForegroundColor(int command_id, |
804 bool is_hovered, | 796 bool is_hovered, |
805 SkColor* override_color) const { | 797 SkColor* override_color) const { |
806 // The items for which we get a font, should be shown in black. | 798 // The items for which we get a font, should be shown in black. |
807 if (GetLabelFontAt(index)) { | 799 if (GetLabelFontAt(command_id)) { |
808 *override_color = SK_ColorBLACK; | 800 *override_color = SK_ColorBLACK; |
809 return true; | 801 return true; |
810 } | 802 } |
811 return false; | 803 return false; |
812 } | 804 } |
813 | 805 |
814 private: | 806 private: |
815 ui::MenuModel* model_; | 807 ui::MenuModel* model_; |
816 views::MenuItemView* menu_item_; | 808 views::MenuItemView* menu_item_; |
817 | 809 |
818 DISALLOW_COPY_AND_ASSIGN(RecentTabsMenuModelDelegate); | 810 DISALLOW_COPY_AND_ASSIGN(RecentTabsMenuModelDelegate); |
819 }; | 811 }; |
820 | 812 |
821 // WrenchMenu ------------------------------------------------------------------ | 813 // WrenchMenu ------------------------------------------------------------------ |
822 | 814 |
823 WrenchMenu::WrenchMenu(Browser* browser, | 815 WrenchMenu::WrenchMenu(Browser* browser, |
824 bool use_new_menu, | 816 bool use_new_menu, |
825 bool supports_new_separators) | 817 bool supports_new_separators) |
826 : root_(NULL), | 818 : root_(NULL), |
827 browser_(browser), | 819 browser_(browser), |
828 selected_menu_model_(NULL), | 820 selected_menu_model_(NULL), |
829 selected_index_(0), | 821 selected_index_(0), |
830 bookmark_menu_(NULL), | 822 bookmark_menu_(NULL), |
831 feedback_menu_item_(NULL), | 823 feedback_menu_item_(NULL), |
| 824 first_bookmark_command_id_(0), |
| 825 first_recent_tabs_command_id_(-1), |
| 826 last_recent_tabs_command_id_(-1), |
832 use_new_menu_(use_new_menu), | 827 use_new_menu_(use_new_menu), |
833 supports_new_separators_(supports_new_separators) { | 828 supports_new_separators_(supports_new_separators) { |
834 registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED, | 829 registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED, |
835 content::Source<Profile>(browser_->profile())); | 830 content::Source<Profile>(browser_->profile())); |
836 } | 831 } |
837 | 832 |
838 WrenchMenu::~WrenchMenu() { | 833 WrenchMenu::~WrenchMenu() { |
839 if (bookmark_menu_delegate_.get()) { | 834 if (bookmark_menu_delegate_.get()) { |
840 BookmarkModel* model = BookmarkModelFactory::GetForProfile( | 835 BookmarkModel* model = BookmarkModelFactory::GetForProfile( |
841 browser_->profile()); | 836 browser_->profile()); |
842 if (model) | 837 if (model) |
843 model->RemoveObserver(this); | 838 model->RemoveObserver(this); |
844 } | 839 } |
845 FOR_EACH_OBSERVER(WrenchMenuObserver, observer_list_, WrenchMenuDestroyed()); | 840 FOR_EACH_OBSERVER(WrenchMenuObserver, observer_list_, WrenchMenuDestroyed()); |
846 } | 841 } |
847 | 842 |
848 void WrenchMenu::Init(ui::MenuModel* model) { | 843 void WrenchMenu::Init(ui::MenuModel* model) { |
849 DCHECK(!root_); | 844 DCHECK(!root_); |
850 root_ = new MenuItemView(this); | 845 root_ = new MenuItemView(this); |
851 root_->set_has_icons(true); // We have checks, radios and icons, set this | 846 root_->set_has_icons(true); // We have checks, radios and icons, set this |
852 // so we get the taller menu style. | 847 // so we get the taller menu style. |
853 PopulateMenu(root_, model); | 848 int next_id = 1; |
854 | 849 PopulateMenu(root_, model, &next_id); |
855 #if defined(DEBUG) | 850 first_bookmark_command_id_ = next_id + 1; |
856 // Verify that the reserved command ID's for bookmarks menu are not used. | |
857 for (int i = WrenchMenuModel:kMinBookmarkCommandId; | |
858 i <= WrenchMenuModel::kMaxBookmarkCommandId; ++i) | |
859 DCHECK(command_id_to_entry_.find(i) == command_id_to_entry_.end()); | |
860 #endif // defined(DEBUG) | |
861 | |
862 menu_runner_.reset(new views::MenuRunner(root_)); | 851 menu_runner_.reset(new views::MenuRunner(root_)); |
863 } | 852 } |
864 | 853 |
865 void WrenchMenu::RunMenu(views::MenuButton* host) { | 854 void WrenchMenu::RunMenu(views::MenuButton* host) { |
866 gfx::Point screen_loc; | 855 gfx::Point screen_loc; |
867 views::View::ConvertPointToScreen(host, &screen_loc); | 856 views::View::ConvertPointToScreen(host, &screen_loc); |
868 gfx::Rect bounds(screen_loc, host->size()); | 857 gfx::Rect bounds(screen_loc, host->size()); |
869 content::RecordAction(UserMetricsAction("ShowAppMenu")); | 858 content::RecordAction(UserMetricsAction("ShowAppMenu")); |
870 if (menu_runner_->RunMenuAt(host->GetWidget(), host, bounds, | 859 if (menu_runner_->RunMenuAt(host->GetWidget(), host, bounds, |
871 MenuItemView::TOPRIGHT, ui::MENU_SOURCE_NONE, | 860 MenuItemView::TOPRIGHT, ui::MENU_SOURCE_NONE, |
(...skipping 26 matching lines...) Expand all Loading... |
898 } | 887 } |
899 | 888 |
900 void WrenchMenu::AddObserver(WrenchMenuObserver* observer) { | 889 void WrenchMenu::AddObserver(WrenchMenuObserver* observer) { |
901 observer_list_.AddObserver(observer); | 890 observer_list_.AddObserver(observer); |
902 } | 891 } |
903 | 892 |
904 void WrenchMenu::RemoveObserver(WrenchMenuObserver* observer) { | 893 void WrenchMenu::RemoveObserver(WrenchMenuObserver* observer) { |
905 observer_list_.RemoveObserver(observer); | 894 observer_list_.RemoveObserver(observer); |
906 } | 895 } |
907 | 896 |
908 const gfx::Font* WrenchMenu::GetLabelFont(int command_id) const { | 897 const gfx::Font* WrenchMenu::GetLabelFont(int index) const { |
909 if (IsRecentTabsCommand(command_id)) { | 898 if (is_recent_tabs_command(index)) { |
910 return recent_tabs_menu_model_delegate_->GetLabelFontAt( | 899 return recent_tabs_menu_model_delegate_->GetLabelFontAt( |
911 ModelIndexFromCommandId(command_id)); | 900 index - first_recent_tabs_command_id_); |
912 } | 901 } |
913 return NULL; | 902 return NULL; |
914 } | 903 } |
915 | 904 |
916 bool WrenchMenu::GetForegroundColor(int command_id, | 905 bool WrenchMenu::GetForegroundColor(int command_id, |
917 bool is_hovered, | 906 bool is_hovered, |
918 SkColor* override_color) const { | 907 SkColor* override_color) const { |
919 if (IsRecentTabsCommand(command_id)) { | 908 if (is_recent_tabs_command(command_id)) { |
920 return recent_tabs_menu_model_delegate_->GetForegroundColorAt( | 909 return recent_tabs_menu_model_delegate_->GetForegroundColor( |
921 ModelIndexFromCommandId(command_id), is_hovered, override_color); | 910 command_id - first_recent_tabs_command_id_, |
| 911 is_hovered, |
| 912 override_color); |
922 } | 913 } |
923 return false; | 914 return false; |
924 } | 915 } |
925 | 916 |
926 string16 WrenchMenu::GetTooltipText(int command_id, | 917 string16 WrenchMenu::GetTooltipText(int id, |
927 const gfx::Point& p) const { | 918 const gfx::Point& p) const { |
928 return IsBookmarkCommand(command_id) ? | 919 return is_bookmark_command(id) ? |
929 bookmark_menu_delegate_->GetTooltipText(command_id, p) : string16(); | 920 bookmark_menu_delegate_->GetTooltipText(id, p) : string16(); |
930 } | 921 } |
931 | 922 |
932 bool WrenchMenu::IsTriggerableEvent(views::MenuItemView* menu, | 923 bool WrenchMenu::IsTriggerableEvent(views::MenuItemView* menu, |
933 const ui::Event& e) { | 924 const ui::Event& e) { |
934 return IsBookmarkCommand(menu->GetCommand()) ? | 925 return is_bookmark_command(menu->GetCommand()) ? |
935 bookmark_menu_delegate_->IsTriggerableEvent(menu, e) : | 926 bookmark_menu_delegate_->IsTriggerableEvent(menu, e) : |
936 MenuDelegate::IsTriggerableEvent(menu, e); | 927 MenuDelegate::IsTriggerableEvent(menu, e); |
937 } | 928 } |
938 | 929 |
939 bool WrenchMenu::GetDropFormats( | 930 bool WrenchMenu::GetDropFormats( |
940 MenuItemView* menu, | 931 MenuItemView* menu, |
941 int* formats, | 932 int* formats, |
942 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { | 933 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { |
943 CreateBookmarkMenu(); | 934 CreateBookmarkMenu(); |
944 return bookmark_menu_delegate_.get() && | 935 return bookmark_menu_delegate_.get() && |
(...skipping 10 matching lines...) Expand all Loading... |
955 const ui::OSExchangeData& data) { | 946 const ui::OSExchangeData& data) { |
956 CreateBookmarkMenu(); | 947 CreateBookmarkMenu(); |
957 return bookmark_menu_delegate_.get() && | 948 return bookmark_menu_delegate_.get() && |
958 bookmark_menu_delegate_->CanDrop(menu, data); | 949 bookmark_menu_delegate_->CanDrop(menu, data); |
959 } | 950 } |
960 | 951 |
961 int WrenchMenu::GetDropOperation( | 952 int WrenchMenu::GetDropOperation( |
962 MenuItemView* item, | 953 MenuItemView* item, |
963 const ui::DropTargetEvent& event, | 954 const ui::DropTargetEvent& event, |
964 DropPosition* position) { | 955 DropPosition* position) { |
965 return IsBookmarkCommand(item->GetCommand()) ? | 956 return is_bookmark_command(item->GetCommand()) ? |
966 bookmark_menu_delegate_->GetDropOperation(item, event, position) : | 957 bookmark_menu_delegate_->GetDropOperation(item, event, position) : |
967 ui::DragDropTypes::DRAG_NONE; | 958 ui::DragDropTypes::DRAG_NONE; |
968 } | 959 } |
969 | 960 |
970 int WrenchMenu::OnPerformDrop(MenuItemView* menu, | 961 int WrenchMenu::OnPerformDrop(MenuItemView* menu, |
971 DropPosition position, | 962 DropPosition position, |
972 const ui::DropTargetEvent& event) { | 963 const ui::DropTargetEvent& event) { |
973 if (!IsBookmarkCommand(menu->GetCommand())) | 964 if (!is_bookmark_command(menu->GetCommand())) |
974 return ui::DragDropTypes::DRAG_NONE; | 965 return ui::DragDropTypes::DRAG_NONE; |
975 | 966 |
976 int result = bookmark_menu_delegate_->OnPerformDrop(menu, position, event); | 967 int result = bookmark_menu_delegate_->OnPerformDrop(menu, position, event); |
977 return result; | 968 return result; |
978 } | 969 } |
979 | 970 |
980 bool WrenchMenu::ShowContextMenu(MenuItemView* source, | 971 bool WrenchMenu::ShowContextMenu(MenuItemView* source, |
981 int command_id, | 972 int id, |
982 const gfx::Point& p, | 973 const gfx::Point& p, |
983 ui::MenuSourceType source_type) { | 974 ui::MenuSourceType source_type) { |
984 return IsBookmarkCommand(command_id) ? | 975 return is_bookmark_command(id) ? |
985 bookmark_menu_delegate_->ShowContextMenu(source, command_id, p, | 976 bookmark_menu_delegate_->ShowContextMenu(source, id, p, |
986 source_type) : | 977 source_type) : |
987 false; | 978 false; |
988 } | 979 } |
989 | 980 |
990 bool WrenchMenu::CanDrag(MenuItemView* menu) { | 981 bool WrenchMenu::CanDrag(MenuItemView* menu) { |
991 return IsBookmarkCommand(menu->GetCommand()) ? | 982 return is_bookmark_command(menu->GetCommand()) ? |
992 bookmark_menu_delegate_->CanDrag(menu) : false; | 983 bookmark_menu_delegate_->CanDrag(menu) : false; |
993 } | 984 } |
994 | 985 |
995 void WrenchMenu::WriteDragData(MenuItemView* sender, | 986 void WrenchMenu::WriteDragData(MenuItemView* sender, |
996 ui::OSExchangeData* data) { | 987 ui::OSExchangeData* data) { |
997 DCHECK(IsBookmarkCommand(sender->GetCommand())); | 988 DCHECK(is_bookmark_command(sender->GetCommand())); |
998 return bookmark_menu_delegate_->WriteDragData(sender, data); | 989 return bookmark_menu_delegate_->WriteDragData(sender, data); |
999 } | 990 } |
1000 | 991 |
1001 int WrenchMenu::GetDragOperations(MenuItemView* sender) { | 992 int WrenchMenu::GetDragOperations(MenuItemView* sender) { |
1002 return IsBookmarkCommand(sender->GetCommand()) ? | 993 return is_bookmark_command(sender->GetCommand()) ? |
1003 bookmark_menu_delegate_->GetDragOperations(sender) : | 994 bookmark_menu_delegate_->GetDragOperations(sender) : |
1004 MenuDelegate::GetDragOperations(sender); | 995 MenuDelegate::GetDragOperations(sender); |
1005 } | 996 } |
1006 | 997 |
1007 int WrenchMenu::GetMaxWidthForMenu(MenuItemView* menu) { | 998 int WrenchMenu::GetMaxWidthForMenu(MenuItemView* menu) { |
1008 if (IsBookmarkCommand(menu->GetCommand())) | 999 if (is_bookmark_command(menu->GetCommand())) |
1009 return bookmark_menu_delegate_->GetMaxWidthForMenu(menu); | 1000 return bookmark_menu_delegate_->GetMaxWidthForMenu(menu); |
1010 int max_width = -1; | 1001 int max_width = -1; |
1011 // If recent tabs menu is available, it will decide if |menu| is one of recent | 1002 // If recent tabs menu is available, it will decide if |menu| is one of recent |
1012 // tabs; if yes, it would return the menu width for recent tabs. | 1003 // tabs; if yes, it would return the menu width for recent tabs. |
1013 // otherwise, it would return -1. | 1004 // otherwise, it would return -1. |
1014 if (recent_tabs_menu_model_delegate_.get()) | 1005 if (recent_tabs_menu_model_delegate_.get()) |
1015 max_width = recent_tabs_menu_model_delegate_->GetMaxWidthForMenu(menu); | 1006 max_width = recent_tabs_menu_model_delegate_->GetMaxWidthForMenu(menu); |
1016 if (max_width == -1) | 1007 if (max_width == -1) |
1017 max_width = MenuDelegate::GetMaxWidthForMenu(menu); | 1008 max_width = MenuDelegate::GetMaxWidthForMenu(menu); |
1018 return max_width; | 1009 return max_width; |
1019 } | 1010 } |
1020 | 1011 |
1021 bool WrenchMenu::IsItemChecked(int command_id) const { | 1012 bool WrenchMenu::IsItemChecked(int id) const { |
1022 if (IsBookmarkCommand(command_id)) | 1013 if (is_bookmark_command(id)) |
1023 return false; | 1014 return false; |
1024 | 1015 |
1025 const Entry& entry = command_id_to_entry_.find(command_id)->second; | 1016 const Entry& entry = id_to_entry_.find(id)->second; |
1026 return entry.first->IsItemCheckedAt(entry.second); | 1017 return entry.first->IsItemCheckedAt(entry.second); |
1027 } | 1018 } |
1028 | 1019 |
1029 bool WrenchMenu::IsCommandEnabled(int command_id) const { | 1020 bool WrenchMenu::IsCommandEnabled(int id) const { |
1030 if (IsBookmarkCommand(command_id)) | 1021 if (is_bookmark_command(id)) |
1031 return true; | 1022 return true; |
1032 | 1023 |
1033 if (command_id == 0) | 1024 if (id == 0) |
1034 return false; // The root item. | 1025 return false; // The root item. |
1035 | 1026 |
| 1027 const Entry& entry = id_to_entry_.find(id)->second; |
| 1028 int command_id = entry.first->GetCommandIdAt(entry.second); |
1036 // The items representing the cut menu (cut/copy/paste) and zoom menu | 1029 // The items representing the cut menu (cut/copy/paste) and zoom menu |
1037 // (increment/decrement/reset) are always enabled. The child views of these | 1030 // (increment/decrement/reset) are always enabled. The child views of these |
1038 // items enabled state updates appropriately. | 1031 // items enabled state updates appropriately. |
1039 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) | 1032 return command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS || |
1040 return true; | 1033 entry.first->IsEnabledAt(entry.second); |
1041 | |
1042 const Entry& entry = command_id_to_entry_.find(command_id)->second; | |
1043 return entry.first->IsEnabledAt(entry.second); | |
1044 } | 1034 } |
1045 | 1035 |
1046 void WrenchMenu::ExecuteCommand(int command_id, int mouse_event_flags) { | 1036 void WrenchMenu::ExecuteCommand(int id, int mouse_event_flags) { |
1047 if (IsBookmarkCommand(command_id)) { | 1037 if (is_bookmark_command(id)) { |
1048 bookmark_menu_delegate_->ExecuteCommand(command_id, mouse_event_flags); | 1038 bookmark_menu_delegate_->ExecuteCommand(id, mouse_event_flags); |
1049 return; | 1039 return; |
1050 } | 1040 } |
1051 | 1041 |
| 1042 // Not a bookmark |
| 1043 const Entry& entry = id_to_entry_.find(id)->second; |
| 1044 int command_id = entry.first->GetCommandIdAt(entry.second); |
| 1045 |
1052 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { | 1046 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { |
1053 // These items are represented by child views. If ExecuteCommand is invoked | 1047 // These items are represented by child views. If ExecuteCommand is invoked |
1054 // it means the user clicked on the area around the buttons and we should | 1048 // it means the user clicked on the area around the buttons and we should |
1055 // not do anyting. | 1049 // not do anyting. |
1056 return; | 1050 return; |
1057 } | 1051 } |
1058 | 1052 |
1059 const Entry& entry = command_id_to_entry_.find(command_id)->second; | |
1060 return entry.first->ActivatedAt(entry.second, mouse_event_flags); | 1053 return entry.first->ActivatedAt(entry.second, mouse_event_flags); |
1061 } | 1054 } |
1062 | 1055 |
1063 bool WrenchMenu::GetAccelerator(int command_id, ui::Accelerator* accelerator) { | 1056 bool WrenchMenu::GetAccelerator(int id, ui::Accelerator* accelerator) { |
1064 if (IsBookmarkCommand(command_id)) | 1057 if (is_bookmark_command(id)) |
1065 return false; | 1058 return false; |
| 1059 IDToEntry::iterator ix = id_to_entry_.find(id); |
| 1060 if (ix == id_to_entry_.end()) { |
| 1061 // There is no entry for this id. |
| 1062 return false; |
| 1063 } |
1066 | 1064 |
| 1065 const Entry& entry = ix->second; |
| 1066 int command_id = entry.first->GetCommandIdAt(entry.second); |
1067 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { | 1067 if (command_id == IDC_CUT || command_id == IDC_ZOOM_MINUS) { |
1068 // These have special child views; don't show the accelerator for them. | 1068 // These have special child views; don't show the accelerator for them. |
1069 return false; | 1069 return false; |
1070 } | 1070 } |
1071 | 1071 |
1072 CommandIDToEntry::iterator ix = command_id_to_entry_.find(command_id); | |
1073 const Entry& entry = ix->second; | |
1074 ui::Accelerator menu_accelerator; | 1072 ui::Accelerator menu_accelerator; |
1075 if (!entry.first->GetAcceleratorAt(entry.second, &menu_accelerator)) | 1073 if (!entry.first->GetAcceleratorAt(entry.second, &menu_accelerator)) |
1076 return false; | 1074 return false; |
1077 | 1075 |
1078 *accelerator = ui::Accelerator(menu_accelerator.key_code(), | 1076 *accelerator = ui::Accelerator(menu_accelerator.key_code(), |
1079 menu_accelerator.modifiers()); | 1077 menu_accelerator.modifiers()); |
1080 return true; | 1078 return true; |
1081 } | 1079 } |
1082 | 1080 |
1083 void WrenchMenu::WillShowMenu(MenuItemView* menu) { | 1081 void WrenchMenu::WillShowMenu(MenuItemView* menu) { |
(...skipping 29 matching lines...) Expand all Loading... |
1113 // A change in the global errors list can add or remove items from the | 1111 // A change in the global errors list can add or remove items from the |
1114 // menu. Close the menu to avoid have a stale menu on-screen. | 1112 // menu. Close the menu to avoid have a stale menu on-screen. |
1115 root_->Cancel(); | 1113 root_->Cancel(); |
1116 break; | 1114 break; |
1117 default: | 1115 default: |
1118 NOTREACHED(); | 1116 NOTREACHED(); |
1119 } | 1117 } |
1120 } | 1118 } |
1121 | 1119 |
1122 void WrenchMenu::PopulateMenu(MenuItemView* parent, | 1120 void WrenchMenu::PopulateMenu(MenuItemView* parent, |
1123 MenuModel* model) { | 1121 MenuModel* model, |
| 1122 int* next_id) { |
1124 for (int i = 0, max = model->GetItemCount(); i < max; ++i) { | 1123 for (int i = 0, max = model->GetItemCount(); i < max; ++i) { |
1125 // 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 |
1126 // use instead of the normal height. | 1125 // use instead of the normal height. |
1127 int height = 0; | 1126 int height = 0; |
1128 if (use_new_menu_ && | 1127 if (use_new_menu_ && |
1129 (model->GetCommandIdAt(i) == IDC_CUT || | 1128 (model->GetCommandIdAt(i) == IDC_CUT || |
1130 model->GetCommandIdAt(i) == IDC_ZOOM_MINUS)) | 1129 model->GetCommandIdAt(i) == IDC_ZOOM_MINUS)) |
1131 height = kMenuItemContainingButtonsHeight; | 1130 height = kMenuItemContainingButtonsHeight; |
1132 | 1131 |
1133 MenuItemView* item = AppendMenuItem( | 1132 MenuItemView* item = AppendMenuItem( |
1134 parent, model, i, model->GetTypeAt(i), height); | 1133 parent, model, i, model->GetTypeAt(i), next_id, height); |
1135 | 1134 |
1136 if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) | 1135 if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { |
1137 PopulateMenu(item, model->GetSubmenuModelAt(i)); | 1136 bool is_recent_tabs_menu = |
| 1137 model->GetCommandIdAt(i) == IDC_RECENT_TABS_MENU; |
| 1138 if (is_recent_tabs_menu) |
| 1139 first_recent_tabs_command_id_ = *next_id; |
| 1140 PopulateMenu(item, model->GetSubmenuModelAt(i), next_id); |
| 1141 if (is_recent_tabs_menu) |
| 1142 last_recent_tabs_command_id_ = *next_id - 1; |
| 1143 } |
1138 | 1144 |
1139 const ui::NativeTheme* native_theme = GetNativeTheme(); | 1145 const ui::NativeTheme* native_theme = GetNativeTheme(); |
1140 | 1146 |
1141 switch (model->GetCommandIdAt(i)) { | 1147 switch (model->GetCommandIdAt(i)) { |
1142 case IDC_CUT: | 1148 case IDC_CUT: |
1143 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(i)); | 1149 DCHECK_EQ(MenuModel::TYPE_COMMAND, model->GetTypeAt(i)); |
1144 DCHECK_LT(i + 2, max); | 1150 DCHECK_LT(i + 2, max); |
1145 DCHECK_EQ(IDC_COPY, model->GetCommandIdAt(i + 1)); | 1151 DCHECK_EQ(IDC_COPY, model->GetCommandIdAt(i + 1)); |
1146 DCHECK_EQ(IDC_PASTE, model->GetCommandIdAt(i + 2)); | 1152 DCHECK_EQ(IDC_PASTE, model->GetCommandIdAt(i + 2)); |
1147 item->SetTitle(l10n_util::GetStringUTF16(IDS_EDIT2)); | 1153 item->SetTitle(l10n_util::GetStringUTF16(IDS_EDIT2)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 default: | 1188 default: |
1183 break; | 1189 break; |
1184 } | 1190 } |
1185 } | 1191 } |
1186 } | 1192 } |
1187 | 1193 |
1188 MenuItemView* WrenchMenu::AppendMenuItem(MenuItemView* parent, | 1194 MenuItemView* WrenchMenu::AppendMenuItem(MenuItemView* parent, |
1189 MenuModel* model, | 1195 MenuModel* model, |
1190 int index, | 1196 int index, |
1191 MenuModel::ItemType menu_type, | 1197 MenuModel::ItemType menu_type, |
| 1198 int* next_id, |
1192 int height) { | 1199 int height) { |
1193 int command_id = model->GetCommandIdAt(index); | 1200 int id = (*next_id)++; |
1194 DCHECK(command_id > -1 || | |
1195 (command_id == -1 && | |
1196 model->GetTypeAt(index) == MenuModel::TYPE_SEPARATOR)); | |
1197 | 1201 |
1198 if (command_id > -1) { // Don't add separators to |command_id_to_entry_|. | 1202 id_to_entry_[id].first = model; |
1199 // All command ID's should be unique except for IDC_SHOW_HISTORY which is | 1203 id_to_entry_[id].second = index; |
1200 // in both wrench menu and RecentTabs submenu, | |
1201 if (command_id != IDC_SHOW_HISTORY) { | |
1202 DCHECK(command_id_to_entry_.find(command_id) == | |
1203 command_id_to_entry_.end()) | |
1204 << "command ID " << command_id << " already exists!"; | |
1205 } | |
1206 command_id_to_entry_[command_id].first = model; | |
1207 command_id_to_entry_[command_id].second = index; | |
1208 } | |
1209 | 1204 |
1210 MenuItemView* menu_item = NULL; | 1205 MenuItemView* menu_item = NULL; |
1211 if (height > 0) { | 1206 if (height > 0) { |
1212 // For menu items with a special menu height we use our special class to be | 1207 // For menu items with a special menu height we use our special class to be |
1213 // able to modify the item height. | 1208 // able to modify the item height. |
1214 menu_item = new ButtonContainerMenuItemView(parent, command_id, height); | 1209 menu_item = new ButtonContainerMenuItemView(parent, id, height); |
1215 parent->GetSubmenu()->AddChildView(menu_item); | 1210 parent->GetSubmenu()->AddChildView(menu_item); |
1216 } else { | 1211 } else { |
1217 // For all other cases we use the more generic way to add menu items. | 1212 // For all other cases we use the more generic way to add menu items. |
1218 menu_item = views::MenuModelAdapter::AppendMenuItemFromModel( | 1213 menu_item = views::MenuModelAdapter::AppendMenuItemFromModel( |
1219 model, index, parent, command_id); | 1214 model, index, parent, id); |
1220 } | 1215 } |
1221 | 1216 |
1222 if (menu_item) { | 1217 if (menu_item) { |
1223 // Flush all buttons to the right side of the menu for the new menu type. | 1218 // Flush all buttons to the right side of the menu for the new menu type. |
1224 menu_item->set_use_right_margin(!use_new_menu_); | 1219 menu_item->set_use_right_margin(!use_new_menu_); |
1225 menu_item->SetVisible(model->IsVisibleAt(index)); | 1220 menu_item->SetVisible(model->IsVisibleAt(index)); |
1226 | 1221 |
1227 if (menu_type == MenuModel::TYPE_COMMAND && model->HasIcons()) { | 1222 if (menu_type == MenuModel::TYPE_COMMAND && model->HasIcons()) { |
1228 gfx::Image icon; | 1223 gfx::Image icon; |
1229 if (model->GetIconAt(index, &icon)) | 1224 if (model->GetIconAt(index, &icon)) |
(...skipping 21 matching lines...) Expand all Loading... |
1251 | 1246 |
1252 model->AddObserver(this); | 1247 model->AddObserver(this); |
1253 | 1248 |
1254 // TODO(oshima): Replace with views only API. | 1249 // TODO(oshima): Replace with views only API. |
1255 views::Widget* parent = views::Widget::GetWidgetForNativeWindow( | 1250 views::Widget* parent = views::Widget::GetWidgetForNativeWindow( |
1256 browser_->window()->GetNativeWindow()); | 1251 browser_->window()->GetNativeWindow()); |
1257 bookmark_menu_delegate_.reset( | 1252 bookmark_menu_delegate_.reset( |
1258 new BookmarkMenuDelegate(browser_, | 1253 new BookmarkMenuDelegate(browser_, |
1259 browser_, | 1254 browser_, |
1260 parent, | 1255 parent, |
1261 WrenchMenuModel::kMinBookmarkCommandId, | 1256 first_bookmark_command_id_)); |
1262 WrenchMenuModel::kMaxBookmarkCommandId)); | |
1263 bookmark_menu_delegate_->Init(this, | 1257 bookmark_menu_delegate_->Init(this, |
1264 bookmark_menu_, | 1258 bookmark_menu_, |
1265 model->bookmark_bar_node(), | 1259 model->bookmark_bar_node(), |
1266 0, | 1260 0, |
1267 BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS, | 1261 BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS, |
1268 BOOKMARK_LAUNCH_LOCATION_WRENCH_MENU); | 1262 BOOKMARK_LAUNCH_LOCATION_WRENCH_MENU); |
1269 } | 1263 } |
1270 | |
1271 int WrenchMenu::ModelIndexFromCommandId(int command_id) const { | |
1272 CommandIDToEntry::const_iterator ix = command_id_to_entry_.find(command_id); | |
1273 DCHECK(ix != command_id_to_entry_.end()); | |
1274 return ix->second.second; | |
1275 } | |
OLD | NEW |