Index: chrome/browser/ui/cocoa/history_overlay_controller.mm |
diff --git a/chrome/browser/ui/cocoa/history_overlay_controller.mm b/chrome/browser/ui/cocoa/history_overlay_controller.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..699ecdd9a3f02e1d0fc0e0cfcee09705c3e70a80 |
--- /dev/null |
+++ b/chrome/browser/ui/cocoa/history_overlay_controller.mm |
@@ -0,0 +1,184 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "chrome/browser/ui/cocoa/history_overlay_controller.h" |
+ |
+#import <QuartzCore/QuartzCore.h> |
+ |
+#include "base/logging.h" |
Mark Mentovai
2011/08/16 01:01:20
Used? Doesn’t look it.
Nico
2011/08/16 04:56:17
Done.
|
+#include "base/memory/scoped_nsobject.h" |
+#include "base/sys_string_conversions.h" |
Mark Mentovai
2011/08/16 01:01:20
Used? Doesn’t look it.
Nico
2011/08/16 04:56:17
Done.
|
+ |
+// OverlayFrameView //////////////////////////////////////////////////////////// |
+ |
+// The content view of the window that draws a custom frame. |
+@interface OverlayFrameView : NSView { |
+ @private |
+ NSTextField* message_; // Weak, owned by the view hierarchy. |
+} |
+- (void)setMessageText:(NSString*)text; |
+@end |
+ |
+// The content view of the window that draws a custom frame. |
+@implementation OverlayFrameView |
+ |
+- (id)initWithFrame:(NSRect)frameRect { |
Mark Mentovai
2011/08/16 01:01:20
I know where this code is ultimately ripped from:
Nico
2011/08/16 04:56:17
I'm hoping to get a bigger version of our back but
|
+ if ((self = [super initWithFrame:frameRect])) { |
+ scoped_nsobject<NSTextField> message( |
+ // The frame will be fixed up when |-setMessageText:| is called. |
+ [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]); |
Mark Mentovai
2011/08/16 01:01:20
NSZeroRect?
Nico
2011/08/16 04:56:17
Done.
|
+ message_ = message.get(); |
+ [message_ setEditable:NO]; |
+ [message_ setSelectable:NO]; |
+ [message_ setBezeled:NO]; |
+ [message_ setDrawsBackground:NO]; |
+ [message_ setFont:[NSFont boldSystemFontOfSize:72]]; |
+ [message_ setTextColor:[NSColor whiteColor]]; |
+ [self addSubview:message_]; |
+ } |
+ return self; |
+} |
+ |
+- (void)drawRect:(NSRect)dirtyRect { |
+ const CGFloat kCornerRadius = 5.0; |
+ NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] |
+ xRadius:kCornerRadius |
+ yRadius:kCornerRadius]; |
+ |
+ NSColor* fillColor = [NSColor colorWithCalibratedWhite:0.2 alpha:0.85]; |
+ [fillColor set]; |
+ [path fill]; |
+} |
+ |
+- (void)setMessageText:(NSString*)text { |
+ const CGFloat kHorizontalPadding = 30; // In view coordinates. |
+ |
+ // Style the string. |
+ scoped_nsobject<NSMutableAttributedString> attrString( |
+ [[NSMutableAttributedString alloc] initWithString:text]); |
+ scoped_nsobject<NSShadow> textShadow([[NSShadow alloc] init]); |
+ [textShadow.get() setShadowColor:[NSColor colorWithCalibratedWhite:0 |
+ alpha:0.6]]; |
+ [textShadow.get() setShadowOffset:NSMakeSize(0, -1)]; |
+ [textShadow setShadowBlurRadius:1.0]; |
+ [attrString addAttribute:NSShadowAttributeName |
+ value:textShadow |
+ range:NSMakeRange(0, [text length])]; |
+ [message_ setAttributedStringValue:attrString]; |
+ |
+ // Fixup the frame of the string. |
Mark Mentovai
2011/08/16 01:01:20
“Fix up” as a verb is two words (although the prob
Nico
2011/08/16 04:56:17
Done.
|
+ [message_ sizeToFit]; |
+ NSRect messageFrame = [message_ frame]; |
+ NSRect frameInViewSpace = |
+ [message_ convertRect:[[self window] frame] fromView:nil]; |
+ |
+ if (NSWidth(messageFrame) > NSWidth(frameInViewSpace)) |
+ frameInViewSpace.size.width = NSWidth(messageFrame) + kHorizontalPadding; |
+ |
+ messageFrame.origin.x = |
+ (NSWidth(frameInViewSpace) - NSWidth(messageFrame)) / 2; |
+ messageFrame.origin.y = |
+ (NSHeight(frameInViewSpace) - NSHeight(messageFrame)) / 2; |
+ |
+ [[self window] setFrame:[message_ convertRect:frameInViewSpace toView:nil] |
+ display:YES]; |
+ [message_ setFrame:messageFrame]; |
+} |
+ |
+@end |
+ |
+// HistoryOverlayController //////////////////////////////////////////////////// |
+ |
+@implementation HistoryOverlayController |
+ |
+- (id)initForMode:(HistoryOverlayMode)mode { |
+ const NSRect kWindowFrame = NSMakeRect(0, 0, 120, 70); |
+ scoped_nsobject<NSWindow> window( |
+ [[NSWindow alloc] initWithContentRect:kWindowFrame |
+ styleMask:NSBorderlessWindowMask |
+ backing:NSBackingStoreBuffered |
+ defer:NO]); |
+ if ((self = [super initWithWindow:window])) { |
+ mode_ = mode; |
+ |
+ [window setDelegate:self]; |
+ [window setBackgroundColor:[NSColor clearColor]]; |
+ [window setOpaque:NO]; |
+ [window setHasShadow:NO]; |
+ |
+ // Create the content view. Take the frame from the existing content view. |
+ NSRect frame = [[window contentView] frame]; |
+ scoped_nsobject<OverlayFrameView> frameView( |
+ [[OverlayFrameView alloc] initWithFrame:frame]); |
+ contentView_ = frameView.get(); |
+ [window setContentView:contentView_]; |
+ |
+ const unichar kBackArrowCharacter = 0x2190; |
+ const unichar kForwardArrowCharacter = 0x2192; |
+ |
+ unichar commandChar = mode_ == kHistoryOverlayModeForward ? |
+ kForwardArrowCharacter : kBackArrowCharacter; |
+ NSString* text = |
+ [NSString stringWithCharacters:&commandChar length:1]; |
+ [contentView_ setMessageText:text]; |
+ } |
+ return self; |
+} |
+ |
+- (void)setProgress:(CGFloat)gestureAmount { |
+ CGFloat alpha = 0; |
+ CGFloat x = 0; |
+ |
+ NSRect windowFrame = [parent_ frame]; |
+ CGFloat minX = NSMinX(windowFrame); |
+ CGFloat maxX = NSMaxX(windowFrame) - NSWidth([[self window] frame]); |
+ |
+ if (mode_ == kHistoryOverlayModeForward) { |
+ alpha = -(gestureAmount + 1) * (gestureAmount + 1) + 1; |
Mark Mentovai
2011/08/16 01:01:20
Can you pull the alpha computation out of the cond
Nico
2011/08/16 04:56:17
It feels good starting at 0 I think. Did the rest.
|
+ x = maxX + gestureAmount * (maxX - minX); |
+ } else if (mode_ == kHistoryOverlayModeBack) { |
+ alpha = -(gestureAmount - 1) * (gestureAmount - 1) + 1; |
+ x = minX + gestureAmount * (maxX - minX); |
+ } |
+ [[self window] setAlphaValue:alpha]; |
+ |
+ NSPoint p = [parent_ frame].origin; |
+ p.x = x; |
Mark Mentovai
2011/08/16 01:01:20
I wonder if we need a “target” for the arrow to hi
Nico
2011/08/16 04:56:17
Yes, this will need tweaking.
|
+ p.y += (NSHeight(windowFrame) - NSHeight([[self window] frame])) * 0.65; |
+ [[self window] setFrameOrigin:p]; |
+} |
+ |
+- (void)dismiss { |
+ const CGFloat kFadeOutDuration = 0.2; // In seconds. |
Mark Mentovai
2011/08/16 01:01:20
Instead of the comment, name the variable kFadeOut
Nico
2011/08/16 04:56:17
Done.
|
+ |
+ NSWindow* overlayWindow = [self window]; |
+ |
+ scoped_nsobject<CAAnimation> animation( |
+ [[overlayWindow animationForKey:@"alphaValue"] copy]); |
+ [animation setDelegate:self]; |
+ [animation setDuration:kFadeOutDuration]; |
+ NSMutableDictionary* dictionary = |
+ [NSMutableDictionary dictionaryWithCapacity:1]; |
+ [dictionary setObject:animation forKey:@"alphaValue"]; |
+ [overlayWindow setAnimations:dictionary]; |
+ [[overlayWindow animator] setAlphaValue:0.0]; |
+} |
+ |
+- (void)windowWillClose:(NSNotification*)notif { |
Mark Mentovai
2011/08/16 01:01:20
Don’t name variables notif, even if they’re unused
Nico
2011/08/16 04:56:17
Done.
|
+ // Release all animations because CAAnimation retains its delegate (self), |
+ // which will cause a retain cycle. Break it! |
+ [[self window] setAnimations:[NSDictionary dictionary]]; |
+} |
+ |
+- (void)showPanelForWindow:(NSWindow*)window { |
+ parent_ = window; |
Mark Mentovai
2011/08/16 01:01:20
Is it possible for parent_ to go away while this o
Nico
2011/08/16 04:56:17
Great catch, done. I made it a scoped_nsobject (hi
|
+ [self setProgress:0]; // Set initial window position. |
+ [self showWindow:self]; |
+} |
+ |
+- (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)finished { |
+ [self close]; |
+} |
+ |
+@end |