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.
This commit is contained in:
Aparajita Fishman
2012-03-23 01:49:01 -07:00
parent d620032d0d
commit 08f013171e
3 changed files with 101 additions and 64 deletions
+27 -18
View File
@@ -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]]];
+63 -41
View File
@@ -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
+11 -5
View File
@@ -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];