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

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

Issue 7313007: [Mac] Remove ProfileMenuButton now that AvatarButton exists. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 5 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/profile_menu_button.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "chrome/browser/ui/profile_menu_model.h"
11 #import "third_party/GTM/AppKit/GTMFadeTruncatingTextFieldCell.h"
12
13 namespace {
14
15 const CGFloat kTabWidth = 24;
16 const CGFloat kTabHeight = 13;
17 const CGFloat kTabArrowWidth = 7;
18 const CGFloat kTabArrowHeight = 4;
19 const CGFloat kTabRoundRectRadius = 5;
20 const CGFloat kTabDisplayNameMarginY = 3;
21
22 NSColor* GetWhiteWithAlpha(CGFloat alpha) {
23 return [NSColor colorWithCalibratedWhite:1.0 alpha:alpha];
24 }
25
26 NSColor* GetBlackWithAlpha(CGFloat alpha) {
27 return [NSColor colorWithCalibratedWhite:0.0 alpha:alpha];
28 }
29
30 } // namespace
31
32 @interface ProfileMenuButton (Private)
33 - (void)commonInit;
34 - (NSPoint)popUpMenuPosition;
35 - (NSImage*)tabImage;
36 - (NSRect)textFieldRect;
37 - (NSBezierPath*)tabPathWithRect:(NSRect)rect
38 radius:(CGFloat)radius;
39 - (NSBezierPath*)downArrowPathWithRect:(NSRect)rect;
40 - (NSImage*)tabImageWithSize:(NSSize)tabSize
41 fillColor:(NSColor*)fillColor
42 isPressed:(BOOL)isPressed;
43 @end
44
45 @implementation ProfileMenuButton
46
47 @synthesize shouldShowProfileDisplayName = shouldShowProfileDisplayName_;
48
49 - (void)commonInit {
50 textFieldCell_.reset(
51 [[GTMFadeTruncatingTextFieldCell alloc] initTextCell:@""]);
52 [textFieldCell_ setBackgroundStyle:NSBackgroundStyleRaised];
53 [textFieldCell_ setAlignment:NSRightTextAlignment];
54 [textFieldCell_ setFont:[NSFont systemFontOfSize:
55 [NSFont smallSystemFontSize]]];
56
57 [self setOpenMenuOnClick:YES];
58
59 profile_menu_model_.reset(new ProfileMenuModel);
60 menu_.reset([[MenuController alloc] initWithModel:profile_menu_model_.get()
61 useWithPopUpButtonCell:NO]);
62 }
63
64 - (id)initWithFrame:(NSRect)frame {
65 if ((self = [super initWithFrame:frame]))
66 [self commonInit];
67 return self;
68 }
69
70 - (id)initWithCoder:(NSCoder*)decoder {
71 if ((self = [super initWithCoder:decoder]))
72 [self commonInit];
73 return self;
74 }
75
76 - (void)dealloc {
77 [[NSNotificationCenter defaultCenter] removeObserver:self];
78 [super dealloc];
79 }
80
81 - (NSString*)profileDisplayName {
82 return [textFieldCell_ stringValue];
83 }
84
85 - (void)setProfileDisplayName:(NSString*)name {
86 if (![[textFieldCell_ stringValue] isEqual:name]) {
87 [textFieldCell_ setStringValue:name];
88 [self setNeedsDisplay:YES];
89 }
90 }
91
92 - (void)setShouldShowProfileDisplayName:(BOOL)flag {
93 shouldShowProfileDisplayName_ = flag;
94 [self setNeedsDisplay:YES];
95 }
96
97 - (BOOL)isFlipped {
98 return NO;
99 }
100
101 - (void)viewWillMoveToWindow:(NSWindow*)newWindow {
102 if ([self window] == newWindow)
103 return;
104
105 if ([self window]) {
106 [[NSNotificationCenter defaultCenter]
107 removeObserver:self
108 name:NSWindowDidBecomeMainNotification
109 object:[self window]];
110 [[NSNotificationCenter defaultCenter]
111 removeObserver:self
112 name:NSWindowDidResignMainNotification
113 object:[self window]];
114 }
115
116 if (newWindow) {
117 [[NSNotificationCenter defaultCenter]
118 addObserver:self
119 selector:@selector(onWindowFocusChanged:)
120 name:NSWindowDidBecomeMainNotification
121 object:newWindow];
122 [[NSNotificationCenter defaultCenter]
123 addObserver:self
124 selector:@selector(onWindowFocusChanged:)
125 name:NSWindowDidResignMainNotification
126 object:newWindow];
127 }
128 }
129
130 - (void)onWindowFocusChanged:(NSNotification*)note {
131 [self setNeedsDisplay:YES];
132 }
133
134 - (NSRect)tabRect {
135 NSRect bounds = [self bounds];
136 NSRect tabRect;
137 tabRect.size.width = kTabWidth;
138 tabRect.size.height = kTabHeight;
139 tabRect.origin.x = NSMaxX(bounds) - NSWidth(tabRect);
140 tabRect.origin.y = NSMaxY(bounds) - NSHeight(tabRect);
141 return tabRect;
142 }
143
144 - (NSRect)textFieldRect {
145 NSRect bounds = [self bounds];
146 NSSize desiredSize = [textFieldCell_ cellSize];
147
148 NSRect textRect = bounds;
149 textRect.size.height = std::min(desiredSize.height, NSHeight(bounds));
150
151 // For some reason there's always a 2 pixel gap on the right side of the
152 // text field. Fix it by moving the text field to the right by 2 pixels.
153 textRect.origin.x += 2;
154
155 return textRect;
156 }
157
158 - (NSView*)hitTest:(NSPoint)aPoint {
159 NSView* probe = [super hitTest:aPoint];
160 if (probe != self)
161 return probe;
162
163 NSPoint viewPoint = [self convertPoint:aPoint fromView:[self superview]];
164 BOOL isFlipped = [self isFlipped];
165 if (NSMouseInRect(viewPoint, [self tabRect], isFlipped))
166 return self;
167 else
168 return nil;
169 }
170
171 - (NSBezierPath*)tabPathWithRect:(NSRect)rect
172 radius:(CGFloat)radius {
173 const NSRect innerRect = NSInsetRect(rect, radius, radius);
174 NSBezierPath* path = [NSBezierPath bezierPath];
175
176 // Top left
177 [path moveToPoint:NSMakePoint(NSMinX(rect), NSMaxY(rect))];
178
179 // Bottom left
180 [path lineToPoint:NSMakePoint(NSMinX(rect), NSMinY(innerRect))];
181 [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(innerRect),
182 NSMinY(innerRect))
183 radius:radius
184 startAngle:180
185 endAngle:270
186 clockwise:NO];
187
188 // Bottom right
189 [path lineToPoint:NSMakePoint(NSMaxX(innerRect), NSMinY(rect))];
190 [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(innerRect),
191 NSMinY(innerRect))
192 radius:radius
193 startAngle:270
194 endAngle:360
195 clockwise:NO];
196
197 // Top right
198 [path lineToPoint:NSMakePoint(NSMaxX(rect), NSMaxY(rect))];
199
200 [path closePath];
201 return path;
202 }
203
204 - (NSBezierPath*)downArrowPathWithRect:(NSRect)rect {
205 NSBezierPath* path = [NSBezierPath bezierPath];
206
207 // Top left
208 [path moveToPoint:NSMakePoint(NSMinX(rect), NSMaxY(rect))];
209
210 // Bottom middle
211 [path lineToPoint:NSMakePoint(NSMidX(rect), NSMinY(rect))];
212
213 // Top right
214 [path lineToPoint:NSMakePoint(NSMaxX(rect), NSMaxY(rect))];
215
216 [path closePath];
217 return path;
218 }
219
220 - (NSImage*)tabImageWithSize:(NSSize)tabSize
221 fillColor:(NSColor*)fillColor
222 isPressed:(BOOL)isPressed {
223 NSImage* image = [[[NSImage alloc] initWithSize:tabSize] autorelease];
224 [image lockFocus];
225
226 // White shadow for inset look
227 [[NSGraphicsContext currentContext] saveGraphicsState];
228 scoped_nsobject<NSShadow> tabShadow([[NSShadow alloc] init]);
229 [tabShadow.get() setShadowOffset:NSMakeSize(0, -1)];
230 [tabShadow setShadowBlurRadius:0];
231 [tabShadow.get() setShadowColor:GetWhiteWithAlpha(0.6)];
232 [tabShadow set];
233
234 // Gray outline
235 NSRect tabRect = NSMakeRect(0, 1, tabSize.width, tabSize.height - 1);
236 NSBezierPath* outlinePath = [self tabPathWithRect:tabRect
237 radius:kTabRoundRectRadius];
238 [[NSColor colorWithCalibratedWhite:0.44 alpha:1.0] set];
239 [outlinePath fill];
240
241 [[NSGraphicsContext currentContext] restoreGraphicsState];
242
243 // Fill
244 NSRect fillRect = NSInsetRect(tabRect, 1, 0);
245 fillRect.size.height -= 1;
246 fillRect.origin.y += 1;
247 NSBezierPath* fillPath = [self tabPathWithRect:fillRect
248 radius:kTabRoundRectRadius - 1];
249 [fillColor set];
250 [fillPath fill];
251
252 // Shading for fill to make the bottom of the tab slightly darker.
253 scoped_nsobject<NSGradient> gradient([[NSGradient alloc]
254 initWithStartingColor:GetBlackWithAlpha(isPressed ? 0.2 : 0.0)
255 endingColor:GetBlackWithAlpha(0.2)]);
256 [gradient drawInBezierPath:fillPath angle:270];
257
258 // Highlight on top
259 NSRect highlightRect = NSInsetRect(tabRect, 1, 0);
260 highlightRect.size.height = 1;
261 highlightRect.origin.y = NSMaxY(tabRect) - highlightRect.size.height;
262 [GetWhiteWithAlpha(0.5) set];
263 NSRectFillUsingOperation(highlightRect, NSCompositeSourceOver);
264
265 // Arrow shadow
266 [[NSGraphicsContext currentContext] saveGraphicsState];
267 scoped_nsobject<NSShadow> arrowShadow([[NSShadow alloc] init]);
268 [arrowShadow.get() setShadowOffset:NSMakeSize(0, -1)];
269 [arrowShadow setShadowBlurRadius:0];
270 [arrowShadow.get() setShadowColor:GetBlackWithAlpha(0.6)];
271 [arrowShadow set];
272
273 // Down arrow
274 NSRect arrowRect;
275 arrowRect.size.width = kTabArrowWidth;
276 arrowRect.size.height = kTabArrowHeight;
277 arrowRect.origin.x = NSMinX(tabRect) + roundf((NSWidth(tabRect) -
278 NSWidth(arrowRect)) / 2.0);
279 arrowRect.origin.y = NSMinY(tabRect) + roundf((tabRect.size.height -
280 arrowRect.size.height) / 2.0);
281 NSBezierPath* arrowPath = [self downArrowPathWithRect:arrowRect];
282 if (isPressed)
283 [[NSColor colorWithCalibratedWhite:0.8 alpha:1.0] set];
284 else
285 [[NSColor whiteColor] set];
286 [arrowPath fill];
287
288 [[NSGraphicsContext currentContext] restoreGraphicsState];
289
290 [image unlockFocus];
291 return image;
292 }
293
294 - (NSImage*)tabImage {
295 BOOL isPressed = [[self cell] isHighlighted];
296
297 // Invalidate the cached image if necessary.
298 if (cachedTabImageIsPressed_ != isPressed) {
299 cachedTabImageIsPressed_ = isPressed;
300 cachedTabImage_.reset();
301 }
302
303 if (cachedTabImage_)
304 return cachedTabImage_;
305
306 // TODO: Use different colors for different profiles and tint for
307 // the current browser theme.
308 NSColor* fillColor = [NSColor colorWithCalibratedRed:122.0/255.0
309 green:177.0/255.0
310 blue:252.0/255.0
311 alpha:1.0];
312 NSRect tabRect = [self tabRect];
313 cachedTabImage_.reset([[self tabImageWithSize:tabRect.size
314 fillColor:fillColor
315 isPressed:isPressed] retain]);
316 return cachedTabImage_;
317 }
318
319 - (void)drawRect:(NSRect)rect {
320 CGFloat alpha = [[self window] isMainWindow] ? 1.0 : 0.5;
321 [[self tabImage] drawInRect:[self tabRect]
322 fromRect:NSZeroRect
323 operation:NSCompositeSourceOver
324 fraction:alpha];
325
326 if (shouldShowProfileDisplayName_) {
327 NSColor* textColor = [[self window] isMainWindow] ?
328 GetBlackWithAlpha(0.6) : GetBlackWithAlpha(0.4);
329 if (![[textFieldCell_ textColor] isEqual:textColor])
330 [textFieldCell_ setTextColor:textColor];
331 [textFieldCell_ drawWithFrame:[self textFieldRect] inView:self];
332 }
333 }
334
335 - (NSSize)desiredControlSize {
336 NSSize size = [self tabRect].size;
337
338 if (shouldShowProfileDisplayName_) {
339 NSSize textFieldSize = [textFieldCell_ cellSize];
340 size.width = std::max(size.width, textFieldSize.width);
341 size.height += textFieldSize.height + kTabDisplayNameMarginY;
342 }
343
344 size.width = ceil(size.width);
345 size.height = ceil(size.height);
346 return size;
347 }
348
349 - (NSSize)minControlSize {
350 return [self tabRect].size;
351 }
352
353 // Overridden from MenuButton.
354 - (NSMenu*)attachedMenu {
355 return [menu_.get() menu];
356 }
357
358 // Overridden from MenuButton.
359 - (NSRect)menuRect {
360 return [self tabRect];
361 }
362
363 @end
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/profile_menu_button.h ('k') | chrome/browser/ui/cocoa/profile_menu_button_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698