mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 21:17:03 +00:00
575 lines
16 KiB
Plaintext
575 lines
16 KiB
Plaintext
/*
|
|
* AppController.j
|
|
* CPAnimatablePropertyContainerTest
|
|
*
|
|
* Created by You on December 3, 2012.
|
|
* Copyright 2012, Your Company All rights reserved.
|
|
*/
|
|
|
|
@import <Foundation/CPObject.j>
|
|
|
|
CPLogRegister(CPLogConsole);
|
|
|
|
var ANIMATIONS_NAMES = ["Fade In", "Fade Out", "Background Color", "Frame Origin", "Bounce", "Frame Size", "Frame"];
|
|
|
|
@implementation AppController : CPObject
|
|
{
|
|
@outlet CPWindow theWindow; //this "outlet" is connected automatically by the Cib
|
|
|
|
@outlet CPBox group1Box;
|
|
@outlet CPBox group2Box;
|
|
|
|
@outlet AnimationSandbox animationSandbox;
|
|
|
|
CPView leftView;
|
|
CPView rightView;
|
|
|
|
CPArray animations;
|
|
|
|
float duration1 @accessors;
|
|
float duration2 @accessors;
|
|
|
|
CPString message1 @accessors;
|
|
CPString message2 @accessors;
|
|
|
|
CPInteger selectedTimingFunction1 @accessors;
|
|
CPInteger selectedTimingFunction2 @accessors;
|
|
|
|
CPString timingFunction1 @accessors;
|
|
CPString timingFunction2 @accessors;
|
|
BOOL periodicFrameUpdates;
|
|
}
|
|
|
|
- (id)init
|
|
{
|
|
self = [super init];
|
|
|
|
animations = [CPArray array];
|
|
|
|
[ANIMATIONS_NAMES enumerateObjectsUsingBlock:function(anim, idx)
|
|
{
|
|
var dict = [CPDictionary dictionaryWithObjectsAndKeys:anim, @"name", NO, @"enabled1", NO, @"enabled2"];
|
|
[animations addObject:dict];
|
|
}];
|
|
|
|
duration1 = 1.0;
|
|
duration2 = 1.0;
|
|
|
|
message1 = @"Done for View 1";
|
|
message2 = @"Done for View 2";
|
|
|
|
timingFunction1 = @"0,1,1,0";
|
|
timingFunction2 = @"0,1,1,0";
|
|
|
|
selectedTimingFunction1 = 1;
|
|
selectedTimingFunction2 = 1;
|
|
|
|
periodicFrameUpdates = NO;
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
|
|
{
|
|
// This is called when the application is done loading.
|
|
}
|
|
|
|
- (void)awakeFromCib
|
|
{
|
|
// This is called when the cib is done loading.
|
|
// You can implement this method on any object instantiated from a Cib.
|
|
// It's a useful hook for setting up current UI values, and other things.
|
|
|
|
[[theWindow contentView] setBackgroundColor:[CPColor colorWithRed:1 green:238/255 blue:185/255 alpha:1]];
|
|
[animationSandbox setBackgroundColor:[CPColor whiteColor]];
|
|
|
|
[self revert:nil];
|
|
// In this case, we want the window from Cib to become our full browser window
|
|
[theWindow setFullPlatformWindow:YES];
|
|
}
|
|
|
|
- (IBAction)runAnimationsGroup1:(id)sender
|
|
{
|
|
[[CPAnimationContext currentContext] setDuration:duration1];
|
|
[[CPAnimationContext currentContext] setTimingFunction:[self timingFunctionForGroup:1 fromPopUp:selectedTimingFunction1]];
|
|
[[CPAnimationContext currentContext] setCompletionHandler:[self completionHandlerFromString:message1]];
|
|
|
|
[self runAnimationsForGroup:1];
|
|
}
|
|
|
|
- (IBAction)runAnimationsGroup2:(id)sender
|
|
{
|
|
[[CPAnimationContext currentContext] setDuration:duration2];
|
|
[[CPAnimationContext currentContext] setTimingFunction:[self timingFunctionForGroup:2 fromPopUp:selectedTimingFunction2]];
|
|
[[CPAnimationContext currentContext] setCompletionHandler:[self completionHandlerFromString:message2]];
|
|
|
|
[self runAnimationsForGroup:2];
|
|
}
|
|
|
|
- (IBAction)animate:(id)sender
|
|
{
|
|
[[CPAnimationContext currentContext] setDuration:duration1];
|
|
[[CPAnimationContext currentContext] setTimingFunction:[self timingFunctionForGroup:1 fromPopUp:selectedTimingFunction2]];
|
|
[[CPAnimationContext currentContext] setCompletionHandler:[self completionHandlerFromString:message1]];
|
|
|
|
var tag = [sender tag];
|
|
var width = tag ? 100 : 200;
|
|
[[sender animator] setFrameSize:CGSizeMake(width, CGRectGetHeight([sender frame]))];
|
|
|
|
[sender setTag:(1 - tag)];
|
|
}
|
|
|
|
- (IBAction)runBothGroups:(id)sender
|
|
{
|
|
[CPAnimationContext runAnimationGroup:function(context)
|
|
{
|
|
[context setDuration:duration1];
|
|
[context setTimingFunction:[self timingFunctionForGroup:1 fromPopUp:selectedTimingFunction1]];
|
|
[self runAnimationsForGroup:1];
|
|
|
|
} completionHandler:function()
|
|
{
|
|
CPLogConsole(message1);
|
|
}];
|
|
|
|
[CPAnimationContext runAnimationGroup:function(context)
|
|
{
|
|
[context setDuration:duration2];
|
|
[context setTimingFunction:[self timingFunctionForGroup:2 fromPopUp:selectedTimingFunction2]];
|
|
[self runAnimationsForGroup:2];
|
|
|
|
} completionHandler:function()
|
|
{
|
|
CPLogConsole(message2);
|
|
}];
|
|
}
|
|
|
|
/*
|
|
- (IBAction)runInGroups:(id)sender
|
|
{
|
|
[CPAnimationContext beginGrouping];
|
|
|
|
[[CPAnimationContext currentContext] setDuration:duration1];
|
|
[[CPAnimationContext currentContext] setTimingFunction:[self timingFunctionFromString:timingFunction1]];
|
|
[[CPAnimationContext currentContext] setCompletionHandler:[self completionHandlerFromString:message1]];
|
|
[self runAnimationsForGroup:1];
|
|
|
|
[CPAnimationContext endGrouping];
|
|
|
|
|
|
[CPAnimationContext beginGrouping];
|
|
|
|
[[CPAnimationContext currentContext] setDuration:duration2];
|
|
[[CPAnimationContext currentContext] setCompletionHandler:[self completionHandlerFromString:message2]];
|
|
[self runAnimationsForGroup:2];
|
|
|
|
[CPAnimationContext endGrouping];
|
|
}
|
|
|
|
- (IBAction)emptyGroupTest:(id)sender
|
|
{
|
|
[CPAnimationContext beginGrouping];
|
|
|
|
[[CPAnimationContext currentContext] setDuration:10];
|
|
[[CPAnimationContext currentContext] setCompletionHandler:function()
|
|
{
|
|
CPLogConsole("Context duration is 10s but no animations were set. We run the completionHandler (this message) immediately and return");
|
|
}];
|
|
|
|
[CPAnimationContext endGrouping];
|
|
}
|
|
*/
|
|
- (IBAction)removeFromSuperview:(id)sender
|
|
{
|
|
[[leftView animator] removeFromSuperview];
|
|
[[rightView animator] removeFromSuperview];
|
|
}
|
|
|
|
- (IBAction)revert:(id)sender
|
|
{
|
|
[self setupGroup1:nil];
|
|
[self setupGroup2:nil];
|
|
[animationSandbox setNeedsDisplay:YES];
|
|
}
|
|
/*
|
|
- (IBAction)addSubview:(id)sender
|
|
{
|
|
[[theWindow contentView] addSubview:];
|
|
}
|
|
*/
|
|
- (void)runAnimationsForGroup:(CPInteger)group
|
|
{
|
|
var aView = group == 1 ? leftView : rightView,
|
|
enabledKey = @"enabled" + group;
|
|
|
|
var enabledIndexes = [animations indexesOfObjectsPassingTest:function(obj, idx)
|
|
{
|
|
return [obj objectForKey:enabledKey];
|
|
}];
|
|
|
|
if ([enabledIndexes count] == 0)
|
|
return;
|
|
|
|
if ([enabledIndexes containsIndex:0])
|
|
{
|
|
[aView setAlphaValue:0];
|
|
[[aView animator] setAlphaValue:1];
|
|
}
|
|
else if ([enabledIndexes containsIndex:1])
|
|
{
|
|
[[aView animator] setAlphaValue:0];
|
|
}
|
|
|
|
if ([enabledIndexes containsIndex:2])
|
|
{
|
|
[[aView animator] setBackgroundColor:[CPColor magentaColor]];
|
|
}
|
|
|
|
if ([enabledIndexes containsIndex:6])
|
|
{
|
|
var frame = CGRectMakeCopy([aView frame]),
|
|
origin = frame.origin,
|
|
size = frame.size;
|
|
|
|
origin.x += 450;
|
|
origin.y += 200;
|
|
|
|
size.width += 100;
|
|
size.height += 100;
|
|
|
|
[[aView animator] setWantsPeriodicFrameUpdates:periodicFrameUpdates];
|
|
[[aView animator] setFrame:frame];
|
|
return;
|
|
}
|
|
|
|
if ([enabledIndexes containsIndex:4])
|
|
{
|
|
[[aView animations] setObject:[self bounceAnimation:aView] forKey:@"frameOrigin"];
|
|
|
|
var origin = CGPointMakeCopy([aView frameOrigin]);
|
|
[[aView animator] setWantsPeriodicFrameUpdates:periodicFrameUpdates];
|
|
[[aView animator] setFrameOrigin:origin];
|
|
}
|
|
else if ([enabledIndexes containsIndex:3])
|
|
{
|
|
[[aView animations] removeObjectForKey:@"frameOrigin"];
|
|
|
|
var origin = CGPointMakeCopy([aView frameOrigin]);
|
|
origin.x +=550;
|
|
origin.y +=300;
|
|
[[aView animator] setWantsPeriodicFrameUpdates:periodicFrameUpdates];
|
|
[[aView animator] setFrameOrigin:origin];
|
|
}
|
|
|
|
if ([enabledIndexes containsIndex:5])
|
|
{
|
|
var size = CGSizeMakeCopy([aView frameSize]);
|
|
size.width += 300;
|
|
size.height += 200;
|
|
[[aView animator] setFrameSize:size];
|
|
}
|
|
}
|
|
|
|
- (CAMediaTimingFunction)controlsPointsForGroup:(CPInteger)aGroup
|
|
{
|
|
var aString = (aGroup == 1) ? timingFunction1 : timingFunction2;
|
|
|
|
if (!aString || ![aString length])
|
|
return nil;
|
|
|
|
var controlsPoints = [aString componentsSeparatedByString:@","];
|
|
|
|
return [[controlsPoints[0] floatValue], [controlsPoints[1] floatValue], [controlsPoints[2] floatValue], [controlsPoints[3] floatValue]];
|
|
}
|
|
|
|
- (CAMediaTimingFunction)timingFunctionForGroup:(CPInteger)aGroup fromPopUp:(CPInteger)selectedTag
|
|
{
|
|
var controlsPoints;
|
|
|
|
switch (selectedTag)
|
|
{
|
|
case 1: controlsPoints = [0, 0, 1, 1];
|
|
break;
|
|
case 2: controlsPoints = [0.42, 0, 1, 1];
|
|
break;
|
|
case 3: controlsPoints = [0, 0, 0.58, 1];
|
|
break;
|
|
case 4: controlsPoints = [0.42, 0, 0.58, 1];
|
|
break;
|
|
case 0: controlsPoints = [self controlsPointsForGroup:aGroup];
|
|
break;
|
|
}
|
|
|
|
return [CAMediaTimingFunction functionWithControlPoints:controlsPoints[0] :controlsPoints[1] :controlsPoints[2] :controlsPoints[3]];
|
|
}
|
|
|
|
- (Function)completionHandlerFromString:(CPString)aMessage
|
|
{
|
|
if (!aMessage || ![aMessage length])
|
|
return nil;
|
|
|
|
var s = new Date();
|
|
return function()
|
|
{
|
|
var e = new Date() - s;
|
|
CPLogConsole(aMessage + " in " + e + " ms");
|
|
};
|
|
}
|
|
|
|
- (CAKeyframeAnimation)bounceAnimation:(CPView)aView
|
|
{
|
|
var anim = [CAKeyframeAnimation animation],
|
|
easein = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
|
|
easeout = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
|
|
|
[anim setKeyTimes:[0, 0.2, 0.3, 0.5, 0.7, 0.8]];
|
|
var origin = CGPointMakeCopy([aView frameOrigin]);
|
|
[anim setValues:[origin, CGPointMake(origin.x, origin.y + 200), origin, CGPointMake(origin.x, origin.y + 100), origin, CGPointMake(origin.x, origin.y + 50)]];
|
|
[anim setTimingFunctions:[easeout, easein, easeout, easein, easeout]];
|
|
|
|
return anim;
|
|
}
|
|
|
|
- (CABasicAnimation)fadeOutAnimation
|
|
{
|
|
var animation = [CABasicAnimation animationWithKeyPath:@"alphaValue"];
|
|
[animation setDuration:0.2];
|
|
[animation setFromValue:1];
|
|
[animation setToValue:0];
|
|
|
|
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
|
|
|
|
return animation;
|
|
}
|
|
|
|
- (IBAction)setupGroup1:(id)sender
|
|
{
|
|
var contentView = [group1Box contentView];
|
|
|
|
var hasSubviews = [[contentView viewWithTag:1000] state] * 2,
|
|
customLayout = [[contentView viewWithTag:1001] state] * 4,
|
|
customDraw = [[contentView viewWithTag:1002] state] * 8,
|
|
customDrawSubviews = [[contentView viewWithTag:1003] state],
|
|
autoLayout = [[contentView viewWithTag:1004] state],
|
|
options = hasSubviews | customLayout | customDraw;
|
|
|
|
[leftView removeFromSuperview];
|
|
leftView = [self viewWithOptions:options];
|
|
|
|
if (leftView)
|
|
{
|
|
[leftView setFrame:CGRectMake(0, 0, 200, 200)];
|
|
[leftView setTag:1];
|
|
[animationSandbox addSubview:leftView];
|
|
}
|
|
|
|
if (hasSubviews)
|
|
[self addSubviewsToView:leftView autoLayout:(autoLayout && !customLayout) customDrawSubviews:customDrawSubviews];
|
|
}
|
|
|
|
- (IBAction)setupGroup2:(id)sender
|
|
{
|
|
var contentView = [group2Box contentView];
|
|
|
|
var hasSubviews = [[contentView viewWithTag:1000] state] * 2,
|
|
customLayout = [[contentView viewWithTag:1001] state] * 4,
|
|
customDraw = [[contentView viewWithTag:1002] state] * 8,
|
|
options = hasSubviews | customLayout | customDraw;
|
|
|
|
[rightView removeFromSuperview];
|
|
rightView = [self viewWithOptions:options];
|
|
|
|
if (rightView)
|
|
{
|
|
[rightView setFrame:CGRectMake(250, 0, 200, 200)];
|
|
[rightView setTag:2];
|
|
[animationSandbox addSubview:rightView];
|
|
}
|
|
|
|
if (leftView)
|
|
{
|
|
[leftView setTag:1];
|
|
[animationSandbox addSubview:leftView];
|
|
}
|
|
|
|
if (hasSubviews)
|
|
[self addSubviewsToView:rightView autoLayout:!customLayout customDrawSubviews:NO];
|
|
}
|
|
|
|
- (void)viewWithOptions:(CPInteger)options
|
|
{
|
|
var view = nil,
|
|
hasSubviews = NO;
|
|
|
|
switch (options)
|
|
{
|
|
case 0: view = [[ColorView alloc] initWithFrame:CGRectMakeZero()];
|
|
break;
|
|
|
|
case 2: view = [[ColorView alloc] initWithFrame:CGRectMakeZero()];
|
|
hasSubviews = YES;
|
|
break;
|
|
|
|
case 4:
|
|
case 6: view = [[CustomLayoutView alloc] initWithFrame:CGRectMakeZero()];
|
|
[view setBackgroundColor:[CPColor randomColor]];
|
|
hasSubviews = YES;
|
|
break;
|
|
|
|
case 12:
|
|
case 14: view = [[CustomLayoutDrawView alloc] initWithFrame:CGRectMakeZero()];
|
|
hasSubviews = YES;
|
|
break;
|
|
|
|
case 8: view = [[DrawView alloc] initWithFrame:CGRectMakeZero()];
|
|
break;
|
|
|
|
case 10: view = [[DrawView alloc] initWithFrame:CGRectMakeZero()];
|
|
hasSubviews = YES;
|
|
break;
|
|
|
|
}
|
|
|
|
var anims = [CPDictionary dictionaryWithObject:[self fadeOutAnimation] forKey:@"CPAnimationTriggerOrderOut"];
|
|
[view setAnimations:anims];
|
|
|
|
return view;
|
|
}
|
|
|
|
- (void)addSubviewsToView:(CPView)aView autoLayout:(BOOL)autoLayout customDrawSubviews:(BOOL)customDrawSubviews
|
|
{
|
|
var subViewClass = customDrawSubviews ? [DrawView class] : [ColorView class];
|
|
|
|
for (var i = 0; i < 5; i++)
|
|
{
|
|
var view = [[subViewClass alloc] initWithFrame:CGRectMake(50, i * 40, 80, 26)];
|
|
if (autoLayout)
|
|
[view setAutoresizingMask:CPViewWidthSizable|CPViewMinYMargin];
|
|
|
|
[aView addSubview:view];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation ColorView : CPView
|
|
{
|
|
}
|
|
|
|
- (id)initWithFrame:(CGRect)aFrame
|
|
{
|
|
self = [super initWithFrame:aFrame];
|
|
|
|
[self setBackgroundColor:[CPColor randomColor]];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)setFrameOrigin:(CGPoint)anOrigin
|
|
{
|
|
[super setFrameOrigin:anOrigin];
|
|
[[self superview] setNeedsDisplay:YES];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation DrawView : CPView
|
|
{
|
|
CPColor color @accessors;
|
|
}
|
|
|
|
- (id)initWithFrame:(CGRect)aFrame
|
|
{
|
|
self = [super initWithFrame:aFrame];
|
|
|
|
color = [CPColor randomColor];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)drawRect:(CGRect)aRect
|
|
{
|
|
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
|
bounds = [self bounds];
|
|
|
|
CGContextSetLineWidth(context, 2);
|
|
CGContextSetStrokeColor(context, [CPColor blackColor]);
|
|
CGContextSetFillColor(context, color);
|
|
|
|
CGContextBeginPath(context);
|
|
CGContextFillRect(context, bounds);
|
|
|
|
var height = CGRectGetHeight(bounds),
|
|
width = CGRectGetWidth(bounds);
|
|
|
|
CGContextStrokeLineSegments(context, [CGPointMake(10,0), CGPointMake(10, height),
|
|
CGPointMake(0, 10), CGPointMake(CGRectGetWidth(aRect), 10),
|
|
CGPointMake(width - 10, 0), CGPointMake(width - 10, height),
|
|
CGPointMake(0, height - 10), CGPointMake(width, height - 10)], 8);
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation CustomLayoutView : CPView
|
|
{
|
|
}
|
|
|
|
- (void)layoutSubviews
|
|
{
|
|
var subviews = [self subviews],
|
|
count = [subviews count] - 1;
|
|
|
|
var dx = (CGRectGetWidth([self frame]) - 100) / count,
|
|
dy = (CGRectGetHeight([self frame]) - 26) / count
|
|
|
|
[subviews enumerateObjectsUsingBlock:function(view, idx, stop)
|
|
{
|
|
[view setFrameOrigin:CGPointMake(dx * idx, dy * idx)];
|
|
}];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation CustomLayoutDrawView : DrawView
|
|
{
|
|
}
|
|
|
|
- (void)layoutSubviews
|
|
{
|
|
var subviews = [self subviews],
|
|
count = [subviews count] - 1;
|
|
|
|
var dx = (CGRectGetWidth([self frame]) - 100) / count,
|
|
dy = (CGRectGetHeight([self frame]) - 26) / count
|
|
|
|
[subviews enumerateObjectsUsingBlock:function(view, idx, stop)
|
|
{
|
|
[view setFrameOrigin:CGPointMake(dx * idx, dy * idx)];
|
|
}];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation AnimationSandbox : CPView
|
|
{
|
|
|
|
}
|
|
|
|
- (void)drawRect:(CGRect)aRect
|
|
{
|
|
if ([[self subviews] count] < 2)
|
|
return;
|
|
|
|
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
|
leftViewCenter = [[self viewWithTag:1] center],
|
|
rightViewCenter = [[self viewWithTag:2] center];
|
|
|
|
CGContextBeginPath(context);
|
|
CGContextMoveToPoint(context, leftViewCenter.x, leftViewCenter.y);
|
|
CGContextAddLineToPoint(context, rightViewCenter.x, rightViewCenter.y);
|
|
CGContextSetLineWidth(context, 2);
|
|
CGContextStrokePath(context);
|
|
}
|
|
|
|
@end
|