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

Side by Side Diff: chrome/browser/cocoa/status_bubble_mac.mm

Issue 196043: Pretty-up the blocked popup view by sharing code from the status bubble. Bloc... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 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
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/cocoa/status_bubble_mac.h" 5 #include "chrome/browser/cocoa/status_bubble_mac.h"
6 6
7 #include "app/gfx/text_elider.h" 7 #include "app/gfx/text_elider.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "base/sys_string_conversions.h" 9 #include "base/sys_string_conversions.h"
10 #import "chrome/browser/cocoa/bubble_view.h"
10 #include "googleurl/src/gurl.h" 11 #include "googleurl/src/gurl.h"
11 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" 12 #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h"
12 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" 13 #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h"
13 #import "third_party/GTM/AppKit/GTMTheme.h" 14 #import "third_party/GTM/AppKit/GTMTheme.h"
14 15
15 namespace { 16 namespace {
16 17
17 const int kWindowHeight = 18; 18 const int kWindowHeight = 18;
18 // The width of the bubble in relation to the width of the parent window. 19 // The width of the bubble in relation to the width of the parent window.
19 const float kWindowWidthPercent = 1.0f/3.0f; 20 const float kWindowWidthPercent = 1.0f/3.0f;
20 21
21 // How close the mouse can get to the infobubble before it starts sliding 22 // How close the mouse can get to the infobubble before it starts sliding
22 // off-screen. 23 // off-screen.
23 const int kMousePadding = 20; 24 const int kMousePadding = 20;
24 25
25 const int kTextPadding = 3; 26 const int kTextPadding = 3;
26 const int kTextPositionX = 4;
27 const int kTextPositionY = 2;
28
29 const float kWindowFill = 0.8f;
30 const float kWindowEdge = 0.7f;
31
32 // The roundedness of the edges of our bubble.
33 const int kBubbleCornerRadius = 4.0f;
34 27
35 // How long each fade should last for. 28 // How long each fade should last for.
36 const int kShowFadeDuration = 0.120f; 29 const int kShowFadeDuration = 0.120f;
37 const int kHideFadeDuration = 0.200f; 30 const int kHideFadeDuration = 0.200f;
38 31
39 } 32 }
40 33
41 // TODO(avi): 34 // TODO(avi):
42 // - do display delay 35 // - do display delay
43 36
44 enum BubbleStyle {
45 STYLE_BOTTOM, // Hanging off the bottom of the parent window
46 STYLE_FLOATING, // Between BOTTOM and STANDARD
47 STYLE_STANDARD // Nestled in the corner of the parent window
48 };
49
50 @interface StatusBubbleViewCocoa : NSView {
51 @private
52 NSString* content_;
53 BubbleStyle style_;
54 NSWindow* parent_;
55 }
56
57 - (void)setContent:(NSString*)content;
58 - (void)setStyle:(BubbleStyle)style;
59 - (void)setParent:(NSWindow*)parent;
60 - (NSFont*)font;
61 @end
62
63 StatusBubbleMac::StatusBubbleMac(NSWindow* parent, id delegate) 37 StatusBubbleMac::StatusBubbleMac(NSWindow* parent, id delegate)
64 : parent_(parent), 38 : parent_(parent),
65 delegate_(delegate), 39 delegate_(delegate),
66 window_(nil), 40 window_(nil),
67 status_text_(nil), 41 status_text_(nil),
68 url_text_(nil), 42 url_text_(nil),
69 is_download_shelf_visible_(false) { 43 is_download_shelf_visible_(false) {
70 } 44 }
71 45
72 StatusBubbleMac::~StatusBubbleMac() { 46 StatusBubbleMac::~StatusBubbleMac() {
73 Hide(); 47 Hide();
74 } 48 }
75 49
76 void StatusBubbleMac::SetStatus(const std::wstring& status) { 50 void StatusBubbleMac::SetStatus(const std::wstring& status) {
77 Create(); 51 Create();
78 52
79 NSString* status_ns = base::SysWideToNSString(status); 53 NSString* status_ns = base::SysWideToNSString(status);
80 54
81 SetStatus(status_ns, false); 55 SetStatus(status_ns, false);
82 } 56 }
83 57
84 void StatusBubbleMac::SetURL(const GURL& url, const std::wstring& languages) { 58 void StatusBubbleMac::SetURL(const GURL& url, const std::wstring& languages) {
85 Create(); 59 Create();
86 60
87 NSRect frame = [window_ frame]; 61 NSRect frame = [window_ frame];
88 int text_width = static_cast<int>(frame.size.width - 62 int text_width = static_cast<int>(frame.size.width -
89 kTextPositionX - 63 kBubbleViewTextPositionX -
90 kTextPadding); 64 kTextPadding);
91 NSFont* font = [[window_ contentView] font]; 65 NSFont* font = [[window_ contentView] font];
92 gfx::Font font_chr = 66 gfx::Font font_chr =
93 gfx::Font::CreateFont(base::SysNSStringToWide([font fontName]), 67 gfx::Font::CreateFont(base::SysNSStringToWide([font fontName]),
94 [font pointSize]); 68 [font pointSize]);
95 69
96 std::wstring status = gfx::ElideUrl(url, font_chr, text_width, languages); 70 std::wstring status = gfx::ElideUrl(url, font_chr, text_width, languages);
97 NSString* status_ns = base::SysWideToNSString(status); 71 NSString* status_ns = base::SysWideToNSString(status);
98 72
99 SetStatus(status_ns, true); 73 SetStatus(status_ns, true);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 // scaled by how horizontally far away the cursor is from the bubble. 144 // scaled by how horizontally far away the cursor is from the bubble.
171 if (cursor_location.x > 0) { 145 if (cursor_location.x > 0) {
172 offset = offset * ((kMousePadding - cursor_location.x) / kMousePadding); 146 offset = offset * ((kMousePadding - cursor_location.x) / kMousePadding);
173 } 147 }
174 148
175 // Cap the offset and change the visual presentation of the bubble 149 // Cap the offset and change the visual presentation of the bubble
176 // depending on where it ends up (so that rounded corners square off 150 // depending on where it ends up (so that rounded corners square off
177 // and mate to the edges of the tab content). 151 // and mate to the edges of the tab content).
178 if (offset >= NSHeight(window_frame)) { 152 if (offset >= NSHeight(window_frame)) {
179 offset = NSHeight(window_frame); 153 offset = NSHeight(window_frame);
180 [[window_ contentView] setStyle:STYLE_BOTTOM]; 154 [[window_ contentView] setCornerFlags:
155 kRoundedBottomLeftCorner | kRoundedBottomRightCorner];
181 } else if (offset > 0) { 156 } else if (offset > 0) {
182 [[window_ contentView] setStyle:STYLE_FLOATING]; 157 [[window_ contentView] setCornerFlags:
158 kRoundedTopRightCorner | kRoundedBottomLeftCorner |
159 kRoundedBottomRightCorner];
183 } else { 160 } else {
184 [[window_ contentView] setStyle:STYLE_STANDARD]; 161 [[window_ contentView] setCornerFlags:kRoundedTopRightCorner];
185 } 162 }
186 163
187 offset_ = offset; 164 offset_ = offset;
188 window_frame.origin.y -= offset; 165 window_frame.origin.y -= offset;
189 } else { 166 } else {
190 offset_ = 0; 167 offset_ = 0;
191 [[window_ contentView] setStyle:STYLE_STANDARD]; 168 [[window_ contentView] setCornerFlags:kRoundedTopRightCorner];
192 } 169 }
193 170
194 // |delegate_| can be nil during unit tests. 171 // |delegate_| can be nil during unit tests.
195 if (is_download_shelf_visible_) { 172 if (is_download_shelf_visible_) {
196 if ([delegate_ respondsToSelector:@selector(verticalOffsetForStatusBubble)]) 173 if ([delegate_ respondsToSelector:@selector(verticalOffsetForStatusBubble)])
197 window_frame.origin.y += [delegate_ verticalOffsetForStatusBubble]; 174 window_frame.origin.y += [delegate_ verticalOffsetForStatusBubble];
198 } 175 }
199 176
200 [window_ setFrame:window_frame display:YES]; 177 [window_ setFrame:window_frame display:YES];
201 } 178 }
(...skipping 13 matching lines...) Expand all
215 window_ = [[NSWindow alloc] initWithContentRect:rect 192 window_ = [[NSWindow alloc] initWithContentRect:rect
216 styleMask:NSBorderlessWindowMask 193 styleMask:NSBorderlessWindowMask
217 backing:NSBackingStoreBuffered 194 backing:NSBackingStoreBuffered
218 defer:YES]; 195 defer:YES];
219 [window_ setMovableByWindowBackground:NO]; 196 [window_ setMovableByWindowBackground:NO];
220 [window_ setBackgroundColor:[NSColor clearColor]]; 197 [window_ setBackgroundColor:[NSColor clearColor]];
221 [window_ setLevel:NSNormalWindowLevel]; 198 [window_ setLevel:NSNormalWindowLevel];
222 [window_ setOpaque:NO]; 199 [window_ setOpaque:NO];
223 [window_ setHasShadow:NO]; 200 [window_ setHasShadow:NO];
224 201
225 StatusBubbleViewCocoa* view = 202 // We do not need to worry about the bubble outliving |parent_| because our
226 [[[StatusBubbleViewCocoa alloc] initWithFrame:NSZeroRect] autorelease]; 203 // teardown sequence in BWC guarantees that |parent_| outlives the status
227 [view setParent:parent_]; 204 // bubble and that the StatusBubble is torn down completely prior to the
228 205 // window going away.
206 scoped_nsobject<BubbleView> view(
207 [[BubbleView alloc] initWithFrame:NSZeroRect themeProvider:parent_]);
229 [window_ setContentView:view]; 208 [window_ setContentView:view];
230 209
231 [parent_ addChildWindow:window_ ordered:NSWindowAbove]; 210 [parent_ addChildWindow:window_ ordered:NSWindowAbove];
232 211
233 [window_ setAlphaValue:0.0f]; 212 [window_ setAlphaValue:0.0f];
234 213
235 offset_ = 0; 214 offset_ = 0;
236 [view setStyle:STYLE_STANDARD]; 215 [view setCornerFlags:kRoundedTopRightCorner];
237 MouseMoved(); 216 MouseMoved();
238 } 217 }
239 218
240 void StatusBubbleMac::FadeIn() { 219 void StatusBubbleMac::FadeIn() {
241 [NSAnimationContext beginGrouping]; 220 [NSAnimationContext beginGrouping];
242 [[NSAnimationContext currentContext] setDuration:kShowFadeDuration]; 221 [[NSAnimationContext currentContext] setDuration:kShowFadeDuration];
243 [[window_ animator] setAlphaValue:1.0f]; 222 [[window_ animator] setAlphaValue:1.0f];
244 [NSAnimationContext endGrouping]; 223 [NSAnimationContext endGrouping];
245 } 224 }
246 225
247 void StatusBubbleMac::FadeOut() { 226 void StatusBubbleMac::FadeOut() {
248 [NSAnimationContext beginGrouping]; 227 [NSAnimationContext beginGrouping];
249 [[NSAnimationContext currentContext] setDuration:kHideFadeDuration]; 228 [[NSAnimationContext currentContext] setDuration:kHideFadeDuration];
250 [[window_ animator] setAlphaValue:0.0f]; 229 [[window_ animator] setAlphaValue:0.0f];
251 [NSAnimationContext endGrouping]; 230 [NSAnimationContext endGrouping];
252 } 231 }
253 232
254 @implementation StatusBubbleViewCocoa
255
256 - (void)dealloc {
257 [parent_ release];
258 [content_ release];
259 [super dealloc];
260 }
261
262 - (void)setContent:(NSString*)content {
263 [content_ autorelease];
264 content_ = [content copy];
265 [self setNeedsDisplay:YES];
266 }
267
268 - (void)setStyle:(BubbleStyle)style {
269 style_ = style;
270 [self setNeedsDisplay:YES];
271 }
272
273 - (void)setParent:(NSWindow*)parent {
274 [parent_ autorelease];
275 parent_ = [parent retain];
276 [self setNeedsDisplay:YES];
277 }
278
279 - (GTMTheme*)gtm_theme {
280 return [parent_ gtm_theme];
281 }
282
283 - (NSFont*)font {
284 return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
285 }
286
287 - (void)drawRect:(NSRect)rect {
288 float tl_radius, tr_radius, bl_radius, br_radius;
289
290 switch (style_) {
291 case STYLE_BOTTOM:
292 tl_radius = 0.0f;
293 tr_radius = 0.0f;
294 bl_radius = kBubbleCornerRadius;
295 br_radius = kBubbleCornerRadius;
296 break;
297 case STYLE_FLOATING:
298 tl_radius = 0.0f;
299 tr_radius = kBubbleCornerRadius;
300 bl_radius = kBubbleCornerRadius;
301 br_radius = kBubbleCornerRadius;
302 break;
303 case STYLE_STANDARD:
304 tl_radius = 0.0f;
305 tr_radius = kBubbleCornerRadius;
306 bl_radius = 0.0f;
307 br_radius = 0.0f;
308 break;
309 default:
310 NOTREACHED();
311 tl_radius = 0.0f;
312 tr_radius = 0.0f;
313 bl_radius = 0.0f;
314 br_radius = 0.0f;
315 }
316
317 // Background / Edge
318
319 NSRect bounds = [self bounds];
320 bounds = NSInsetRect(bounds, 0.5, 0.5);
321 NSBezierPath *border = [NSBezierPath gtm_bezierPathWithRoundRect:bounds
322 topLeftCornerRadius:tl_radius
323 topRightCornerRadius:tr_radius
324 bottomLeftCornerRadius:bl_radius
325 bottomRightCornerRadius:br_radius];
326
327 NSColor* color =
328 [[self gtm_theme] backgroundColorForStyle:GTMThemeStyleToolBar
329 state:GTMThemeStateActiveWindow];
330
331 // workaround for default theme
332 // TODO(alcor) next GTM update return nil for background color if not set;
333 if ([color isEqual:[NSColor colorWithCalibratedWhite:0.5 alpha:1.0]])
334 color = nil;
335 if (!color)
336 color = [NSColor colorWithCalibratedWhite:0.9 alpha:1.0];
337 [color set];
338 [border fill];
339
340 border = [NSBezierPath gtm_bezierPathWithRoundRect:bounds
341 topLeftCornerRadius:tl_radius
342 topRightCornerRadius:tr_radius
343 bottomLeftCornerRadius:bl_radius
344 bottomRightCornerRadius:br_radius];
345
346 [[NSColor colorWithDeviceWhite:kWindowEdge alpha:1.0f] set];
347 [border stroke];
348
349 // Text
350 NSColor* textColor = [color gtm_legibleTextColor];
351 NSFont* textFont = [self font];
352 NSShadow* textShadow = [[[NSShadow alloc] init] autorelease];
353 [textShadow setShadowBlurRadius:0.0f];
354 [textShadow setShadowColor:[textColor gtm_legibleTextColor]];
355 [textShadow setShadowOffset:NSMakeSize(0.0f, -1.0f)];
356
357 NSDictionary* textDict = [NSDictionary dictionaryWithObjectsAndKeys:
358 textColor, NSForegroundColorAttributeName,
359 textFont, NSFontAttributeName,
360 textShadow, NSShadowAttributeName,
361 nil];
362 [content_ drawAtPoint:NSMakePoint(kTextPositionX, kTextPositionY)
363 withAttributes:textDict];
364 }
365
366 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698