From 80b621e741fa7fd59ee5dd4eef224e773133bb1c Mon Sep 17 00:00:00 2001 From: Fabio G Date: Wed, 17 Mar 2021 18:42:00 +0100 Subject: [PATCH] CATTY-442 Copy Brick with nested Bricks --- src/Catty.xcodeproj/project.pbxproj | 4 + .../DataModel/Bricks/Control/LoopBeginBrick.m | 11 + .../DataModel/Bricks/Control/LoopEndBrick.m | 2 +- .../Localization/en.lproj/Localizable.strings | 28 +- .../BrickManager/BrickManager.h | 2 +- .../BrickManager/BrickManager.m | 251 ++++++++++++++++-- .../ScriptCollectionViewController.m | 2 +- .../BrickInsertManagerTests.m | 2 +- .../Bricks/BrickManager/BrickCopyTests.swift | 229 ++++++++++++++++ src/CattyUITests/ObjectTVCTests.swift | 2 +- 10 files changed, 491 insertions(+), 42 deletions(-) create mode 100644 src/CattyTests/Bricks/BrickManager/BrickCopyTests.swift diff --git a/src/Catty.xcodeproj/project.pbxproj b/src/Catty.xcodeproj/project.pbxproj index 3ca775017b..1604ea2114 100644 --- a/src/Catty.xcodeproj/project.pbxproj +++ b/src/Catty.xcodeproj/project.pbxproj @@ -1744,6 +1744,7 @@ E4C5C1122143A3150054F236 /* SearchStoreDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C5C1112143A3150054F236 /* SearchStoreDataSourceTests.swift */; }; E4E5599820FCD6AD004B4A08 /* StoreProject.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4E5599620FCD6AD004B4A08 /* StoreProject.swift */; }; E5103DEE25CAE67300A32DF8 /* StagePresenterSideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5103DED25CAE67300A32DF8 /* StagePresenterSideMenuView.swift */; }; + E5635D8625FFB118001E4297 /* BrickCopyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5635D8525FFB118001E4297 /* BrickCopyTests.swift */; }; E564EBE1255D60F5001F0CD0 /* PlayButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E564EBE0255D60F4001F0CD0 /* PlayButton.swift */; }; E577F0462563C5A400368C18 /* BrickCategoryOverviewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E577F0452563C5A400368C18 /* BrickCategoryOverviewController.swift */; }; E577F04A2563E8F200368C18 /* BrickCategoryOverviewCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E577F0492563E8F200368C18 /* BrickCategoryOverviewCollectionViewCell.swift */; }; @@ -4186,6 +4187,7 @@ E4E5599620FCD6AD004B4A08 /* StoreProject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreProject.swift; sourceTree = ""; }; E5103DED25CAE67300A32DF8 /* StagePresenterSideMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StagePresenterSideMenuView.swift; sourceTree = ""; }; E5505707FE2839B02A26E338 /* en-AU */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = "en-AU"; path = "en-AU.lproj/Localizable.strings"; sourceTree = ""; }; + E5635D8525FFB118001E4297 /* BrickCopyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrickCopyTests.swift; sourceTree = ""; }; E564EBE0255D60F4001F0CD0 /* PlayButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayButton.swift; sourceTree = ""; }; E57396A397CC08132F593B32 /* en */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; E577F0452563C5A400368C18 /* BrickCategoryOverviewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrickCategoryOverviewController.swift; sourceTree = ""; }; @@ -5697,6 +5699,7 @@ isa = PBXGroup; children = ( 4C38B3732371522200F33721 /* BrickManagerTests.swift */, + E5635D8525FFB118001E4297 /* BrickCopyTests.swift */, ); path = BrickManager; sourceTree = ""; @@ -11711,6 +11714,7 @@ 4C822659213FA7A400F3D750 /* AudioManagerMock.swift in Sources */, 9E4D238C232AF688009D0C3C /* SetColorBrickTests.swift in Sources */, 6F9CF123246E8767008CED1C /* UserListTest.swift in Sources */, + E5635D8625FFB118001E4297 /* BrickCopyTests.swift in Sources */, D3C6E3A824C8134A00A9E186 /* GoToBrickTests.swift in Sources */, 4CD27AAA21B5765C00DDADB5 /* FeatureMock.swift in Sources */, 4CEB22501B95E47500B3BE2F /* BrickMoveManagerLogicTests.m in Sources */, diff --git a/src/Catty/DataModel/Bricks/Control/LoopBeginBrick.m b/src/Catty/DataModel/Bricks/Control/LoopBeginBrick.m index c43fc95259..f37c1488da 100644 --- a/src/Catty/DataModel/Bricks/Control/LoopBeginBrick.m +++ b/src/Catty/DataModel/Bricks/Control/LoopBeginBrick.m @@ -25,11 +25,22 @@ @implementation LoopBeginBrick +- (kBrickCategoryType)category +{ + return kControlBrick; +} + - (BOOL)isLoopBrick { return YES; } +#pragma mark - Description +- (NSString*)description +{ + return [NSString stringWithFormat:@"Loop Begin Brick"]; +} + #pragma mark - Compare - (BOOL)isEqualToBrick:(Brick*)brick { diff --git a/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m b/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m index 0f28fbbc77..0c3b85e981 100644 --- a/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m +++ b/src/Catty/DataModel/Bricks/Control/LoopEndBrick.m @@ -55,7 +55,7 @@ - (void)performFromScript:(Script*)script #pragma mark - Description - (NSString*)description { - return [NSString stringWithFormat:@"EndLoop"]; + return [NSString stringWithFormat:@"Loop End Brick"]; } #pragma mark - Compare diff --git a/src/Catty/Resources/Localization/en.lproj/Localizable.strings b/src/Catty/Resources/Localization/en.lproj/Localizable.strings index b02e234ba1..0029cf9741 100644 --- a/src/Catty/Resources/Localization/en.lproj/Localizable.strings +++ b/src/Catty/Resources/Localization/en.lproj/Localizable.strings @@ -169,12 +169,12 @@ /* No comment provided by engineer. */ "Before you can start coding, please read and accept our Privacy Policy to use the app:" = "Before you can start coding, please read and accept our Privacy Policy to use the app:"; -/* No comment provided by engineer. */ -"blue" = "blue"; - /* paint */ "Blue" = "Blue"; +/* No comment provided by engineer. */ +"blue" = "blue"; + /* No comment provided by engineer. */ "Bluetooth is not available. Either your device does not support Bluetooth 4.0 or your Bluetooth chip is damaged. Please check it by connection to another Bluetooth device in the Settings." = "Bluetooth is not available. Either your device does not support Bluetooth 4.0 or your Bluetooth chip is damaged. Please check it by connection to another Bluetooth device in the Settings."; @@ -763,12 +763,12 @@ /* No comment provided by engineer. */ "Go to front" = "Go to front"; -/* No comment provided by engineer. */ -"green" = "green"; - /* paint */ "Green" = "Green"; +/* No comment provided by engineer. */ +"green" = "green"; + /* No comment provided by engineer. */ "Guitar" = "Guitar"; @@ -905,10 +905,10 @@ "left-right only" = "left-right only"; /* No comment provided by engineer. */ -"length" = "length"; +"Length" = "Length"; /* No comment provided by engineer. */ -"Length" = "Length"; +"length" = "length"; /* No comment provided by engineer. */ "letter" = "letter"; @@ -958,12 +958,12 @@ /* No comment provided by engineer. */ "longitude" = "longitude"; -/* LOOK */ -"look" = "look"; - /* No comment provided by engineer. */ "Look" = "Look"; +/* LOOK */ +"look" = "look"; + /* No comment provided by engineer. */ "look name" = "look name"; @@ -1381,12 +1381,12 @@ /* paint */ "Rectangle / Square" = "Rectangle / Square"; -/* paint */ -"Red" = "Red"; - /* No comment provided by engineer. */ "red" = "red"; +/* paint */ +"Red" = "Red"; + /* No comment provided by engineer. */ "Register" = "Register"; diff --git a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.h b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.h index dfc3b93755..cfa41d6936 100644 --- a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.h +++ b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.h @@ -39,7 +39,7 @@ - (CGSize)sizeForBrick:(id)brick; - (NSInteger)checkEndLoopBrickTypeForDrawing:(BrickCell*)cell; - (NSArray*)animateWithIndexPath:(NSIndexPath*)path Script:(Script*)script andBrick:(Brick*)brick; -- (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath andBrick:(Brick*)brick; +- (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath Brick:(Brick*)brick nestedIndexOrZero:(int)nestedInteger; - (NSArray*)getIndexPathsForRemovingBricks:(NSIndexPath*)indexPath andBrick:(Brick*)brick; @end diff --git a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.m b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.m index 62a28fdea4..8d55f0f7db 100644 --- a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.m +++ b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/BrickManager/BrickManager.m @@ -336,32 +336,101 @@ - (NSArray*)ifBrickForAnimationIndexPath:(NSIndexPath*)indexPath Script:(Script* #pragma mark ScriptCollectionViewController Copy -- (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath andBrick:(Brick*)brick +- (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath Brick:(Brick*)brick nestedIndexOrZero:(int)nestedIndex { if ([brick isLoopBrick]) { // loop brick LoopBeginBrick *loopBeginBrick = nil; LoopEndBrick *loopEndBrick = nil; + NSUInteger loopBeginIndex = 0; + NSUInteger loopEndIndex = 0; + NSMutableArray *nestedBricks = [NSMutableArray new]; + if ([brick isKindOfClass:[LoopBeginBrick class]]) { loopBeginBrick = ((LoopBeginBrick*)brick); loopEndBrick = loopBeginBrick.loopEndBrick; + + loopBeginIndex = [brick.script.brickList indexOfObject:loopBeginBrick]; + loopEndIndex = [brick.script.brickList indexOfObject:loopEndBrick]; } else { CBAssert([brick isKindOfClass:[LoopEndBrick class]]); loopEndBrick = ((LoopEndBrick*)brick); loopBeginBrick = loopEndBrick.loopBeginBrick; + + loopBeginIndex = [brick.script.brickList indexOfObject:loopBeginBrick]; + loopEndIndex = [brick.script.brickList indexOfObject:loopEndBrick]; } + + for (int i = (int) loopBeginIndex + 1; i < loopEndIndex; i++) + { + Brick *object = [brick.script.brickList objectAtIndex:i]; + [nestedBricks addObject:object]; + } + CBAssert((loopBeginBrick != nil) || (loopEndBrick != nil)); - NSUInteger loopBeginIndex = [brick.script.brickList indexOfObject:loopBeginBrick]; - NSUInteger loopEndIndex = (loopBeginIndex + 1); + + //create copies LoopBeginBrick *copiedLoopBeginBrick = [loopBeginBrick mutableCopyWithContext:[CBMutableCopyContext new]]; LoopEndBrick *copiedLoopEndBrick = [loopEndBrick mutableCopyWithContext:[CBMutableCopyContext new]]; copiedLoopBeginBrick.loopEndBrick = copiedLoopEndBrick; copiedLoopEndBrick.loopBeginBrick = copiedLoopBeginBrick; - [brick.script addBrick:copiedLoopBeginBrick atIndex:loopBeginIndex]; - [brick.script addBrick:copiedLoopEndBrick atIndex:loopEndIndex]; - NSIndexPath *loopBeginIndexPath = [NSIndexPath indexPathForItem:(loopBeginIndex + 1) inSection:indexPath.section]; - NSIndexPath *loopEndIndexPath = [NSIndexPath indexPathForItem:(loopBeginIndex + 2) inSection:indexPath.section]; - return @[loopBeginIndexPath, loopEndIndexPath]; + if(nestedIndex == 0) + { + [brick.script addBrick:copiedLoopBeginBrick atIndex:loopBeginIndex]; + } + else + { + [brick.script addBrick:copiedLoopBeginBrick atIndex:nestedIndex]; + } + NSMutableArray *returnValues = [NSMutableArray new]; + NSIndexPath *loopIndexPath = [NSIndexPath indexPathForItem:( 1 + nestedIndex) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + NSInteger loopBeginIndexCopy = loopBeginIndex + 1; + Brick *nestedBrick; + //for(Brick *nestedBrick in nestedBricks) + for(int i = 0; i < nestedBricks.count; i++) + { + nestedBrick = nestedBricks[i]; + if([nestedBrick isKindOfClass:[LoopBeginBrick class]] || [nestedBrick isKindOfClass:[IfThenLogicBeginBrick class]] || [nestedBrick isKindOfClass:[IfLogicBeginBrick class]] ) + { + NSArray* nestedLoopOrLogic = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:[NSIndexPath indexPathForItem:(i + 2) inSection:indexPath.section] Brick:nestedBrick nestedIndexOrZero:(int)loopBeginIndex + 1 + i - nestedIndex]; + [returnValues addObjectsFromArray:nestedLoopOrLogic]; + i += nestedLoopOrLogic.count-1; + } + else if ([nestedBrick isKindOfClass:[IfLogicElseBrick class]] ) + { + NSError(@"Copying wrong Brick, Should not happen!!"); + } + else if ([nestedBrick isKindOfClass:[LoopEndBrick class]] || [nestedBrick isKindOfClass:[IfThenLogicEndBrick class]] || [nestedBrick isKindOfClass:[IfLogicEndBrick class]]) + { + NSError(@"Copying wrong Brick, Should not happen!!"); + } + else + { + if(nestedIndex == 0) + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:loopBeginIndex + 1 + i]; + } + else + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:nestedIndex + 1 + i]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + i) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + } + } + + if(nestedIndex == 0) + { + [brick.script addBrick:copiedLoopEndBrick atIndex:loopBeginIndexCopy + nestedBricks.count]; + } + else + { + [brick.script addBrick:copiedLoopEndBrick atIndex:nestedIndex + 1 + nestedBricks.count]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(1 + nestedIndex + nestedBricks.count) inSection:indexPath.section]; //HERE + [returnValues addObject:loopIndexPath]; + return returnValues; } else if ([brick isIfLogicBrick]) { // if brick @@ -370,6 +439,7 @@ - (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath andBr IfLogicBeginBrick *ifLogicBeginBrick = nil; IfLogicElseBrick *ifLogicElseBrick = nil; IfLogicEndBrick *ifLogicEndBrick = nil; + NSMutableArray *nestedBricks = [NSMutableArray new]; if ([brick isKindOfClass:[IfThenLogicBeginBrick class]]) { ifThenLogicBeginBrick = ((IfThenLogicBeginBrick*)brick); ifThenLogicEndBrick = ifThenLogicBeginBrick.ifEndBrick; @@ -393,8 +463,8 @@ - (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath andBr if(ifLogicBeginBrick != nil) { CBAssert((ifLogicBeginBrick != nil) && (ifLogicElseBrick != nil) && (ifLogicEndBrick != nil)); NSUInteger ifLogicBeginIndex = [brick.script.brickList indexOfObject:ifLogicBeginBrick]; - NSUInteger ifLogicElseIndex = (ifLogicBeginIndex + 1); - NSUInteger ifLogicEndIndex = (ifLogicElseIndex + 1); + NSUInteger ifLogicEndIndex = [brick.script.brickList indexOfObject:ifLogicEndBrick]; + IfLogicBeginBrick *copiedIfLogicBeginBrick = [ifLogicBeginBrick mutableCopyWithContext:[CBMutableCopyContext new]]; IfLogicElseBrick *copiedIfLogicElseBrick = [ifLogicElseBrick mutableCopyWithContext:[CBMutableCopyContext new]]; IfLogicEndBrick *copiedIfLogicEndBrick = [ifLogicEndBrick mutableCopyWithContext:[CBMutableCopyContext new]]; @@ -404,26 +474,161 @@ - (NSArray*)scriptCollectionCopyBrickWithIndexPath:(NSIndexPath*)indexPath andBr copiedIfLogicElseBrick.ifEndBrick = copiedIfLogicEndBrick; copiedIfLogicEndBrick.ifBeginBrick = copiedIfLogicBeginBrick; copiedIfLogicEndBrick.ifElseBrick = copiedIfLogicElseBrick; - [brick.script addBrick:copiedIfLogicBeginBrick atIndex:ifLogicBeginIndex]; - [brick.script addBrick:copiedIfLogicElseBrick atIndex:ifLogicElseIndex]; - [brick.script addBrick:copiedIfLogicEndBrick atIndex:ifLogicEndIndex]; - NSIndexPath *ifLogicBeginIndexPath = [NSIndexPath indexPathForItem:(ifLogicBeginIndex + 1) inSection:indexPath.section]; - NSIndexPath *ifLogicElseIndexPath = [NSIndexPath indexPathForItem:(ifLogicBeginIndex + 2) inSection:indexPath.section]; - NSIndexPath *ifLogicEndIndexPath = [NSIndexPath indexPathForItem:(ifLogicBeginIndex + 3) inSection:indexPath.section]; - return @[ifLogicBeginIndexPath, ifLogicElseIndexPath, ifLogicEndIndexPath]; + + for (int i = (int) ifLogicBeginIndex + 1; i < ifLogicEndIndex; i++) + { + Brick *object = [brick.script.brickList objectAtIndex:i]; + [nestedBricks addObject:object]; + } + + if(nestedIndex == 0) + { + [brick.script addBrick:copiedIfLogicBeginBrick atIndex:ifLogicBeginIndex]; + } + else + { + [brick.script addBrick:copiedIfLogicBeginBrick atIndex:nestedIndex]; + } + NSMutableArray *returnValues = [NSMutableArray new]; + NSIndexPath *loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 1) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + Brick *nestedBrick; + + for(int i = 0; i < nestedBricks.count; i++) + { + nestedBrick = nestedBricks[i]; + if([nestedBrick isKindOfClass:[LoopBeginBrick class]] || [nestedBrick isKindOfClass:[IfThenLogicBeginBrick class]] || [nestedBrick isKindOfClass:[IfLogicBeginBrick class]] ) + { + NSArray* nestedLoopOrLogic = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:[NSIndexPath indexPathForItem:(i + 2) inSection:indexPath.section] Brick:nestedBrick nestedIndexOrZero:(int)ifLogicBeginIndex + 1 + i - nestedIndex]; + [returnValues addObjectsFromArray:nestedLoopOrLogic]; + i += nestedLoopOrLogic.count-1; + } + else if ([nestedBrick isKindOfClass:[IfLogicElseBrick class]] ) + { + if(nestedIndex == 0) + { + [brick.script addBrick:copiedIfLogicElseBrick atIndex:ifLogicBeginIndex + 1 + i]; + } + else + { + [brick.script addBrick:copiedIfLogicElseBrick atIndex:nestedIndex + 1 + i]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + i) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + } + else if ([nestedBrick isKindOfClass:[LoopEndBrick class]] || [nestedBrick isKindOfClass:[IfThenLogicEndBrick class]] || [nestedBrick isKindOfClass:[IfLogicEndBrick class]]) + { + NSError(@"Copying wrong Brick, Should not happen!!"); + } + else + { + if(nestedIndex == 0) + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:ifLogicBeginIndex + 1 + i]; + } + else + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:nestedIndex + 1 + i]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + i) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + } + } + + if(nestedIndex == 0) + { + [brick.script addBrick:copiedIfLogicEndBrick atIndex:ifLogicBeginIndex + 1 + nestedBricks.count]; + } + else + { + [brick.script addBrick:copiedIfLogicEndBrick atIndex:nestedIndex + 1 + nestedBricks.count]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + nestedBricks.count) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + return returnValues; + } else if(ifThenLogicBeginBrick != nil){ CBAssert((ifThenLogicBeginBrick != nil) && (ifLogicElseBrick == nil) && (ifThenLogicEndBrick != nil)); NSUInteger ifLogicBeginIndex = [brick.script.brickList indexOfObject:ifThenLogicBeginBrick]; - NSUInteger ifLogicEndIndex = (ifLogicBeginIndex + 1); + NSUInteger ifLogicEndIndex = [brick.script.brickList indexOfObject:ifThenLogicEndBrick]; + + for (int i = (int) ifLogicBeginIndex + 1; i < ifLogicEndIndex; i++) + { + Brick *object = [brick.script.brickList objectAtIndex:i]; + [nestedBricks addObject:object]; + } IfThenLogicBeginBrick *copiedIfLogicBeginBrick = [ifThenLogicBeginBrick mutableCopyWithContext:[CBMutableCopyContext new]]; IfThenLogicEndBrick *copiedIfLogicEndBrick = [ifThenLogicEndBrick mutableCopyWithContext:[CBMutableCopyContext new]]; copiedIfLogicBeginBrick.ifEndBrick = copiedIfLogicEndBrick; copiedIfLogicEndBrick.ifBeginBrick = copiedIfLogicBeginBrick; - [brick.script addBrick:copiedIfLogicBeginBrick atIndex:ifLogicBeginIndex]; - [brick.script addBrick:copiedIfLogicEndBrick atIndex:ifLogicEndIndex]; - NSIndexPath *ifLogicBeginIndexPath = [NSIndexPath indexPathForItem:(ifLogicBeginIndex + 1) inSection:indexPath.section]; - NSIndexPath *ifLogicEndIndexPath = [NSIndexPath indexPathForItem:(ifLogicBeginIndex + 2) inSection:indexPath.section]; - return @[ifLogicBeginIndexPath, ifLogicEndIndexPath]; + + if(nestedIndex == 0) + { + [brick.script addBrick:copiedIfLogicBeginBrick atIndex:ifLogicBeginIndex]; + } + else + { + [brick.script addBrick:copiedIfLogicBeginBrick atIndex:nestedIndex]; + } + NSMutableArray *returnValues = [NSMutableArray new]; + NSIndexPath *loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 1) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + Brick *nestedBrick; + + + for(int i = 0; i < nestedBricks.count; i++) + { + nestedBrick = nestedBricks[i]; + if([nestedBrick isKindOfClass:[LoopBeginBrick class]] || [nestedBrick isKindOfClass:[IfThenLogicBeginBrick class]] || [nestedBrick isKindOfClass:[IfLogicBeginBrick class]] ) + { + NSArray* nestedLoopOrLogic = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:[NSIndexPath indexPathForItem:(i + 2) inSection:indexPath.section] Brick:nestedBrick nestedIndexOrZero:(int)ifLogicBeginIndex + 1 + i - nestedIndex]; + [returnValues addObjectsFromArray:nestedLoopOrLogic]; + i += nestedLoopOrLogic.count -1; + } + else if ([nestedBrick isKindOfClass:[IfLogicElseBrick class]] ) + { + if(nestedIndex == 0) + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:ifLogicBeginIndex + 1 + i]; + } + else + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:nestedIndex + 1 + i]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + i) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + } + else if ([nestedBrick isKindOfClass:[LoopEndBrick class]] || [nestedBrick isKindOfClass:[IfThenLogicEndBrick class]] || [nestedBrick isKindOfClass:[IfLogicEndBrick class]]) + { + NSError(@"Copying wrong Brick, Should not happen!!"); + } + else + { + if(nestedIndex == 0) + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:ifLogicBeginIndex + 1 + i]; + } + else + { + [brick.script addBrick:[nestedBrick mutableCopyWithContext:[CBMutableCopyContext new]] atIndex:nestedIndex + 1 + i]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + i) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + } + } + + if(nestedIndex == 0) + { + [brick.script addBrick:copiedIfLogicEndBrick atIndex:ifLogicBeginIndex + 1 + nestedBricks.count]; + } + else + { + [brick.script addBrick:copiedIfLogicEndBrick atIndex:nestedIndex + 1 + nestedBricks.count]; + } + loopIndexPath = [NSIndexPath indexPathForItem:(nestedIndex + 2 + nestedBricks.count) inSection:indexPath.section]; + [returnValues addObject:loopIndexPath]; + return returnValues; + } else { return @[]; } diff --git a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m index 8f310d8d25..20808408d9 100644 --- a/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m +++ b/src/Catty/ViewController/Continue&New/MaintainObject/MaintainScript/ScriptCollectionViewController.m @@ -863,7 +863,7 @@ -(void)animate:(NSIndexPath*)indexPath brickCell:(BrickCell*)brickCell #pragma mark - Copy Brick - (void)copyBrick:(Brick*)brick atIndexPath:(NSIndexPath*)indexPath { - NSArray* indexArray = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:indexPath andBrick:brick]; + NSArray* indexArray = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:indexPath Brick:brick nestedIndexOrZero:0]; [self.collectionView insertItemsAtIndexPaths:indexArray]; self.placeHolderView.hidden = YES; [self.object.scene.project saveToDiskWithNotification:YES]; diff --git a/src/CattyTests/Bricks/BrickInsertManager/BrickInsertManagerTests.m b/src/CattyTests/Bricks/BrickInsertManager/BrickInsertManagerTests.m index b194d36aaf..96c37f64da 100644 --- a/src/CattyTests/Bricks/BrickInsertManager/BrickInsertManagerTests.m +++ b/src/CattyTests/Bricks/BrickInsertManager/BrickInsertManagerTests.m @@ -157,7 +157,7 @@ - (void)testCopyIfThenLogicBeginBrick { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0]; - NSArray *copiedBricksIndexPaths = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:indexPath andBrick:ifThenLogicBeginBrick]; + NSArray *copiedBricksIndexPaths = [[BrickManager sharedBrickManager] scriptCollectionCopyBrickWithIndexPath:indexPath Brick:ifThenLogicBeginBrick nestedIndexOrZero:0]; XCTAssertEqual(2, [copiedBricksIndexPaths count]); XCTAssertEqual(indexPath.section, copiedBricksIndexPaths[0].section); diff --git a/src/CattyTests/Bricks/BrickManager/BrickCopyTests.swift b/src/CattyTests/Bricks/BrickManager/BrickCopyTests.swift new file mode 100644 index 0000000000..efb4e0f86d --- /dev/null +++ b/src/CattyTests/Bricks/BrickManager/BrickCopyTests.swift @@ -0,0 +1,229 @@ +/** + * Copyright (C) 2010-2021 The Catrobat Team + * (http://developer.catrobat.org/credits) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * (http://developer.catrobat.org/license_additional_term) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +import XCTest + +@testable import Pocket_Code + +final class BrickCopyTests: XCTestCase { + + var brick: SetTransparencyBrick! + var object: SpriteObject! + var script: StartScript! + + override func setUp() { + super.setUp() + object = SpriteObject() + let scene = Scene(name: "testScene") + object.scene = scene + + script = StartScript() + script.object = object + } + + func testLoopBrickCopy() { + let loopBeginBrick = LoopBeginBrick() + loopBeginBrick.script = self.script + + let hideBrick = HideBrick() + hideBrick.script = self.script + + let loopEndBrick = LoopEndBrick() + loopEndBrick.script = self.script + + loopEndBrick.loopBeginBrick = loopBeginBrick + loopBeginBrick.loopEndBrick = loopEndBrick + + self.script.brickList.add(loopBeginBrick) + self.script.brickList.add(hideBrick) + self.script.brickList.add(loopEndBrick) + + let amountBricks = self.script.brickList.count + + let indexPath = NSIndexPath.init() + let copiedBricksIndexPaths = BrickManager.shared()?.scriptCollectionCopyBrick(with: indexPath as IndexPath, brick: loopBeginBrick, nestedIndexOrZero: 0) + + let amountBricksCopied = self.script.brickList.count + + XCTAssertEqual(amountBricksCopied, amountBricks * 2) + XCTAssertEqual(amountBricks, copiedBricksIndexPaths?.count) + XCTAssertTrue((self.script.brickList.object(at: 0) as! Brick).isEqual(to: self.script.brickList.object(at: 0 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 1) as! Brick).isEqual(to: self.script.brickList.object(at: 1 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 2) as! Brick).isEqual(to: self.script.brickList.object(at: 2 + amountBricks) as? Brick)) + } + + func testIfElseBrickCopy() { + let ifLogicBeginBrick = IfLogicBeginBrick() + ifLogicBeginBrick.ifCondition = Formula(integer: 1) + ifLogicBeginBrick.script = self.script + + let hideBrick = HideBrick() + hideBrick.script = self.script + + let ifLogicElseBrick = IfLogicElseBrick() + ifLogicElseBrick.script = self.script + + let showBrick = ShowBrick() + showBrick.script = self.script + + let ifLogicEndBrick = IfLogicEndBrick() + ifLogicEndBrick.script = self.script + + ifLogicEndBrick.ifBeginBrick = ifLogicBeginBrick + ifLogicEndBrick.ifElseBrick = ifLogicElseBrick + ifLogicElseBrick.ifBeginBrick = ifLogicBeginBrick + ifLogicElseBrick.ifEndBrick = ifLogicEndBrick + ifLogicBeginBrick.ifElseBrick = ifLogicElseBrick + ifLogicBeginBrick.ifEndBrick = ifLogicEndBrick + + self.script.brickList.add(ifLogicBeginBrick) + self.script.brickList.add(hideBrick) + self.script.brickList.add(ifLogicElseBrick) + self.script.brickList.add(showBrick) + self.script.brickList.add(ifLogicEndBrick) + + let amountBricks = self.script.brickList.count + + let indexPath = NSIndexPath.init() + let copiedBricksIndexPaths = BrickManager.shared()?.scriptCollectionCopyBrick(with: indexPath as IndexPath, brick: ifLogicBeginBrick, nestedIndexOrZero: 0) + + let amountBricksCopied = self.script.brickList.count + + XCTAssertEqual(amountBricksCopied, amountBricks * 2) + XCTAssertEqual(amountBricks, copiedBricksIndexPaths?.count) + XCTAssertTrue((self.script.brickList.object(at: 0) as! Brick).isEqual(to: self.script.brickList.object(at: 0 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 1) as! Brick).isEqual(to: self.script.brickList.object(at: 1 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 2) as! Brick).isEqual(to: self.script.brickList.object(at: 2 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 3) as! Brick).isEqual(to: self.script.brickList.object(at: 3 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 4) as! Brick).isEqual(to: self.script.brickList.object(at: 4 + amountBricks) as? Brick)) + } + + func testIfThenBrickCopy() { + let ifThenLogicBeginBrick = IfThenLogicBeginBrick() + ifThenLogicBeginBrick.ifCondition = Formula(integer: 1) + ifThenLogicBeginBrick.script = self.script + + let hideBrick = HideBrick() + hideBrick.script = self.script + + let ifThenLogicEndBrick = IfThenLogicEndBrick() + ifThenLogicEndBrick.script = self.script + + ifThenLogicEndBrick.ifBeginBrick = ifThenLogicBeginBrick + ifThenLogicBeginBrick.ifEndBrick = ifThenLogicEndBrick + + self.script.brickList.add(ifThenLogicBeginBrick) + self.script.brickList.add(hideBrick) + self.script.brickList.add(ifThenLogicEndBrick) + + let amountBricks = self.script.brickList.count + + let indexPath = NSIndexPath.init() + let copiedBricksIndexPaths = BrickManager.shared()?.scriptCollectionCopyBrick(with: indexPath as IndexPath, brick: ifThenLogicBeginBrick, nestedIndexOrZero: 0) + + let amountBricksCopied = self.script.brickList.count + + XCTAssertEqual(amountBricksCopied, amountBricks * 2) + XCTAssertEqual(amountBricks, copiedBricksIndexPaths?.count) + + XCTAssertTrue((self.script.brickList.object(at: 0) as! Brick).isEqual(to: self.script.brickList.object(at: 0 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 1) as! Brick).isEqual(to: self.script.brickList.object(at: 1 + amountBricks) as? Brick)) + XCTAssertTrue((self.script.brickList.object(at: 2) as! Brick).isEqual(to: self.script.brickList.object(at: 2 + amountBricks) as? Brick)) + } + + func testAllNestedBricksCopy() { + let loopBeginBrick = LoopBeginBrick() + loopBeginBrick.script = self.script + + let hideBrick = HideBrick() + hideBrick.script = self.script + + let loopEndBrick = LoopEndBrick() + loopEndBrick.script = self.script + + loopEndBrick.loopBeginBrick = loopBeginBrick + loopBeginBrick.loopEndBrick = loopEndBrick + + let ifLogicBeginBrick = IfLogicBeginBrick() + ifLogicBeginBrick.ifCondition = Formula(integer: 1) + ifLogicBeginBrick.script = self.script + + let nextLookBrick = NextLookBrick() + nextLookBrick.script = self.script + + let ifLogicElseBrick = IfLogicElseBrick() + ifLogicElseBrick.script = self.script + + let showBrick = ShowBrick() + showBrick.script = self.script + + let ifLogicEndBrick = IfLogicEndBrick() + ifLogicEndBrick.script = self.script + + ifLogicEndBrick.ifBeginBrick = ifLogicBeginBrick + ifLogicEndBrick.ifElseBrick = ifLogicElseBrick + ifLogicElseBrick.ifBeginBrick = ifLogicBeginBrick + ifLogicElseBrick.ifEndBrick = ifLogicEndBrick + ifLogicBeginBrick.ifElseBrick = ifLogicElseBrick + ifLogicBeginBrick.ifEndBrick = ifLogicEndBrick + + let ifThenLogicBeginBrick = IfThenLogicBeginBrick() + ifThenLogicBeginBrick.ifCondition = Formula(integer: 1) + ifThenLogicBeginBrick.script = self.script + + let previousLookBrick = PreviousLookBrick() + previousLookBrick.script = self.script + + let ifThenLogicEndBrick = IfThenLogicEndBrick() + ifThenLogicEndBrick.script = self.script + + ifThenLogicEndBrick.ifBeginBrick = ifThenLogicBeginBrick + ifThenLogicBeginBrick.ifEndBrick = ifThenLogicEndBrick + + self.script.brickList.add(loopBeginBrick) + self.script.brickList.add(hideBrick) + self.script.brickList.add(ifLogicBeginBrick) + self.script.brickList.add(nextLookBrick) + self.script.brickList.add(ifLogicElseBrick) + self.script.brickList.add(ifThenLogicBeginBrick) + self.script.brickList.add(previousLookBrick) + self.script.brickList.add(ifThenLogicEndBrick) + self.script.brickList.add(showBrick) + self.script.brickList.add(ifLogicEndBrick) + self.script.brickList.add(loopEndBrick) + + let amountBricks = self.script.brickList.count + + let indexPath = NSIndexPath.init() + let copiedBricksIndexPaths = BrickManager.shared()?.scriptCollectionCopyBrick(with: indexPath as IndexPath, brick: loopBeginBrick, nestedIndexOrZero: 0) + + let amountBricksCopied = self.script.brickList.count + + XCTAssertEqual(amountBricksCopied, amountBricks * 2) + XCTAssertEqual(amountBricks, copiedBricksIndexPaths?.count) + + for i in 0...amountBricks - 1 { + XCTAssertTrue((self.script.brickList.object(at: i) as! Brick).isEqual(to: self.script.brickList.object(at: i + amountBricks) as? Brick)) + } + } + +} diff --git a/src/CattyUITests/ObjectTVCTests.swift b/src/CattyUITests/ObjectTVCTests.swift index ff8e5926cb..2b86a7b47a 100644 --- a/src/CattyUITests/ObjectTVCTests.swift +++ b/src/CattyUITests/ObjectTVCTests.swift @@ -89,7 +89,7 @@ class ObjectTVCTests: XCTestCase { //Check if copied successfull app.navigationBars[kLocalizedScripts].buttons["Mole 1"].tap() app.tables.staticTexts[kLocalizedScripts].tap() - XCTAssert(app.collectionViews.cells.element(boundBy: 3).staticTexts[kLocalizedEndOfLoop].exists) + XCTAssert(app.collectionViews.cells.element(boundBy: 12).staticTexts[kLocalizedEndOfLoop].exists) } func testScriptsCanDeleteWhenProjectStartedBrick() {