From 9a99195a7a540cb00ce9e228cf1db8276d967918 Mon Sep 17 00:00:00 2001 From: Cory Kilger Date: Fri, 17 Aug 2012 00:52:00 -0700 Subject: [PATCH] Animations are awesome. --- Seuss for iPad.xcodeproj/project.pbxproj | 4 + Seuss for iPad/SSCanvasView.m | 39 ++- Seuss for iPad/SSStatement.h | 1 + Seuss for iPad/SSStatementView.h | 8 +- Seuss for iPad/SSStatementView.m | 344 +++++++++++++---------- 5 files changed, 227 insertions(+), 169 deletions(-) diff --git a/Seuss for iPad.xcodeproj/project.pbxproj b/Seuss for iPad.xcodeproj/project.pbxproj index 84925e0..2948842 100644 --- a/Seuss for iPad.xcodeproj/project.pbxproj +++ b/Seuss for iPad.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 9A3E36C815BA74E400C3C268 /* SSCanvasView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3E36C715BA74E400C3C268 /* SSCanvasView.m */; }; 9A3E36CB15BA755E00C3C268 /* SSStatementView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3E36CA15BA755E00C3C268 /* SSStatementView.m */; }; 9A3E36CE15BA758100C3C268 /* SSVariableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3E36CD15BA758100C3C268 /* SSVariableView.m */; }; + 9A4EBA1D15DC4DE900A15E33 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A4EBA1C15DC4DE900A15E33 /* QuartzCore.framework */; }; 9A599F1015C26B72000DED43 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 9A599F0E15C26B72000DED43 /* Model.xcdatamodeld */; }; 9A599F3915C315E9000DED43 /* SSProgram+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A599F3815C315E9000DED43 /* SSProgram+Additions.m */; }; 9A599F4E15C4886B000DED43 /* NSManagedObject+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A599F4D15C4886B000DED43 /* NSManagedObject+Additions.m */; }; @@ -101,6 +102,7 @@ 9A3E36CA15BA755E00C3C268 /* SSStatementView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSStatementView.m; sourceTree = ""; }; 9A3E36CC15BA758100C3C268 /* SSVariableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSVariableView.h; sourceTree = ""; }; 9A3E36CD15BA758100C3C268 /* SSVariableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSVariableView.m; sourceTree = ""; }; + 9A4EBA1C15DC4DE900A15E33 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 9A599F0F15C26B72000DED43 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = ""; }; 9A599F3715C315E9000DED43 /* SSProgram+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SSProgram+Additions.h"; sourceTree = ""; }; 9A599F3815C315E9000DED43 /* SSProgram+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "SSProgram+Additions.m"; sourceTree = ""; }; @@ -151,6 +153,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9A4EBA1D15DC4DE900A15E33 /* QuartzCore.framework in Frameworks */, 9A599F8915C50C2E000DED43 /* CoreData.framework in Frameworks */, 9AB784AF15BBC703002CEE23 /* libseuss.a in Frameworks */, 9A3E369215BA745700C3C268 /* UIKit.framework in Frameworks */, @@ -217,6 +220,7 @@ 9A3E369115BA745700C3C268 /* UIKit.framework */, 9A3E369315BA745700C3C268 /* Foundation.framework */, 9A3E369515BA745700C3C268 /* CoreGraphics.framework */, + 9A4EBA1C15DC4DE900A15E33 /* QuartzCore.framework */, 9A599F8815C50C2E000DED43 /* CoreData.framework */, 9A3E36AF15BA745700C3C268 /* SenTestingKit.framework */, ); diff --git a/Seuss for iPad/SSCanvasView.m b/Seuss for iPad/SSCanvasView.m index 267b84e..7b1fb84 100644 --- a/Seuss for iPad/SSCanvasView.m +++ b/Seuss for iPad/SSCanvasView.m @@ -204,12 +204,12 @@ - (void)moveStatement:(UIGestureRecognizer *)gesture { - (void)moveParameter:(UIGestureRecognizer *)gesture { UIView * view = [gesture view]; - CGPoint point = [gesture locationInView:self.mainView]; switch (gesture.state) { case UIGestureRecognizerStateBegan: { if (!self.movingParameter) { UIView * movingView = view; if ([self.variableViews containsObject:movingView]) { + CGPoint point = [gesture locationInView:self.mainView]; movingView = [[SSVariableView alloc] initWithVariable:[(SSVariableView *)view variable]]; [movingView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(moveParameter:)]]; [movingView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveParameter:)]]; @@ -218,12 +218,17 @@ - (void)moveParameter:(UIGestureRecognizer *)gesture { movingView.layer.shadowOffset = CGSizeMake(0.0, 1.0); movingView.layer.shadowRadius = 3.0; movingView.layer.cornerRadius = 3.0; + movingView.center = point; + [self.mainView addSubview:movingView]; } else { // TODO: remove from the statement + SSStatementView * statementView = (SSStatementView *)[movingView superview]; + [statementView removeParameterForView:movingView]; + movingView.center = [gesture locationInView:statementView]; + [[movingView superview] bringSubviewToFront:movingView]; + [self.mainView bringSubviewToFront:statementView]; } - movingView.center = point; - [self.mainView addSubview:movingView]; self.movingParameter = movingView; [UIView animateWithDuration:0.1 animations:^{ movingView.transform = CGAffineTransformMakeScale(1.25, 1.25); @@ -234,15 +239,19 @@ - (void)moveParameter:(UIGestureRecognizer *)gesture { } break; case UIGestureRecognizerStateChanged: { - self.movingParameter.center = point; - [UIView animateWithDuration:0.2 animations:^{ - for (SSStatementView * statementView in self.statementViews) { - if (CGRectContainsPoint(statementView.frame, point)) - [statementView prepareForParameterView:self.movingParameter atPoint:[self convertPoint:point toView:statementView]]; - else - [statementView unprepare]; + UIView * movingView = self.movingParameter; + CGPoint point = [gesture locationInView:[movingView superview]]; + movingView.center = point; + for (SSStatementView * statementView in self.statementViews) { + if (CGRectContainsPoint(statementView.frame, [self.mainView convertPoint:point fromView:[movingView superview]])) { + CGPoint statementPoint = [[movingView superview] convertPoint:point toView:statementView]; + [statementView prepareForParameterView:movingView atPoint:statementPoint animated:YES]; } - }]; + else { + [statementView unprepareAnimated:YES]; + } + } + [[movingView superview] bringSubviewToFront:movingView]; } break; @@ -250,16 +259,16 @@ - (void)moveParameter:(UIGestureRecognizer *)gesture { BOOL added = NO; UIView * movingView = self.movingParameter; self.movingParameter = nil; - movingView.alpha = 1.0; - movingView.transform = CGAffineTransformIdentity; for (SSStatementView * statementView in self.statementViews) { + CGPoint point = [gesture locationInView:self.mainView]; if (CGRectContainsPoint(statementView.frame, point)) { - added = [statementView addParameterView:movingView atPoint:[self convertPoint:point toView:statementView]]; + [self.mainView bringSubviewToFront:statementView]; + added = [statementView addParameterView:movingView atPoint:[statementView convertPoint:point fromView:self.mainView]]; break; } } if (!added) { - [UIView animateWithDuration:0.1 animations:^{ + [UIView animateWithDuration:0.2 animations:^{ movingView.alpha = 0.0; } completion:^(BOOL finished) { [movingView removeFromSuperview]; diff --git a/Seuss for iPad/SSStatement.h b/Seuss for iPad/SSStatement.h index d6c4c17..f092ad5 100644 --- a/Seuss for iPad/SSStatement.h +++ b/Seuss for iPad/SSStatement.h @@ -18,6 +18,7 @@ @property (nonatomic, retain) SSCommand *command; @property (nonatomic, retain) NSSet *parameters; @property (nonatomic, retain) SSProgram *program; + @end @interface SSStatement (CoreDataGeneratedAccessors) diff --git a/Seuss for iPad/SSStatementView.h b/Seuss for iPad/SSStatementView.h index 8323927..80d8caa 100644 --- a/Seuss for iPad/SSStatementView.h +++ b/Seuss for iPad/SSStatementView.h @@ -7,6 +7,7 @@ // #import +#import @class SSStatement; @class SSCommand; @@ -20,10 +21,11 @@ - (void)addParameterGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer; -- (void)prepareForParameterView:(UIView *)variableView atPoint:(CGPoint)point; -- (void)prepareForParameterView:(UIView *)variableView atIndex:(NSUInteger)index; +- (void)prepareForParameterView:(UIView *)variableView atPoint:(CGPoint)point animated:(BOOL)animated; +- (void)prepareForParameterView:(UIView *)variableView atIndex:(NSUInteger)index animated:(BOOL)animated; - (BOOL)addParameterView:(UIView *)variableView atPoint:(CGPoint)point; - (BOOL)addParameterView:(UIView *)variableView atIndex:(NSUInteger)index; -- (void)unprepare; +- (BOOL)removeParameterForView:(UIView *)variableView; +- (void)unprepareAnimated:(BOOL)animated; @end diff --git a/Seuss for iPad/SSStatementView.m b/Seuss for iPad/SSStatementView.m index 487db32..90964b8 100644 --- a/Seuss for iPad/SSStatementView.m +++ b/Seuss for iPad/SSStatementView.m @@ -36,17 +36,14 @@ @interface SSStatementView () @property (strong, readwrite) SSStatement * statement; -@property (strong) SSParameter * previousParameter; - -- (UILabel *)signatureLabelAtIndex:(NSUInteger)index; -- (UIView *)parameterViewAtIndex:(NSUInteger)index; +@property NSUInteger preparedParameterIndex; @end @implementation SSStatementView @synthesize statement = _statement; -@synthesize previousParameter = _previousParameter; +@synthesize preparedParameterIndex = _preparedParameterIndex; - (id)initWithCommand:(SSCommand *)command { NSManagedObjectContext * context = [command managedObjectContext]; @@ -60,6 +57,7 @@ - (id)initWithStatement:(SSStatement *)statement { if (self) { self.statement = statement; self.backgroundColor = [UIColor clearColor]; + self.preparedParameterIndex = NSUIntegerMax; // Select background image UIImage * backgroundImage = nil; @@ -73,7 +71,7 @@ - (id)initWithStatement:(SSStatement *)statement { backgroundImageView.frame = self.bounds; [self addSubview:backgroundImageView]; - [self updateLayout]; + [self updateLayoutAnimated:NO]; } return self; } @@ -103,7 +101,7 @@ - (UIView *)parameterViewAtIndex:(NSUInteger)index { return [self viewWithTag:PARAMETER_BASE_INDEX+index]; } -- (void)prepareForParameterView:(SSVariableView *)variableView atPoint:(CGPoint)point { +- (void)prepareForParameterView:(SSVariableView *)variableView atPoint:(CGPoint)point animated:(BOOL)animated { CGFloat width = LEFT_PADDING; CGFloat variableWidth = CGRectGetWidth(variableView.frame); NSUInteger count = [self.statement.command.signature count]; @@ -112,7 +110,7 @@ - (void)prepareForParameterView:(SSVariableView *)variableView atPoint:(CGPoint) width += CGRectGetWidth(signatureLabel.frame) + MIDDLE_PADDING; if (point.x >= width && point.x <= width + variableWidth) { - [self prepareForParameterView:variableView atIndex:i]; + [self prepareForParameterView:variableView atIndex:i animated:animated]; return; } @@ -122,38 +120,14 @@ - (void)prepareForParameterView:(SSVariableView *)variableView atPoint:(CGPoint) parameterWidth = CGRectGetWidth(parameterView.frame); width += DEFAULT_VARIABLE_WIDTH + MIDDLE_PADDING; } - [self unprepare]; + [self unprepareAnimated:YES]; } -- (void)prepareForParameterView:(UIView *)parameterView atIndex:(NSUInteger)index { - if (!self.previousParameter) { - NSManagedObjectContext * context = self.statement.managedObjectContext; - - self.previousParameter.statement = self.statement; - - NSPredicate * predicate = [NSPredicate predicateWithFormat:@"order = %d", index]; - SSParameter * previousParameter = [[self.statement.parameters filteredSetUsingPredicate:predicate] anyObject]; - previousParameter.statement = nil; - self.previousParameter = previousParameter; - - SSParameter * newParameter = [[SSParameter alloc] initWithManagedObjectContext:context]; - newParameter.order = previousParameter.order; - newParameter.statement = self.statement; - - if ([parameterView isKindOfClass:[SSVariableView class]]) { - SSVariableView * variableView = (SSVariableView *)parameterView; - newParameter.variable = variableView.variable; - newParameter.type = SSParameterTypeVariable; - } - else if ([parameterView isKindOfClass:[SSStringView class]]) { - SSStringView * stringView = (SSStringView *)parameterView; - SSString * string = [[SSString alloc] initWithManagedObjectContext:context]; - string.value = stringView.string; - newParameter.string = string; - newParameter.type = SSParameterTypeString; - } - - [self updateLayoutWithPreparedWidth:CGRectGetWidth(parameterView.frame) atIndex:index]; +- (void)prepareForParameterView:(UIView *)parameterView atIndex:(NSUInteger)index animated:(BOOL)animated { + if (self.preparedParameterIndex == NSUIntegerMax) { + self.preparedParameterIndex = index; + CGRect frame = CGRectApplyAffineTransform(parameterView.frame, CGAffineTransformInvert(parameterView.transform)); + [self updateLayoutWithPreparedWidth:roundf(CGRectGetWidth(frame)) atIndex:index animated:animated]; } } @@ -182,8 +156,9 @@ - (BOOL)addParameterView:(UIView *)variableView atPoint:(CGPoint)point { - (BOOL)addParameterView:(UIView *)parameterView atIndex:(NSUInteger)index { NSManagedObjectContext * context = self.statement.managedObjectContext; - self.previousParameter = nil; + self.preparedParameterIndex = NSUIntegerMax; + // TODO: delete the previous parameter NSPredicate * predicate = [NSPredicate predicateWithFormat:@"order = %d", index]; SSParameter * previousParameter = [[self.statement.parameters filteredSetUsingPredicate:predicate] anyObject]; previousParameter.statement = nil; @@ -205,144 +180,211 @@ - (BOOL)addParameterView:(UIView *)parameterView atIndex:(NSUInteger)index { newParameter.type = SSParameterTypeString; } + CGPoint originalCenter = [self convertPoint:parameterView.center fromView:[parameterView superview]]; + CGAffineTransform originalTransform = parameterView.transform; + CGFloat originalAlpha = parameterView.alpha; + [[self viewWithTag:PARAMETER_BASE_INDEX + index] removeFromSuperview]; parameterView.tag = PARAMETER_BASE_INDEX + index; [self addSubview:parameterView]; - [self updateLayout]; + parameterView.transform = CGAffineTransformIdentity; + parameterView.alpha = 1.0; + + [self updateLayoutAnimated:NO]; + + CGPoint finalCenter = parameterView.center; + CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; + CGMutablePathRef path = CGPathCreateMutable(); + CGPathMoveToPoint(path, NULL, originalCenter.x, originalCenter.y); + CGPathAddLineToPoint(path, NULL, finalCenter.x, finalCenter.y-30); + CGPathAddLineToPoint(path, NULL, finalCenter.x, finalCenter.y); + animation.path = path; + animation.duration = 0.25; + animation.calculationMode = kCAAnimationPaced; + [parameterView.layer addAnimation:animation forKey:@"pathAnimation"]; + CGPathRelease(path); + + parameterView.transform = originalTransform; + parameterView.alpha = originalAlpha; + + [UIView animateWithDuration:0.25 animations:^{ + parameterView.transform = CGAffineTransformIdentity; + parameterView.alpha = 1.0; + }]; + return YES; } -- (void)unprepare { - if (self.previousParameter) { - // TODO: Delete temporary objects -// NSManagedObjectContext * context = self.statement.managedObjectContext; - int16_t order = self.previousParameter.order; - NSPredicate * predicate = [NSPredicate predicateWithFormat:@"order = %d", order]; - SSParameter * newParameter = [[self.statement.parameters filteredSetUsingPredicate:predicate] anyObject]; - newParameter.statement = nil; - self.previousParameter.statement = self.statement; -// [context deleteObject:newParameter.string]; -// [context deleteObject:newParameter]; - self.previousParameter = nil; - [self updateLayout]; +- (BOOL)removeParameterForView:(UIView *)parameterView { + NSUInteger index = parameterView.tag - PARAMETER_BASE_INDEX; + NSPredicate * predicate = [NSPredicate predicateWithFormat:@"order = %d", index]; + SSParameter * parameter = [[self.statement.parameters filteredSetUsingPredicate:predicate] anyObject]; + if (parameter) { + // TODO: delete parameter + parameter.statement = nil; + parameterView.tag = 0; + [self prepareForParameterView:parameterView atIndex:index animated:YES]; + return YES; } + return NO; } -- (void)updateLayout { - [self updateLayoutWithPreparedWidth:0 atIndex:NSUIntegerMax]; +- (void)unprepareAnimated:(BOOL)animated { + if (self.preparedParameterIndex != NSUIntegerMax) { + self.preparedParameterIndex = NSUIntegerMax; + [self updateLayoutAnimated:animated]; + } } -- (void)updateLayoutWithPreparedWidth:(CGFloat)preparedWidth atIndex:(NSUInteger)preparedIndex { - // Select background image - UIImage * slitBack = [[UIImage imageNamed:@"slit_back.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 16)]; - UIImage * slitFront = nil; - if ([self.statement.command.signatureKey caseInsensitiveCompare:@"Write"] == NSOrderedSame) - slitFront = [UIImage imageNamed:@"slit_front_blue.png"]; - else if ([self.statement.command.signatureKey caseInsensitiveCompare:@"Read"] == NSOrderedSame) - slitFront = [UIImage imageNamed:@"slit_front_green.png"]; - slitFront = [slitFront resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 16)]; - - NSSortDescriptor * sort = [[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES]; - NSArray * signature = [self.statement.command.signature sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; - NSArray * parameters = [self.statement.parameters sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; - - UIFont * font = SSStatementFont(); - CGFloat x = LEFT_PADDING; - NSUInteger index = 0; - NSUInteger parameterIndex = 0; - for (SSString * string in signature) { - NSString * value = string.value; - UILabel * label = [self signatureLabelAtIndex:index]; - CGFloat width = ceilf([value sizeWithFont:font].width); - label.frame = CGRectMake(x, PARAMETER_VERTICAL_PADDING, width, DEFAULT_HEIGHT - PARAMETER_VERTICAL_PADDING); - label.text = value; - [self addSubview:label]; - x += width + MIDDLE_PADDING; - - UIImageView * backSlitView = (UIImageView *)[self viewWithTag:PARAMETER_BACK_BASE_INDEX + index]; - if (!backSlitView) { - backSlitView = [[UIImageView alloc] initWithImage:slitBack]; - backSlitView.tag = PARAMETER_BACK_BASE_INDEX + index; - } - UIImageView * frontSlitView = (UIImageView *)[self viewWithTag:PARAMETER_FRONT_BASE_INDEX + index]; - if (!frontSlitView) { - frontSlitView = [[UIImageView alloc] initWithImage:slitFront]; - frontSlitView.tag = PARAMETER_FRONT_BASE_INDEX + index; - } - [self addSubview:backSlitView]; +- (void)updateLayoutAnimated:(BOOL)animated { + [self updateLayoutWithPreparedWidth:0 atIndex:NSUIntegerMax animated:animated]; +} + +- (void)updateLayoutWithPreparedWidth:(CGFloat)preparedWidth atIndex:(NSUInteger)preparedIndex animated:(BOOL)animated { + void(^updateLayout)(void) = ^{ + // Select background image + UIImage * slitBack = [[UIImage imageNamed:@"slit_back.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 16)]; + UIImage * slitFront = nil; + if ([self.statement.command.signatureKey caseInsensitiveCompare:@"Write"] == NSOrderedSame) + slitFront = [UIImage imageNamed:@"slit_front_blue.png"]; + else if ([self.statement.command.signatureKey caseInsensitiveCompare:@"Read"] == NSOrderedSame) + slitFront = [UIImage imageNamed:@"slit_front_green.png"]; + slitFront = [slitFront resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 16)]; - SSParameter * parameter = nil; - UIView * parameterView = [self parameterViewAtIndex:index]; + NSSortDescriptor * sort = [[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES]; + NSArray * signature = [self.statement.command.signature sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; + NSArray * parameters = [self.statement.parameters sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; - if (index == preparedIndex) { - if (parameterIndex < [parameters count] && (parameter = [parameters objectAtIndex:parameterIndex]) && parameter.order == index) - parameterIndex++; - backSlitView.frame = CGRectMake(x - 5, 15, preparedWidth + 10, CGRectGetHeight(backSlitView.frame)); - frontSlitView.frame = CGRectMake(x - 5, 45, preparedWidth + 10, CGRectGetHeight(frontSlitView.frame)); - parameterView.hidden = YES; - x += preparedWidth + MIDDLE_PADDING; - } - else if (parameterIndex < [parameters count] && (parameter = [parameters objectAtIndex:parameterIndex]) && parameter.order == index) { - parameterIndex++; + UIFont * font = SSStatementFont(); + CGFloat x = LEFT_PADDING; + NSUInteger index = 0; + NSUInteger parameterIndex = 0; + for (SSString * string in signature) { + NSString * value = string.value; + UILabel * label = [self signatureLabelAtIndex:index]; + CGFloat width = ceilf([value sizeWithFont:font].width); + label.frame = CGRectMake(x, PARAMETER_VERTICAL_PADDING, width, DEFAULT_HEIGHT - PARAMETER_VERTICAL_PADDING); + label.text = value; + [self addSubview:label]; + x += width + MIDDLE_PADDING; - if (!parameterView) { - switch (parameter.type) { - case SSParameterTypeVariable: { - parameterView = [[SSVariableView alloc] initWithVariable:parameter.variable]; - } break; - - case SSParameterTypeString: { - parameterView = [[SSStringView alloc] initWithString:parameter.string.value]; - } break; - - default: - break; - } - - parameterView.tag = PARAMETER_BASE_INDEX + index; + UIImageView * backSlitView = (UIImageView *)[self viewWithTag:PARAMETER_BACK_BASE_INDEX + index]; + if (!backSlitView) { + backSlitView = [[UIImageView alloc] initWithImage:slitBack]; + backSlitView.tag = PARAMETER_BACK_BASE_INDEX + index; } + UIImageView * frontSlitView = (UIImageView *)[self viewWithTag:PARAMETER_FRONT_BASE_INDEX + index]; + if (!frontSlitView) { + frontSlitView = [[UIImageView alloc] initWithImage:slitFront]; + frontSlitView.tag = PARAMETER_FRONT_BASE_INDEX + index; + } + [self addSubview:backSlitView]; - CGRect parameterFrame = parameterView.frame; - parameterFrame.origin.x = x; - parameterFrame.origin.y = PARAMETER_VERTICAL_PADDING; - parameterView.frame = parameterFrame; - parameterView.hidden = NO; + SSParameter * parameter = nil; + UIView * parameterView = [self parameterViewAtIndex:index]; - backSlitView.frame = CGRectMake(x - 5, 15, CGRectGetWidth(parameterFrame) + 10, CGRectGetHeight(backSlitView.frame)); - frontSlitView.frame = CGRectMake(x - 5, 45, CGRectGetWidth(parameterFrame) + 10, CGRectGetHeight(frontSlitView.frame)); + if (index == preparedIndex) { + if (parameterIndex < [parameters count] && (parameter = [parameters objectAtIndex:parameterIndex]) && parameter.order == index) + parameterIndex++; + backSlitView.frame = CGRectMake(x - 5, 15, preparedWidth + 10, CGRectGetHeight(backSlitView.frame)); + frontSlitView.frame = CGRectMake(x - 5, 45, preparedWidth + 10, CGRectGetHeight(frontSlitView.frame)); +// parameterView.alpha = 0.0; + x += preparedWidth + MIDDLE_PADDING; + } + else if (parameterIndex < [parameters count] && (parameter = [parameters objectAtIndex:parameterIndex]) && parameter.order == index) { + parameterIndex++; + + if (!parameterView) { + switch (parameter.type) { + case SSParameterTypeVariable: { + parameterView = [[SSVariableView alloc] initWithVariable:parameter.variable]; + } break; + + case SSParameterTypeString: { + parameterView = [[SSStringView alloc] initWithString:parameter.string.value]; + } break; + + default: + break; + } + + parameterView.tag = PARAMETER_BASE_INDEX + index; + } + + CGRect parameterFrame = parameterView.frame; + parameterFrame.origin.x = x; + parameterFrame.origin.y = PARAMETER_VERTICAL_PADDING; + parameterView.frame = parameterFrame; +// parameterView.alpha = 1.0; + + backSlitView.frame = CGRectMake(x - 5, 15, CGRectGetWidth(parameterFrame) + 10, CGRectGetHeight(backSlitView.frame)); + frontSlitView.frame = CGRectMake(x - 5, 45, CGRectGetWidth(parameterFrame) + 10, CGRectGetHeight(frontSlitView.frame)); + + [self addSubview:parameterView]; + + x += CGRectGetWidth(parameterFrame) + MIDDLE_PADDING; + } + else { + [parameterView removeFromSuperview]; + backSlitView.frame = CGRectMake(x - 5, 15, DEFAULT_VARIABLE_WIDTH + 10, CGRectGetHeight(backSlitView.frame)); + frontSlitView.frame = CGRectMake(x - 5, 45, DEFAULT_VARIABLE_WIDTH + 10, CGRectGetHeight(frontSlitView.frame)); + x += DEFAULT_VARIABLE_WIDTH + MIDDLE_PADDING; + } - [self addSubview:parameterView]; + [self addSubview:frontSlitView]; - x += CGRectGetWidth(parameterFrame) + MIDDLE_PADDING; - } - else { - [parameterView removeFromSuperview]; - backSlitView.frame = CGRectMake(x - 5, 15, DEFAULT_VARIABLE_WIDTH + 10, CGRectGetHeight(backSlitView.frame)); - frontSlitView.frame = CGRectMake(x - 5, 45, DEFAULT_VARIABLE_WIDTH + 10, CGRectGetHeight(frontSlitView.frame)); - x += DEFAULT_VARIABLE_WIDTH + MIDDLE_PADDING; + index++; } - [self addSubview:frontSlitView]; + static NSString * periodString = @"."; + CGFloat periodWidth = [periodString sizeWithFont:font].width; + UILabel * periodLabel = [self signatureLabelAtIndex:index]; + periodLabel.frame = CGRectMake(x, PARAMETER_VERTICAL_PADDING, periodWidth, DEFAULT_HEIGHT - PARAMETER_VERTICAL_PADDING); + periodLabel.text = periodString; - index++; - } - - static NSString * periodString = @"."; - CGFloat periodWidth = [periodString sizeWithFont:font].width; - UILabel * periodLabel = [self signatureLabelAtIndex:index]; - periodLabel.frame = CGRectMake(x, PARAMETER_VERTICAL_PADDING, periodWidth, DEFAULT_HEIGHT - PARAMETER_VERTICAL_PADDING); - periodLabel.text = periodString; - - x += periodWidth + RIGHT_PADDING; + x += periodWidth + RIGHT_PADDING; + + CGRect frame = self.frame; + frame.size.width = x; + frame.size.height = DEFAULT_HEIGHT; + self.frame = frame; + + [self addSubview:periodLabel]; + }; - CGRect frame = self.frame; - frame.size.width = x; - frame.size.height = DEFAULT_HEIGHT; - self.frame = frame; + void(^updateAlpha)(void) = ^{ + for (NSUInteger i = 0; i < [self.statement.command.signature count]; i++) { + UIView * view = [self parameterViewAtIndex:i]; + if (i == preparedIndex) + view.alpha = 0.0; + else + view.alpha = 1.0; + } + }; - [self addSubview:periodLabel]; + if (animated) { + UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState; + if (preparedIndex == NSUIntegerMax) { + [UIView animateWithDuration:0.2 delay:0.0 options:options animations:updateLayout completion:^(BOOL finished) { + if (finished) { + [UIView animateWithDuration:0.2 delay:0.0 options:options animations:updateAlpha completion:NULL]; + } + }]; + } + else { + [UIView animateWithDuration:0.2 delay:0.0 options:options animations:updateAlpha completion:^(BOOL finished) { + if (finished) { + [UIView animateWithDuration:0.2 delay:0.0 options:options animations:updateLayout completion:NULL]; + } + }]; + } + } + else { + updateLayout(); + updateAlpha(); + } } @end