summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/ui/panels/panel_titlebar_view_cocoa.h16
-rw-r--r--chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm93
2 files changed, 108 insertions, 1 deletions
diff --git a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h
index 0a97f4b..0623408 100644
--- a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h
+++ b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.h
@@ -32,6 +32,14 @@ enum PanelDragState {
PANEL_DRAG_SUPPRESSED // Ignore drag events until PANEL_DRAG_CAN_START.
};
+@interface RepaintAnimation : NSAnimation {
+ @private
+ NSView* targetView_;
+}
+- (id)initWithView:(NSView*)targetView duration:(double) duration;
+- (void)setCurrentProgress:(NSAnimationProgress)progress;
+@end
+
@interface PanelTitlebarViewCocoa : NSView {
@private
IBOutlet PanelWindowControllerCocoa* controller_;
@@ -50,6 +58,10 @@ enum PanelDragState {
PanelDragState dragState_;
BOOL isDrawingAttention_;
NSPoint dragStartLocation_;
+ // "Glint" animation is used in "Draw Attention" mode.
+ scoped_nsobject<RepaintAnimation> glintAnimation_;
+ scoped_nsobject<NSTimer> glintAnimationTimer_;
+ double glintInterval_;
}
// Callback from Close button.
@@ -88,6 +100,10 @@ enum PanelDragState {
- (void)drawAttention;
- (void)stopDrawingAttention;
- (BOOL)isDrawingAttention;
+- (void)startGlintAnimation;
+- (void)restartGlintAnimation:(NSTimer*)timer;
+- (void)stopGlintAnimation;
+
@end // @interface PanelTitlebarView
// Methods which are either only for testing, or only public for testing.
diff --git a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
index 83b8bdf..31b1dfc 100644
--- a/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
+++ b/chrome/browser/ui/panels/panel_titlebar_view_cocoa.mm
@@ -30,6 +30,15 @@ const int kIconAndTextPadding = 5;
// titlebar with a twitch of the mouse pointer.
const int kDragThreshold = 3;
+// 'Glint' is a speck of light that moves across the titlebar to attract a bit
+// more attention using movement in addition to color of the titlebar.
+// It initially moves fast, then starts to slow down to avoid being annoying
+// if the user chooses not to react on it.
+const double kGlintAnimationDuration = 0.6;
+const double kStartGlintRepeatIntervalSeconds = 0.1;
+const double kFinalGlintRepeatIntervalSeconds = 2.0;
+const double kGlintRepeatIntervalIncreaseFactor = 1.5;
+
// Used to implement TestingAPI
static NSEvent* MakeMouseEvent(NSEventType type,
NSPoint point,
@@ -45,6 +54,22 @@ static NSEvent* MakeMouseEvent(NSEventType type,
pressure:0.0];
}
+@implementation RepaintAnimation
+- (id)initWithView:(NSView*)targetView duration:(double) duration {
+ if (![super initWithDuration:duration animationCurve:NSAnimationEaseInOut])
+ return nil;
+ [self setAnimationBlockingMode:NSAnimationNonblocking];
+ targetView_ = targetView;
+ return self;
+}
+
+- (void)setCurrentProgress:(NSAnimationProgress)progress {
+ [super setCurrentProgress:progress];
+ [targetView_ setNeedsDisplay:YES];
+}
+@end
+
+
@implementation PanelTitlebarViewCocoa
- (id)initWithFrame:(NSRect)frame {
@@ -64,6 +89,7 @@ static NSEvent* MakeMouseEvent(NSEventType type,
if (closeButtonTrackingArea_.get())
[self removeTrackingArea:closeButtonTrackingArea_.get()];
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [self stopGlintAnimation];
[super dealloc];
}
@@ -100,6 +126,30 @@ static NSEvent* MakeMouseEvent(NSEventType type,
strokeColor = [NSColor colorWithCalibratedWhite:0.6 alpha:1.0];
titleColor = [attentionColor gtm_legibleTextColor];
+
+ if ([glintAnimation_ isAnimating]) {
+ scoped_nsobject<NSGradient> glint([NSGradient alloc]);
+ NSColor* gold =
+ [NSColor colorWithCalibratedRed:0.8 green:0.8 blue:0.0 alpha:1.0];
+ [glint initWithColorsAndLocations:gold, 0.0,
+ [NSColor colorWithCalibratedWhite:1.0 alpha:0.4], 0.3,
+ [NSColor colorWithCalibratedWhite:1.0 alpha:0.0], 1.0,
+ nil];
+ NSRect bounds = [self bounds];
+ NSPoint point = bounds.origin;
+ // The size and position values are experimentally choosen to create
+ // a "speck of light attached to the top edge" effect.
+ int gradientRadius = NSHeight(bounds) * 2;
+ point.y += gradientRadius / 2;
+ double rangeOfMotion = NSWidth(bounds) + 4 * gradientRadius;
+ double startPoint = - 2 * gradientRadius;
+ point.x = startPoint + rangeOfMotion * [glintAnimation_ currentValue];
+ [glint drawFromCenter:point
+ radius:0.0
+ toCenter:point
+ radius:gradientRadius
+ options:NSGradientDrawsBeforeStartingLocation];
+ }
} else if (theme && !theme->UsingDefaultTheme()) {
NSColor* backgroundColor = nil;
if ([[self window] isMainWindow]) {
@@ -439,13 +489,16 @@ static NSEvent* MakeMouseEvent(NSEventType type,
if (isDrawingAttention_)
return;
isDrawingAttention_ = YES;
- [self setNeedsDisplay:YES];
+
+ [self startGlintAnimation];
}
- (void)stopDrawingAttention {
if (!isDrawingAttention_)
return;
isDrawingAttention_ = NO;
+
+ [self stopGlintAnimation];
[self setNeedsDisplay:YES];
}
@@ -453,6 +506,44 @@ static NSEvent* MakeMouseEvent(NSEventType type,
return isDrawingAttention_;
}
+- (void)startGlintAnimation {
+ glintInterval_ = kStartGlintRepeatIntervalSeconds;
+ [self restartGlintAnimation:nil];
+}
+
+- (void)stopGlintAnimation {
+ if (glintAnimationTimer_.get()) {
+ [glintAnimationTimer_ invalidate];
+ glintAnimationTimer_.reset();
+ }
+ if ([glintAnimation_ isAnimating])
+ [glintAnimation_ stopAnimation];
+}
+
+- (void)restartGlintAnimation:(NSTimer*)timer {
+ if (!glintAnimation_.get()) {
+ glintAnimation_.reset(
+ [[RepaintAnimation alloc] initWithView:self
+ duration:kGlintAnimationDuration]);
+ [glintAnimation_ setDelegate:self];
+ }
+ [glintAnimation_ startAnimation];
+}
+
+- (void)animationDidEnd:(NSAnimation*)animation {
+ if (animation == glintAnimation_.get()) { // Restart after a timeout.
+ glintAnimationTimer_.reset([[NSTimer
+ scheduledTimerWithTimeInterval:glintInterval_
+ target:self
+ selector:@selector(restartGlintAnimation:)
+ userInfo:nil
+ repeats:NO] retain]);
+ // Gradually reduce the frequency of repeating the animation,
+ // calming it down if user decides not to act upon it.
+ if (glintInterval_ < kFinalGlintRepeatIntervalSeconds)
+ glintInterval_ *= kGlintRepeatIntervalIncreaseFactor;
+ }
+}
// (Private/TestingAPI)
- (PanelWindowControllerCocoa*)controller {