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

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

Issue 6362007: [Mac] Organize all tab/tab strip files into chrome/browser/ui/cocoa/tabs/.... (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) 2010 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 #include "app/l10n_util_mac.h"
6 #include "base/mac/mac_util.h"
7 #import "chrome/browser/themes/browser_theme_provider.h"
8 #import "chrome/browser/ui/cocoa/menu_controller.h"
9 #import "chrome/browser/ui/cocoa/tab_controller.h"
10 #import "chrome/browser/ui/cocoa/tab_controller_target.h"
11 #import "chrome/browser/ui/cocoa/tab_view.h"
12 #import "chrome/browser/ui/cocoa/themed_window.h"
13 #import "chrome/common/extensions/extension.h"
14 #include "grit/generated_resources.h"
15
16 @implementation TabController
17
18 @synthesize action = action_;
19 @synthesize app = app_;
20 @synthesize loadingState = loadingState_;
21 @synthesize mini = mini_;
22 @synthesize pinned = pinned_;
23 @synthesize target = target_;
24 @synthesize iconView = iconView_;
25 @synthesize titleView = titleView_;
26 @synthesize closeButton = closeButton_;
27
28 namespace TabControllerInternal {
29
30 // A C++ delegate that handles enabling/disabling menu items and handling when
31 // a menu command is chosen. Also fixes up the menu item label for "pin/unpin
32 // tab".
33 class MenuDelegate : public ui::SimpleMenuModel::Delegate {
34 public:
35 explicit MenuDelegate(id<TabControllerTarget> target, TabController* owner)
36 : target_(target),
37 owner_(owner) {}
38
39 // Overridden from ui::SimpleMenuModel::Delegate
40 virtual bool IsCommandIdChecked(int command_id) const { return false; }
41 virtual bool IsCommandIdEnabled(int command_id) const {
42 TabStripModel::ContextMenuCommand command =
43 static_cast<TabStripModel::ContextMenuCommand>(command_id);
44 return [target_ isCommandEnabled:command forController:owner_];
45 }
46 virtual bool GetAcceleratorForCommandId(
47 int command_id,
48 ui::Accelerator* accelerator) { return false; }
49 virtual void ExecuteCommand(int command_id) {
50 TabStripModel::ContextMenuCommand command =
51 static_cast<TabStripModel::ContextMenuCommand>(command_id);
52 [target_ commandDispatch:command forController:owner_];
53 }
54
55 private:
56 id<TabControllerTarget> target_; // weak
57 TabController* owner_; // weak, owns me
58 };
59
60 } // TabControllerInternal namespace
61
62 // The min widths match the windows values and are sums of left + right
63 // padding, of which we have no comparable constants (we draw using paths, not
64 // images). The selected tab width includes the close button width.
65 + (CGFloat)minTabWidth { return 31; }
66 + (CGFloat)minSelectedTabWidth { return 46; }
67 + (CGFloat)maxTabWidth { return 220; }
68 + (CGFloat)miniTabWidth { return 53; }
69 + (CGFloat)appTabWidth { return 66; }
70
71 - (TabView*)tabView {
72 return static_cast<TabView*>([self view]);
73 }
74
75 - (id)init {
76 self = [super initWithNibName:@"TabView" bundle:base::mac::MainAppBundle()];
77 if (self != nil) {
78 isIconShowing_ = YES;
79 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
80 [defaultCenter addObserver:self
81 selector:@selector(viewResized:)
82 name:NSViewFrameDidChangeNotification
83 object:[self view]];
84 [defaultCenter addObserver:self
85 selector:@selector(themeChangedNotification:)
86 name:kBrowserThemeDidChangeNotification
87 object:nil];
88 }
89 return self;
90 }
91
92 - (void)dealloc {
93 [[NSNotificationCenter defaultCenter] removeObserver:self];
94 [[self tabView] setController:nil];
95 [super dealloc];
96 }
97
98 // The internals of |-setSelected:| but doesn't check if we're already set
99 // to |selected|. Pass the selection change to the subviews that need it and
100 // mark ourselves as needing a redraw.
101 - (void)internalSetSelected:(BOOL)selected {
102 selected_ = selected;
103 TabView* tabView = static_cast<TabView*>([self view]);
104 DCHECK([tabView isKindOfClass:[TabView class]]);
105 [tabView setState:selected];
106 [tabView cancelAlert];
107 [self updateVisibility];
108 [self updateTitleColor];
109 }
110
111 // Called when the tab's nib is done loading and all outlets are hooked up.
112 - (void)awakeFromNib {
113 // Remember the icon's frame, so that if the icon is ever removed, a new
114 // one can later replace it in the proper location.
115 originalIconFrame_ = [iconView_ frame];
116
117 // When the icon is removed, the title expands to the left to fill the space
118 // left by the icon. When the close button is removed, the title expands to
119 // the right to fill its space. These are the amounts to expand and contract
120 // titleView_ under those conditions. We don't have to explicilty save the
121 // offset between the title and the close button since we can just get that
122 // value for the close button's frame.
123 NSRect titleFrame = [titleView_ frame];
124 iconTitleXOffset_ = NSMinX(titleFrame) - NSMinX(originalIconFrame_);
125
126 [self internalSetSelected:selected_];
127 }
128
129 // Called when Cocoa wants to display the context menu. Lazily instantiate
130 // the menu based off of the cross-platform model. Re-create the menu and
131 // model every time to get the correct labels and enabling.
132 - (NSMenu*)menu {
133 contextMenuDelegate_.reset(
134 new TabControllerInternal::MenuDelegate(target_, self));
135 contextMenuModel_.reset(new TabMenuModel(contextMenuDelegate_.get(),
136 [self pinned]));
137 contextMenuController_.reset(
138 [[MenuController alloc] initWithModel:contextMenuModel_.get()
139 useWithPopUpButtonCell:NO]);
140 return [contextMenuController_ menu];
141 }
142
143 - (IBAction)closeTab:(id)sender {
144 if ([[self target] respondsToSelector:@selector(closeTab:)]) {
145 [[self target] performSelector:@selector(closeTab:)
146 withObject:[self view]];
147 }
148 }
149
150 - (void)setTitle:(NSString*)title {
151 [[self view] setToolTip:title];
152 if ([self mini] && ![self selected]) {
153 TabView* tabView = static_cast<TabView*>([self view]);
154 DCHECK([tabView isKindOfClass:[TabView class]]);
155 [tabView startAlert];
156 }
157 [super setTitle:title];
158 }
159
160 - (void)setSelected:(BOOL)selected {
161 if (selected_ != selected)
162 [self internalSetSelected:selected];
163 }
164
165 - (BOOL)selected {
166 return selected_;
167 }
168
169 - (void)setIconView:(NSView*)iconView {
170 [iconView_ removeFromSuperview];
171 iconView_ = iconView;
172 if ([self app]) {
173 NSRect appIconFrame = [iconView frame];
174 appIconFrame.origin = originalIconFrame_.origin;
175 // Center the icon.
176 appIconFrame.origin.x = ([TabController appTabWidth] -
177 NSWidth(appIconFrame)) / 2.0;
178 [iconView setFrame:appIconFrame];
179 } else {
180 [iconView_ setFrame:originalIconFrame_];
181 }
182 // Ensure that the icon is suppressed if no icon is set or if the tab is too
183 // narrow to display one.
184 [self updateVisibility];
185
186 if (iconView_)
187 [[self view] addSubview:iconView_];
188 }
189
190 - (NSString*)toolTip {
191 return [[self view] toolTip];
192 }
193
194 // Return a rough approximation of the number of icons we could fit in the
195 // tab. We never actually do this, but it's a helpful guide for determining
196 // how much space we have available.
197 - (int)iconCapacity {
198 CGFloat width = NSMaxX([closeButton_ frame]) - NSMinX(originalIconFrame_);
199 CGFloat iconWidth = NSWidth(originalIconFrame_);
200
201 return width / iconWidth;
202 }
203
204 // Returns YES if we should show the icon. When tabs get too small, we clip
205 // the favicon before the close button for selected tabs, and prefer the
206 // favicon for unselected tabs. The icon can also be suppressed more directly
207 // by clearing iconView_.
208 - (BOOL)shouldShowIcon {
209 if (!iconView_)
210 return NO;
211
212 if ([self mini])
213 return YES;
214
215 int iconCapacity = [self iconCapacity];
216 if ([self selected])
217 return iconCapacity >= 2;
218 return iconCapacity >= 1;
219 }
220
221 // Returns YES if we should be showing the close button. The selected tab
222 // always shows the close button.
223 - (BOOL)shouldShowCloseButton {
224 if ([self mini])
225 return NO;
226 return ([self selected] || [self iconCapacity] >= 3);
227 }
228
229 - (void)updateVisibility {
230 // iconView_ may have been replaced or it may be nil, so [iconView_ isHidden]
231 // won't work. Instead, the state of the icon is tracked separately in
232 // isIconShowing_.
233 BOOL newShowIcon = [self shouldShowIcon];
234
235 [iconView_ setHidden:!newShowIcon];
236 isIconShowing_ = newShowIcon;
237
238 // If the tab is a mini-tab, hide the title.
239 [titleView_ setHidden:[self mini]];
240
241 BOOL newShowCloseButton = [self shouldShowCloseButton];
242
243 [closeButton_ setHidden:!newShowCloseButton];
244
245 // Adjust the title view based on changes to the icon's and close button's
246 // visibility.
247 NSRect oldTitleFrame = [titleView_ frame];
248 NSRect newTitleFrame;
249 newTitleFrame.size.height = oldTitleFrame.size.height;
250 newTitleFrame.origin.y = oldTitleFrame.origin.y;
251
252 if (newShowIcon) {
253 newTitleFrame.origin.x = originalIconFrame_.origin.x + iconTitleXOffset_;
254 } else {
255 newTitleFrame.origin.x = originalIconFrame_.origin.x;
256 }
257
258 if (newShowCloseButton) {
259 newTitleFrame.size.width = NSMinX([closeButton_ frame]) -
260 newTitleFrame.origin.x;
261 } else {
262 newTitleFrame.size.width = NSMaxX([closeButton_ frame]) -
263 newTitleFrame.origin.x;
264 }
265
266 [titleView_ setFrame:newTitleFrame];
267 }
268
269 - (void)updateTitleColor {
270 NSColor* titleColor = nil;
271 ThemeProvider* theme = [[[self view] window] themeProvider];
272 if (theme && ![self selected]) {
273 titleColor =
274 theme->GetNSColor(BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT,
275 true);
276 }
277 // Default to the selected text color unless told otherwise.
278 if (theme && !titleColor) {
279 titleColor = theme->GetNSColor(BrowserThemeProvider::COLOR_TAB_TEXT,
280 true);
281 }
282 [titleView_ setTextColor:titleColor ? titleColor : [NSColor textColor]];
283 }
284
285 // Called when our view is resized. If it gets too small, start by hiding
286 // the close button and only show it if tab is selected. Eventually, hide the
287 // icon as well. We know that this is for our view because we only registered
288 // for notifications from our specific view.
289 - (void)viewResized:(NSNotification*)info {
290 [self updateVisibility];
291 }
292
293 - (void)themeChangedNotification:(NSNotification*)notification {
294 [self updateTitleColor];
295 }
296
297 // Called by the tabs to determine whether we are in rapid (tab) closure mode.
298 - (BOOL)inRapidClosureMode {
299 if ([[self target] respondsToSelector:@selector(inRapidClosureMode)]) {
300 return [[self target] performSelector:@selector(inRapidClosureMode)] ?
301 YES : NO;
302 }
303 return NO;
304 }
305
306 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/tab_controller.h ('k') | chrome/browser/ui/cocoa/tab_controller_target.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698