// -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ // // This file is part of the LibreOffice project. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #import "MLOAnimation.h" typedef CGFloat (^MLOAnimationCurve)(CGFloat time); @interface MLOAnimation () @property BOOL active,didPost,cancelled; @property CGFloat frameCount; @property NSDate * startDate; @property MLOAnimationBehavior behavior; @property MLOAnimationFractionType fractionType; @property (nonatomic,strong) MLOAnimationBlock animation; @property (nonatomic,strong) MLOAnimationCurve curve; @end @implementation MLOAnimation -(void) linearCurve{ static const MLOAnimationCurve LINEAR = ^(CGFloat completedFraction){ return completedFraction; }; [self setCurve:LINEAR name:@"LINEAR"]; } -(void) easeOutCurve{ static const MLOAnimationCurve EASE_OUT = ^(CGFloat completedFraction){ return 1 - completedFraction*completedFraction; }; [self setCurve:EASE_OUT name:@"EASE_OUT"]; } -(void) easeInCurve{ static const MLOAnimationCurve EASE_IN = ^(CGFloat completedFraction){ return completedFraction*completedFraction; }; [self setCurve:EASE_IN name:@"EASE_IN"]; } -(void)setCurve:(MLOAnimationCurve) curve name:(NSString *) name{ self.curve = curve; NSLog(@"MLOAnimation curve set to: %@",name); } -(void) cancel{ if(_behavior == CANCELABLE){ self.cancelled= YES; self.active = NO; [self doPost:nil]; if(_startDate){ NSLog(@"MLOAnimation cancelled after %f millis",[_startDate timeIntervalSinceNow]); }else{ NSLog(@"MLOAnimation aborted"); } }else{ NSLog(@"CLOAnimation cannot be cancelled"); } } -(BOOL) isCancelled{ return self.cancelled; } -(id)initWithBehavior:(BOOL) behavior fractionType:(MLOAnimationFractionType) fractionType animation:(MLOAnimationBlock) animation{ self = [super init]; if(self){ _active=YES; _duration = DEFAULT_MLO_ANIMATION_DURAION; _fps = DEFAULT_ANIMATION_FPS; _behavior=CANCELABLE; _fractionType = fractionType; _frameCount = -1.0f; _startDate = nil; _didPost =NO; _cancelled=NO; [self linearCurve]; self.animation = animation; } return self; } -(void)animate{ if(!_startDate){ self.startDate = [NSDate date]; _frameCount = _duration *_fps; if(_frameCount>0){ CGFloat frameDuration = 1.0f/_fps; NSLog(@"MLOAnimation: duration=%f frameCount=%f fps=%f frameDuration=%f fractionType=%@",_duration,_frameCount,_fps,frameDuration,[self fractionTypeAsString]); for (CGFloat i = 1; i <= _frameCount; i++) { [self performSelector:@selector(doFrame:) withObject:[NSNumber numberWithFloat:i] afterDelay: i*frameDuration]; } [self performSelector:@selector(doPost:) withObject:nil afterDelay:_duration + frameDuration]; }else{ NSLog(@"MLOAnimation cannot run (zero frames)"); } } } -(void) doPost:(NSObject *) niller{ if(!_didPost){ _didPost = YES; if(_endBlock){ _endBlock(); } } } -(NSString *)fractionTypeAsString{ switch (_fractionType) { case DELTA_ONLY: return @"DELTA_ONLY"; case FULL_FRACTION: return @"FULL_FRACTION"; } } -(void)doFrame:(NSNumber *) frame{ if(_active){ CGFloat fFrame = [frame floatValue]; CGFloat currentFraction = _curve(fFrame/_frameCount); if(_fractionType == DELTA_ONLY){ currentFraction -= _curve( (fFrame-1.0f) /_frameCount); } _animation(_curve(currentFraction)); if(fFrame ==_frameCount){ _behavior =MANDATORY; } } } @end