From 08f013171ef9571a0fe86f34cd22281dac952d6d Mon Sep 17 00:00:00 2001 From: Aparajita Fishman Date: Fri, 23 Mar 2012 01:49:01 -0700 Subject: [PATCH] CPPopover tweaks: - Added animationStyle (Lion/iOS) to CPPopover. iOS style does not zoom open, it just appears. - Tweaked the Lion animation a bit to be a bit less rushed and match Mac OS X timing better. - Fixed some typos. --- AppKit/CPPopover.j | 45 ++++++----- AppKit/_CPAttachedWindow.j | 104 +++++++++++++++---------- Tests/Manual/CPPopover/AppController.j | 16 ++-- 3 files changed, 101 insertions(+), 64 deletions(-) diff --git a/AppKit/CPPopover.j b/AppKit/CPPopover.j index 711a5ef26..1968b3079 100644 --- a/AppKit/CPPopover.j +++ b/AppKit/CPPopover.j @@ -35,6 +35,8 @@ CPPopoverBehaviorApplicationDefined = 0; CPPopoverBehaviorTransient = 1; CPPopoverBehaviorSemitransient = 2; +CPPopoverAnimationStyleLion = 0; +CPPopoverAnimationStyleIOS = 1; var CPPopoverDelegate_popover_willShow_ = 1 << 0, CPPopoverDelegate_popover_didShow_ = 1 << 1, @@ -50,11 +52,14 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, view relative to another one. Delegate can implement: - – popoverShouldClose:(CPPopover)aPopOver - – popoverWillShow:(CPPopover)aPopOver - – popoverDidShow:(CPPopover)aPopOver - – popoverWillClose:(CPPopover)aPopOver - – popoverDidClose:(CPPopover)aPopOver + + @code + – popoverShouldClose:(CPPopover)aPopOver + – popoverWillShow:(CPPopover)aPopOver + – popoverDidShow:(CPPopover)aPopOver + – popoverWillClose:(CPPopover)aPopOver + – popoverDidClose:(CPPopover)aPopOver + @endcode */ @implementation CPPopover : CPResponder { @@ -62,6 +67,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, @outlet id _delegate @accessors(getter=delegate); BOOL _animates @accessors(property=animates); + int _animationStyle @accessors(property=animationStyle); BOOL _shown @accessors(getter=shown); int _appearance @accessors(property=appearance); int _behavior @accessors(getter=behavior); @@ -85,6 +91,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, if (self = [super init]) { _animates = YES; + _animationStyle = CPPopoverAnimationStyleLion; _appearance = CPPopoverAppearanceMinimal; _behavior = CPPopoverBehaviorApplicationDefined; _needsCompute = YES; @@ -101,9 +108,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, /*! Returns the current rect of the popover - @return CPRect represeting the frame of the popover + @return CGRect representing the frame of the popover */ -- (CPRect)positioningRect +- (CGRect)positioningRect { if (!_attachedWindow || ![_attachedWindow isVisible]) return nil; @@ -113,7 +120,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, /*! Sets the frame of the popover @param aRect the desired frame */ -- (void)setPositioningRect:(CPRect)aRect +- (void)setPositioningRect:(CGRect)aRect { if (!_attachedWindow || ![_attachedWindow isVisible]) return; @@ -123,9 +130,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, /*! Returns the size of the popover's view - @return CPSize represeting the size of the popover's view + @return CGSize representing the size of the popover's view */ -- (CPRect)contentSize +- (CGSize)contentSize { if (!_attachedWindow || ![_attachedWindow isVisible]) return nil; @@ -145,7 +152,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, /*! Indicates if CPPopover is visible - @returns YES if visible + @returns \c YES if visible */ - (BOOL)shown { @@ -155,11 +162,12 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, } /*! - Set the behaviour of the CPPopover. It can be - - CPPopoverBehaviorTransient: the popover will be close if another control outside the popover become the responder - - CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover +Set the behaviour of the CPPopover. It can be: - @param aBehaviour the desired behaviour +- \c CPPopoverBehaviorTransient: the popover will be close if another control outside the popover become the responder +- \c CPPopoverBehaviorApplicationDefined: (DEFAULT) the application is responsible for closing the popover + +@param aBehaviour the desired behaviour */ - (void)setBehaviour:(int)aBehaviour { @@ -203,9 +211,9 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, @param positioningRect if set, the popover will be positionned to a random rect relative to the window @param positioningView if set, the popover will be positioned relative to this view - @param preferredEdge: CPRectEdge representing the preferred positioning. + @param preferredEdge: \c CPRectEdge representing the preferred positioning. */ -- (void)showRelativeToRect:(CPRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge +- (void)showRelativeToRect:(CGRect)positioningRect ofView:(CPView)positioningView preferredEdge:(CPRectEdge)preferredEdge { if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_) [_delegate popoverWillShow:self]; @@ -216,11 +224,12 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0, if (_needsCompute || !_attachedWindow) { var styleMask = (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : nil; - _attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CPRectMakeZero() styleMask:styleMask]; + _attachedWindow = [[_CPAttachedWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:styleMask]; } [_attachedWindow setAppearance:_appearance]; [_attachedWindow setAnimates:_animates]; + [_attachedWindow setAnimationStyle:_animationStyle]; [_attachedWindow setDelegate:self]; [_attachedWindow setMovableByWindowBackground:NO]; [_attachedWindow setFrame:[_attachedWindow frameRectForContentRect:[[_contentViewController view] frame]]]; diff --git a/AppKit/_CPAttachedWindow.j b/AppKit/_CPAttachedWindow.j index 7c05d6a00..c3fa0e670 100644 --- a/AppKit/_CPAttachedWindow.j +++ b/AppKit/_CPAttachedWindow.j @@ -43,6 +43,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, @implementation _CPAttachedWindow : CPWindow { BOOL _animates @accessors(property=animates); + int _animationStyle @accessors(property=animationStyle); id _targetView @accessors(property=targetView); int _appearance @accessors(getter=appearance); @@ -126,7 +127,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, if (self = [super initWithContentRect:aFrame styleMask:aStyleMask]) { _animates = YES; - _animates = YES; + _animationStyle = CPPopoverAnimationStyleLion; _animationDuration = 150; _closeOnBlur = (aStyleMask & CPClosableOnBlurWindowMask); _isClosed = NO; @@ -136,9 +137,9 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, [self setMovableByWindowBackground:YES]; [self setHasShadow:NO]; - _DOMElement.style.WebkitBackfaceVisibility = "hidden"; - _DOMElement.style.WebkitTransitionProperty = "-webkit-transform, opacity"; - _DOMElement.style.WebkitTransitionDuration = _animationDuration + "ms"; + _DOMElement.style.webkitBackfaceVisibility = "hidden"; + _DOMElement.style.webkitTransitionProperty = "-webkit-transform, opacity"; + _DOMElement.style.webkitTransitionDuration = _animationDuration + "ms"; [_windowView setNeedsDisplay:YES]; } @@ -151,7 +152,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, - (void)setAppearance:(int)anAppearance { - if (_appearance == anAppearance) + if (_appearance === anAppearance) return; [_windowView setAppearance:anAppearance]; @@ -159,7 +160,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, - (void)setDelegate:(id)aDelegate { - if (_delegate == aDelegate) + if (_delegate === aDelegate) return; _delegate = aDelegate; @@ -375,7 +376,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, } /*! - Position the _CPAttachedWindow to a random point + Position the _CPAttachedWindow to a given point @param aPoint the point where the _CPAttachedWindow will be attached */ @@ -385,7 +386,7 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, } /*! - Position the _CPAttachedWindow to a random point + Position the _CPAttachedWindow to a given point @param aPoint the point where the _CPAttachedWindow will be attached @param anEdge the prefered edge @@ -442,47 +443,63 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, { [super orderFront:aSender]; - var tranformOrigin = "50% 100%"; + var transformOrigin = "50% 100%"; - switch ([_windowView preferredEdge]) + if (_animationStyle === CPPopoverAnimationStyleLion) { - case CPMaxYEdge: - var posX = 50 + (([_windowView arrowOffsetX] * 100) / _frame.size.width); - tranformOrigin = posX + "% 0%"; // 50 0 - break; - case CPMinYEdge: - var posX = 50 + (([_windowView arrowOffsetX] * 100) / _frame.size.width); - tranformOrigin = posX + "% 100%"; // 50 100 - break; - case CPMinXEdge: - var posY = 50 + (([_windowView arrowOffsetY] * 100) / _frame.size.height); - tranformOrigin = "100% " + posY + "%"; // 100 50 - break; - case CPMaxXEdge: - var posY = 50 + (([_windowView arrowOffsetY] * 100) / _frame.size.height); - tranformOrigin = "0% "+ posY + "%"; // 0 50 - break; + switch ([_windowView preferredEdge]) + { + case CPMaxYEdge: + var posX = 50 + (([_windowView arrowOffsetX] * 100) / _frame.size.width); + transformOrigin = posX + "% 0%"; // 50 0 + break; + case CPMinYEdge: + var posX = 50 + (([_windowView arrowOffsetX] * 100) / _frame.size.width); + transformOrigin = posX + "% 100%"; // 50 100 + break; + case CPMinXEdge: + var posY = 50 + (([_windowView arrowOffsetY] * 100) / _frame.size.height); + transformOrigin = "100% " + posY + "%"; // 100 50 + break; + case CPMaxXEdge: + var posY = 50 + (([_windowView arrowOffsetY] * 100) / _frame.size.height); + transformOrigin = "0% "+ posY + "%"; // 0 50 + break; + } } // @TODO: implement for FF - if (_animates && _shouldPerformAnimation && typeof(_DOMElement.style.WebkitTransform) != "undefined") + if (_animates && _shouldPerformAnimation && typeof(_DOMElement.style.webkitTransform) != "undefined") { _DOMElement.style.opacity = 0; - _DOMElement.style.WebkitTransform = "scale(0)"; - _DOMElement.style.WebkitTransformOrigin = tranformOrigin; + + if (_animationStyle === CPPopoverAnimationStyleLion) + { + _DOMElement.style.webkitTransform = "scale(0)"; + _DOMElement.style.webkitTransformOrigin = transformOrigin; + } + window.setTimeout(function() { + _DOMElement.style.opacity = 1; _DOMElement.style.height = _frame.size.height + @"px"; _DOMElement.style.width = _frame.size.width + @"px"; - _DOMElement.style.opacity = 1; - _DOMElement.style.WebkitTransform = "scale(1.1)"; - var transitionEndFunction = function() + + if (_animationStyle === CPPopoverAnimationStyleLion) { - _DOMElement.style.WebkitTransform = "scale(1)"; - _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES); - }; - _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES); - },0); + _DOMElement.style.webkitTransform = "scale(1.1)"; + _DOMElement.style.webkitTransitionDuration = "250ms"; + _DOMElement.style.webkitTransitionTimingFunction = "ease-out"; + + var transitionEndFunction = function() + { + _DOMElement.style.webkitTransform = "scale(1)"; + _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES); + }; + + _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES); + } + }, 0); } [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_attachedWindowDidMove:) name:CPWindowDidMoveNotification object:self]; @@ -492,20 +509,25 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0, } /*! - Close the windo with animation + Close the window with animation */ - (void)close { // set a close flag to avoid infinite loop _isClosed = YES; - if (_animates && typeof(_DOMElement.style.WebkitTransform) != "undefined") + if (_animates && typeof(_DOMElement.style.webkitTransform) != "undefined") { _DOMElement.style.opacity = 0; - var transitionEndFunction = function(){ - [super close]; + _DOMElement.style.webkitTransitionDuration = "250ms"; + _DOMElement.style.webkitTransitionTimingFunction = "linear"; + + var transitionEndFunction = function() + { + [super close]; _DOMElement.removeEventListener("webkitTransitionEnd", transitionEndFunction, YES); }; + _DOMElement.addEventListener("webkitTransitionEnd", transitionEndFunction, YES); } else diff --git a/Tests/Manual/CPPopover/AppController.j b/Tests/Manual/CPPopover/AppController.j index bb3175f7a..e2b2623c8 100644 --- a/Tests/Manual/CPPopover/AppController.j +++ b/Tests/Manual/CPPopover/AppController.j @@ -73,7 +73,12 @@ [buttonAnimation addItemWithTitle:"No animation"]; [contentView addSubview:buttonAnimation]; - buttonBehaviour = [[CPPopUpButton alloc] initWithFrame:CPRectMake(430, 10, 130, 24)]; + buttonAnimationStyle = [[CPPopUpButton alloc] initWithFrame:CPRectMake(430, 10, 130, 24)]; + [buttonAnimationStyle addItemWithTitle:"Lion"]; + [buttonAnimationStyle addItemWithTitle:"iOS"]; + [contentView addSubview:buttonAnimationStyle]; + + buttonBehaviour = [[CPPopUpButton alloc] initWithFrame:CPRectMake(570, 10, 130, 24)]; [buttonBehaviour addItemWithTitle:"Transient"]; [buttonBehaviour addItemWithTitle:"Not managed"]; [contentView addSubview:buttonBehaviour]; @@ -121,17 +126,18 @@ [label setFont:[CPFont boldSystemFontOfSize:30.0]]; [label setFrameOrigin:CPPointMake(0, 70)]; - [label setValue:(a == CPPopoverAppearanceHUD) ? [CPColor colorWithHexString:@"333"] : [CPColor colorWithHexString:@"fff"] forThemeAttribute:@"text-shadow-color"]; + [label setValue:(a === CPPopoverAppearanceHUD) ? [CPColor colorWithHexString:@"333"] : [CPColor colorWithHexString:@"fff"] forThemeAttribute:@"text-shadow-color"]; [label setValue:CGSizeMake(0.0, 1.0) forThemeAttribute:@"text-shadow-offset"]; - [label setTextColor:(a == CPPopoverAppearanceHUD) ? [CPColor whiteColor] : [CPColor colorWithHexString:@"444"]]; + [label setTextColor:(a === CPPopoverAppearanceHUD) ? [CPColor whiteColor] : [CPColor colorWithHexString:@"444"]]; [label setFrameSize:CPSizeMake([view frame].size.width, 50)]; [label setAlignment:CPCenterTextAlignment]; [view addSubview:label]; [viewC setView:view]; [p setContentViewController:viewC]; - [p setAnimates:([buttonAnimation title] == @"With animation")]; - [p setBehaviour:([buttonBehaviour title] == @"Transient") ? CPPopoverBehaviorTransient : CPPopoverBehaviorApplicationDefined]; + [p setAnimates:([buttonAnimation title] === @"With animation")]; + [p setAnimationStyle:[buttonAnimationStyle title] === @"Lion" ? CPPopoverAnimationStyleLion : CPPopoverAnimationStyleIOS]; + [p setBehaviour:([buttonBehaviour title] === @"Transient") ? CPPopoverBehaviorTransient : CPPopoverBehaviorApplicationDefined]; [p setAppearance:a]; [p setDelegate:self]; [p showRelativeToRect:nil ofView:sender preferredEdge:g];