OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #import "chrome/browser/cocoa/wrench_menu_controller.h" | 5 #import "chrome/browser/cocoa/wrench_menu_controller.h" |
6 | 6 |
7 #include "app/menus/menu_model.h" | 7 #include "app/menus/menu_model.h" |
8 #include "base/sys_string_conversions.h" | 8 #include "base/sys_string_conversions.h" |
9 #include "chrome/app/chrome_dll_resource.h" | 9 #include "chrome/app/chrome_dll_resource.h" |
10 #include "chrome/browser/browser.h" | 10 #include "chrome/browser/browser.h" |
11 #include "chrome/browser/browser_window.h" | 11 #include "chrome/browser/browser_window.h" |
12 #import "chrome/browser/cocoa/menu_tracked_root_view.h" | |
12 #import "chrome/browser/cocoa/toolbar_controller.h" | 13 #import "chrome/browser/cocoa/toolbar_controller.h" |
13 #include "chrome/browser/wrench_menu_model.h" | 14 #include "chrome/browser/wrench_menu_model.h" |
14 | 15 |
15 @interface WrenchMenuController (Private) | 16 @interface WrenchMenuController (Private) |
16 - (void)adjustPositioning; | 17 - (void)adjustPositioning; |
17 - (void)performCommandDispatch:(NSNumber*)tag; | 18 - (void)performCommandDispatch:(NSNumber*)tag; |
18 @end | 19 @end |
19 | 20 |
20 @implementation WrenchMenuController | 21 @implementation WrenchMenuController |
21 | 22 |
(...skipping 19 matching lines...) Expand all Loading... | |
41 // Handle the special-cased menu items. | 42 // Handle the special-cased menu items. |
42 int command_id = model->GetCommandIdAt(modelIndex); | 43 int command_id = model->GetCommandIdAt(modelIndex); |
43 scoped_nsobject<NSMenuItem> customItem( | 44 scoped_nsobject<NSMenuItem> customItem( |
44 [[NSMenuItem alloc] initWithTitle:@"" | 45 [[NSMenuItem alloc] initWithTitle:@"" |
45 action:nil | 46 action:nil |
46 keyEquivalent:@""]); | 47 keyEquivalent:@""]); |
47 switch (command_id) { | 48 switch (command_id) { |
48 case IDC_EDIT_MENU: | 49 case IDC_EDIT_MENU: |
49 DCHECK(editItem_); | 50 DCHECK(editItem_); |
50 [customItem setView:editItem_]; | 51 [customItem setView:editItem_]; |
52 [editItem_ setMenuItem:customItem]; | |
51 break; | 53 break; |
52 case IDC_ZOOM_MENU: | 54 case IDC_ZOOM_MENU: |
53 DCHECK(zoomItem_); | 55 DCHECK(zoomItem_); |
54 [customItem setView:zoomItem_]; | 56 [customItem setView:zoomItem_]; |
57 [zoomItem_ setMenuItem:customItem]; | |
55 break; | 58 break; |
56 default: | 59 default: |
57 NOTREACHED(); | 60 NOTREACHED(); |
58 break; | 61 break; |
59 } | 62 } |
60 [self adjustPositioning]; | 63 [self adjustPositioning]; |
61 [menu insertItem:customItem.get() atIndex:index]; | 64 [menu insertItem:customItem.get() atIndex:index]; |
62 } | 65 } |
63 | 66 |
64 - (NSMenu*)menu { | 67 - (NSMenu*)menu { |
65 NSMenu* menu = [super menu]; | 68 NSMenu* menu = [super menu]; |
66 if (![menu delegate]) { | 69 if (![menu delegate]) { |
67 [menu setDelegate:self]; | 70 [menu setDelegate:self]; |
68 } | 71 } |
69 return menu; | 72 return menu; |
70 } | 73 } |
71 | 74 |
72 - (void)menuWillOpen:(NSMenu*)menu { | 75 - (void)menuWillOpen:(NSMenu*)menu { |
73 NSString* title = base::SysUTF16ToNSString( | 76 NSString* title = base::SysUTF16ToNSString( |
74 [self wrenchMenuModel]->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY)); | 77 [self wrenchMenuModel]->GetLabelForCommandId(IDC_ZOOM_PERCENT_DISPLAY)); |
75 [[zoomItem_ viewWithTag:IDC_ZOOM_PERCENT_DISPLAY] setTitle:title]; | 78 [[zoomItem_ viewWithTag:IDC_ZOOM_PERCENT_DISPLAY] setTitle:title]; |
79 | |
76 bool plusEnabled = [self wrenchMenuModel]->IsCommandIdEnabled(IDC_ZOOM_PLUS); | 80 bool plusEnabled = [self wrenchMenuModel]->IsCommandIdEnabled(IDC_ZOOM_PLUS); |
77 bool minusEnabled = [self wrenchMenuModel]->IsCommandIdEnabled( | 81 bool minusEnabled = [self wrenchMenuModel]->IsCommandIdEnabled( |
78 IDC_ZOOM_MINUS); | 82 IDC_ZOOM_MINUS); |
79 | |
80 [zoomPlus_ setEnabled:plusEnabled]; | 83 [zoomPlus_ setEnabled:plusEnabled]; |
81 [zoomMinus_ setEnabled:minusEnabled]; | 84 [zoomMinus_ setEnabled:minusEnabled]; |
82 | 85 |
83 NSImage* icon = [self wrenchMenuModel]->browser()->window()->IsFullscreen() ? | 86 NSImage* icon = [self wrenchMenuModel]->browser()->window()->IsFullscreen() ? |
84 [NSImage imageNamed:NSImageNameExitFullScreenTemplate] : | 87 [NSImage imageNamed:NSImageNameExitFullScreenTemplate] : |
85 [NSImage imageNamed:NSImageNameEnterFullScreenTemplate]; | 88 [NSImage imageNamed:NSImageNameEnterFullScreenTemplate]; |
86 [zoomFullScreen_ setImage:icon]; | 89 [zoomFullScreen_ setImage:icon]; |
87 } | 90 } |
88 | 91 |
89 // Used to dispatch commands from the Wrench menu. The custom items within the | 92 // Used to dispatch commands from the Wrench menu. The custom items within the |
90 // menu cannot be hooked up directly to First Responder because the window in | 93 // menu cannot be hooked up directly to First Responder because the window in |
91 // which the controls reside is not the BrowserWindowController, but a | 94 // which the controls reside is not the BrowserWindowController, but a |
92 // NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system. | 95 // NSCarbonMenuWindow; this screws up the typical |-commandDispatch:| system. |
93 - (IBAction)dispatchWrenchMenuCommand:(id)sender { | 96 - (IBAction)dispatchWrenchMenuCommand:(id)sender { |
94 NSInteger tag = [sender tag]; | 97 NSInteger tag = [sender tag]; |
95 | |
96 // NSSegmentedControls (used for the Edit item) need a little help to get the | |
97 // command_id of the pressed item. | |
98 if ([sender isKindOfClass:[NSSegmentedControl class]]) | |
99 tag = [[sender cell] tagForSegment:[sender selectedSegment]]; | |
100 | |
101 // The custom views within the Wrench menu are abnormal and keep the menu open | 98 // The custom views within the Wrench menu are abnormal and keep the menu open |
102 // after a target-action. Close the menu manually. | 99 // after a target-action. Close the menu manually. |
103 // TODO(rsesek): It'd be great if the zoom buttons didn't have to close the | 100 // TODO(rsesek): It'd be great if the zoom buttons didn't have to close the |
104 // menu. See http://crbug.com/48679 for more info. | 101 // menu. See http://crbug.com/48679 for more info. |
105 [menu_ cancelTracking]; | 102 [menu_ cancelTracking]; |
106 [self dispatchCommandInternal:tag]; | 103 [self dispatchCommandInternal:tag]; |
107 } | 104 } |
108 | 105 |
109 - (void)dispatchCommandInternal:(NSInteger)tag { | 106 - (void)dispatchCommandInternal:(NSInteger)tag { |
110 // Executing certain commands from the nested run loop of the menu can lead | 107 // Executing certain commands from the nested run loop of the menu can lead |
111 // to wonky behavior (e.g. http://crbug.com/49716). To avoid this, schedule | 108 // to wonky behavior (e.g. http://crbug.com/49716). To avoid this, schedule |
112 // the dispatch on the outermost run loop. | 109 // the dispatch on the outermost run loop. |
113 [self performSelector:@selector(performCommandDispatch:) | 110 [self performSelector:@selector(performCommandDispatch:) |
114 withObject:[NSNumber numberWithInt:tag] | 111 withObject:[NSNumber numberWithInt:tag] |
115 afterDelay:0.0]; | 112 afterDelay:0.0]; |
116 } | 113 } |
117 | 114 |
118 // Used to perform the actual dispatch on the outermost runloop. | 115 // Used to perform the actual dispatch on the outermost runloop. |
119 - (void)performCommandDispatch:(NSNumber*)tag { | 116 - (void)performCommandDispatch:(NSNumber*)tag { |
120 [self wrenchMenuModel]->ExecuteCommand([tag intValue]); | 117 [self wrenchMenuModel]->ExecuteCommand([tag intValue]); |
121 } | 118 } |
122 | 119 |
123 - (WrenchMenuModel*)wrenchMenuModel { | 120 - (WrenchMenuModel*)wrenchMenuModel { |
124 return static_cast<WrenchMenuModel*>(model_); | 121 return static_cast<WrenchMenuModel*>(model_); |
125 } | 122 } |
126 | 123 |
127 // Fit the localized strings into the Cut/Copy/Paste control, then resize the | 124 // Fit the localized strings into the Cut/Copy/Paste control, then resize the |
128 // whole menu item accordingly. | 125 // whole menu item accordingly. |
129 - (void)adjustPositioning { | 126 - (void)adjustPositioning { |
127 const CGFloat kButtonPadding = 12; | |
128 CGFloat delta = 0; | |
129 | |
130 // Go through the three buttons from right-to-left, adjusting the size to fit | |
131 // the localized strings while keeping them all aligned on their horizontal | |
132 // edges. | |
133 const size_t kAdjustViewCount = 3; | |
134 NSButton* views[kAdjustViewCount] = { editPaste_, editCopy_, editCut_ }; | |
135 for (size_t i = 0; i < kAdjustViewCount; ++i) { | |
Nico
2010/08/03 18:21:10
nit: why not
NSButton* views[] = { editPaste_,
| |
136 NSButton* button = views[i]; | |
137 CGFloat originalWidth = NSWidth([button frame]); | |
138 | |
139 // Do not let |-sizeToFit| change the height of the button. | |
140 NSSize size = [button frame].size; | |
141 [button sizeToFit]; | |
142 size.width = [button frame].size.width + kButtonPadding; | |
143 [button setFrameSize:size]; | |
144 | |
145 CGFloat newWidth = size.width; | |
146 delta += newWidth - originalWidth; | |
147 | |
148 NSRect frame = [button frame]; | |
149 frame.origin.x -= delta; | |
150 [button setFrame:frame]; | |
151 } | |
152 | |
153 // Resize the menu item by the total amound the buttons changed so that the | |
154 // spacing between the buttons and the title remains the same. | |
130 NSRect itemFrame = [editItem_ frame]; | 155 NSRect itemFrame = [editItem_ frame]; |
131 NSRect controlFrame = [editControl_ frame]; | 156 itemFrame.size.width += delta; |
132 | |
133 CGFloat originalControlWidth = NSWidth(controlFrame); | |
134 // Maintain the carefully pixel-pushed gap between the edge of the menu and | |
135 // the rightmost control. | |
136 CGFloat edge = NSWidth(itemFrame) - | |
137 (controlFrame.origin.x + originalControlWidth); | |
138 | |
139 // Resize the edit segmented control to fit the localized strings. | |
140 [editControl_ sizeToFit]; | |
141 controlFrame = [editControl_ frame]; | |
142 CGFloat resizeAmount = NSWidth(controlFrame) - originalControlWidth; | |
143 | |
144 // Adjust the size of the entire menu item to account for changes in the size | |
145 // of the segmented control. | |
146 itemFrame.size.width += resizeAmount; | |
147 [editItem_ setFrame:itemFrame]; | 157 [editItem_ setFrame:itemFrame]; |
148 | 158 |
149 // Keep the spacing between the right edges of the menu and the control. | 159 // Also resize the superview of the buttons, which is an NSView used to slide |
150 controlFrame.origin.x = NSWidth(itemFrame) - edge - NSWidth(controlFrame); | 160 // when the item title is too big and GTM resizes it. |
151 [editControl_ setFrame:controlFrame]; | 161 NSRect parentFrame = [[editCut_ superview] frame]; |
162 parentFrame.size.width += delta; | |
163 parentFrame.origin.x -= delta; | |
164 [[editCut_ superview] setFrame:parentFrame]; | |
152 } | 165 } |
153 | 166 |
154 @end // @implementation WrenchMenuController | 167 @end // @implementation WrenchMenuController |
OLD | NEW |