summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-21 03:22:35 +0000
committerdimich@chromium.org <dimich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-21 03:22:35 +0000
commit60073c47d791066042f4ede0d6eb607138a7718c (patch)
tree1de17e109445169f39514f06058065bbe3594a42
parent33fed0f74b2fa22d85ed39cba99bc394278ceb10 (diff)
downloadchromium_src-60073c47d791066042f4ede0d6eb607138a7718c.zip
chromium_src-60073c47d791066042f4ede0d6eb607138a7718c.tar.gz
chromium_src-60073c47d791066042f4ede0d6eb607138a7718c.tar.bz2
Add 'running glint' animation to 'draw attention' state of Panels on Mac.
Experimental feature, to adjust later. The motivation is to increase visibility and ability to actually 'draw attention'. Simply changing the color of a static object is often missed by the users. Review URL: http://codereview.chromium.org/9008026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115270 0039d316-1c4b-4281-b951-d872f2087c98
-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 {