Skip to content

Commit

Permalink
CPPopover tweaks:
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
aparajita committed Mar 23, 2012
1 parent d620032 commit 08f0131
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 64 deletions.
45 changes: 27 additions & 18 deletions AppKit/CPPopover.j
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -50,18 +52,22 @@ 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
{
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
@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);
Expand All @@ -85,6 +91,7 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
if (self = [super init])
{
_animates = YES;
_animationStyle = CPPopoverAnimationStyleLion;
_appearance = CPPopoverAppearanceMinimal;
_behavior = CPPopoverBehaviorApplicationDefined;
_needsCompute = YES;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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
{
Expand All @@ -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:
- \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
@param aBehaviour the desired behaviour
*/
- (void)setBehaviour:(int)aBehaviour
{
Expand Down Expand Up @@ -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];
Expand All @@ -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]]];
Expand Down
104 changes: 63 additions & 41 deletions AppKit/_CPAttachedWindow.j
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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];
}
Expand All @@ -151,15 +152,15 @@ var _CPAttachedWindow_attachedWindowShouldClose_ = 1 << 0,

- (void)setAppearance:(int)anAppearance
{
if (_appearance == anAppearance)
if (_appearance === anAppearance)
return;

[_windowView setAppearance:anAppearance];
}

- (void)setDelegate:(id)aDelegate
{
if (_delegate == aDelegate)
if (_delegate === aDelegate)
return;

_delegate = aDelegate;
Expand Down Expand Up @@ -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
*/
Expand All @@ -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
Expand Down Expand Up @@ -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];
Expand All @@ -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
Expand Down
16 changes: 11 additions & 5 deletions Tests/Manual/CPPopover/AppController.j
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand Down

4 comments on commit 08f0131

@cacaodev
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that in the CPPopover test, a new popover instance is created every time you click on a button. Maybe it was useful for testing purposes at the time the test was written but it's not the usual way to use a popover. Can we change that ? and then we can test issue #1473 based on the new test app. Or we don't change it and create a specific test for issue #1473 ?

@aparajita
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go ahead and change it, I'll be happy to merge it.

@aparajita
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be changed in the next commit.

@aparajita
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix was just merged.

Please sign in to comment.