Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: chrome/browser/ui/cocoa/wrench_menu_controller.mm

Issue 6283005: [Mac] Move all the related files for the Wrench menu into a subdir of c/b/u/c... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/cocoa/wrench_menu_controller.h"
6
7 #include "app/l10n_util.h"
8 #include "base/sys_string_conversions.h"
9 #include "chrome/app/chrome_command_ids.h"
10 #include "chrome/browser/background_page_tracker.h"
11 #include "chrome/browser/metrics/user_metrics.h"
12 #import "chrome/browser/ui/cocoa/menu_tracked_root_view.h"
13 #import "chrome/browser/ui/cocoa/toolbar_controller.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_window.h"
16 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
17 #include "chrome/common/notification_observer.h"
18 #include "chrome/common/notification_service.h"
19 #include "chrome/common/notification_source.h"
20 #include "chrome/common/notification_type.h"
21 #include "grit/chromium_strings.h"
22 #include "grit/generated_resources.h"
23 #include "ui/base/models/menu_model.h"
24
25 @interface WrenchMenuController (Private)
26 - (void)adjustPositioning;
27 - (void)performCommandDispatch:(NSNumber*)tag;
28 - (NSButton*)zoomDisplay;
29 @end
30
31 namespace WrenchMenuControllerInternal {
32
33 class ZoomLevelObserver : public NotificationObserver {
34 public:
35 explicit ZoomLevelObserver(WrenchMenuController* controller)
36 : controller_(controller) {
37 registrar_.Add(this, NotificationType::ZOOM_LEVEL_CHANGED,
38 NotificationService::AllSources());
39 }
40
41 void Observe(NotificationType type,
42 const NotificationSource& source,
43 const NotificationDetails& details) {
44 DCHECK_EQ(type.value, NotificationType::ZOOM_LEVEL_CHANGED);
45 WrenchMenuModel* wrenchMenuModel = [controller_ wrenchMenuModel];
46 wrenchMenuModel->UpdateZoomControls();
47 const string16 level =
48 wrenchMenuModel->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY);
49 [[controller_ zoomDisplay] setTitle:SysUTF16ToNSString(level)];
50 }
51
52 private:
53 NotificationRegistrar registrar_;
54 WrenchMenuController* controller_; // Weak; owns this.
55 };
56
57 } // namespace WrenchMenuControllerInternal
58
59 @implementation WrenchMenuController
60
61 - (id)init {
62 if ((self = [super init])) {
63 observer_.reset(new WrenchMenuControllerInternal::ZoomLevelObserver(self));
64 }
65 return self;
66 }
67
68 - (void)addItemToMenu:(NSMenu*)menu
69 atIndex:(NSInteger)index
70 fromModel:(ui::MenuModel*)model
71 modelIndex:(int)modelIndex {
72 // Non-button item types should be built as normal items.
73 ui::MenuModel::ItemType type = model->GetTypeAt(modelIndex);
74 if (type != ui::MenuModel::TYPE_BUTTON_ITEM) {
75 [super addItemToMenu:menu
76 atIndex:index
77 fromModel:model
78 modelIndex:modelIndex];
79 return;
80 }
81
82 // Handle the special-cased menu items.
83 int command_id = model->GetCommandIdAt(modelIndex);
84 scoped_nsobject<NSMenuItem> customItem(
85 [[NSMenuItem alloc] initWithTitle:@""
86 action:nil
87 keyEquivalent:@""]);
88 switch (command_id) {
89 case IDC_EDIT_MENU:
90 DCHECK(editItem_);
91 [customItem setView:editItem_];
92 [editItem_ setMenuItem:customItem];
93 break;
94 case IDC_ZOOM_MENU:
95 DCHECK(zoomItem_);
96 [customItem setView:zoomItem_];
97 [zoomItem_ setMenuItem:customItem];
98 break;
99 default:
100 NOTREACHED();
101 break;
102 }
103 [self adjustPositioning];
104 [menu insertItem:customItem.get() atIndex:index];
105 }
106
107 - (NSMenu*)menu {
108 NSMenu* menu = [super menu];
109 if (![menu delegate]) {
110 [menu setDelegate:self];
111 }
112 return menu;
113 }
114
115 - (void)menuWillOpen:(NSMenu*)menu {
116 NSString* title = base::SysUTF16ToNSString(
117 [self wrenchMenuModel]->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY));
118 [[zoomItem_ viewWithTag:IDC_ZOOM_PERCENT_DISPLAY] setTitle:title];
119 UserMetrics::RecordAction(UserMetricsAction("ShowAppMenu"));
120
121 NSImage* icon = [self wrenchMenuModel]->browser()->window()->IsFullscreen() ?
122 [NSImage imageNamed:NSImageNameExitFullScreenTemplate] :
123 [NSImage imageNamed:NSImageNameEnterFullScreenTemplate];
124 [zoomFullScreen_ setImage:icon];
125 }
126
127 - (void)menuDidClose:(NSMenu*)menu {
128 // When the menu is closed, acknowledge the background pages so the badges go
129 // away.
130 BackgroundPageTracker::GetInstance()->AcknowledgeBackgroundPages();
131 }
132
133 // Used to dispatch commands from the Wrench menu. The custom items within the
134 // menu cannot be hooked up directly to First Responder because the window in
135 // which the controls reside is not the BrowserWindowController, but a
136 // NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system.
137 - (IBAction)dispatchWrenchMenuCommand:(id)sender {
138 NSInteger tag = [sender tag];
139 if (sender == zoomPlus_ || sender == zoomMinus_) {
140 // Do a direct dispatch rather than scheduling on the outermost run loop,
141 // which would not get hit until after the menu had closed.
142 [self performCommandDispatch:[NSNumber numberWithInt:tag]];
143
144 // The zoom buttons should not close the menu if opened sticky.
145 if ([sender respondsToSelector:@selector(isTracking)] &&
146 [sender performSelector:@selector(isTracking)]) {
147 [menu_ cancelTracking];
148 }
149 } else {
150 // The custom views within the Wrench menu are abnormal and keep the menu
151 // open after a target-action. Close the menu manually.
152 [menu_ cancelTracking];
153 [self dispatchCommandInternal:tag];
154 }
155 }
156
157 - (void)dispatchCommandInternal:(NSInteger)tag {
158 // Executing certain commands from the nested run loop of the menu can lead
159 // to wonky behavior (e.g. http://crbug.com/49716). To avoid this, schedule
160 // the dispatch on the outermost run loop.
161 [self performSelector:@selector(performCommandDispatch:)
162 withObject:[NSNumber numberWithInt:tag]
163 afterDelay:0.0];
164 }
165
166 // Used to perform the actual dispatch on the outermost runloop.
167 - (void)performCommandDispatch:(NSNumber*)tag {
168 [self wrenchMenuModel]->ExecuteCommand([tag intValue]);
169 }
170
171 - (WrenchMenuModel*)wrenchMenuModel {
172 return static_cast<WrenchMenuModel*>(model_);
173 }
174
175 // Fit the localized strings into the Cut/Copy/Paste control, then resize the
176 // whole menu item accordingly.
177 - (void)adjustPositioning {
178 const CGFloat kButtonPadding = 12;
179 CGFloat delta = 0;
180
181 // Go through the three buttons from right-to-left, adjusting the size to fit
182 // the localized strings while keeping them all aligned on their horizontal
183 // edges.
184 const size_t kAdjustViewCount = 3;
185 NSButton* views[kAdjustViewCount] = { editPaste_, editCopy_, editCut_ };
186 for (size_t i = 0; i < kAdjustViewCount; ++i) {
187 NSButton* button = views[i];
188 CGFloat originalWidth = NSWidth([button frame]);
189
190 // Do not let |-sizeToFit| change the height of the button.
191 NSSize size = [button frame].size;
192 [button sizeToFit];
193 size.width = [button frame].size.width + kButtonPadding;
194 [button setFrameSize:size];
195
196 CGFloat newWidth = size.width;
197 delta += newWidth - originalWidth;
198
199 NSRect frame = [button frame];
200 frame.origin.x -= delta;
201 [button setFrame:frame];
202 }
203
204 // Resize the menu item by the total amound the buttons changed so that the
205 // spacing between the buttons and the title remains the same.
206 NSRect itemFrame = [editItem_ frame];
207 itemFrame.size.width += delta;
208 [editItem_ setFrame:itemFrame];
209
210 // Also resize the superview of the buttons, which is an NSView used to slide
211 // when the item title is too big and GTM resizes it.
212 NSRect parentFrame = [[editCut_ superview] frame];
213 parentFrame.size.width += delta;
214 parentFrame.origin.x -= delta;
215 [[editCut_ superview] setFrame:parentFrame];
216 }
217
218 - (NSButton*)zoomDisplay {
219 return zoomDisplay_;
220 }
221
222 @end // @implementation WrenchMenuController
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698