From 982b70d7fbc9ae664dc356614e99cf0d5870a0fd Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Sun, 18 May 2014 01:06:49 +0200 Subject: [PATCH] Added Change Notifications to MPExpression, MPMutableExpression and MPFunction Removed -beginEditing and -endEditing Optimized -fixSymbols Updated Project File --- MathPad.xcodeproj/project.pbxproj | 6 -- MathPad/MPExpression.h | 11 ++- MathPad/MPExpression.m | 144 +++++++++++++++++++----------- MathPad/MPFunction.h | 8 +- MathPad/MPFunction.m | 15 +++- 5 files changed, 119 insertions(+), 65 deletions(-) diff --git a/MathPad.xcodeproj/project.pbxproj b/MathPad.xcodeproj/project.pbxproj index e331591..16ccf9f 100644 --- a/MathPad.xcodeproj/project.pbxproj +++ b/MathPad.xcodeproj/project.pbxproj @@ -26,7 +26,6 @@ 3BBBA35E1903FD3600824E74 /* MPRangePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B87E35C1900933200259938 /* MPRangePath.m */; }; 3BBBA35F1903FD3600824E74 /* MPRangePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B87E35C1900933200259938 /* MPRangePath.m */; }; 3BBBA3951905704200824E74 /* MPRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBBA3941905704200824E74 /* MPRangeTests.m */; }; - 3BEB0F8119074815005699AB /* MPDisplayExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BEB0F8019074815005699AB /* MPDisplayExtension.m */; }; 3BF9976F18DE623E009CF6C4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF9976E18DE623E009CF6C4 /* Cocoa.framework */; }; 3BF9977918DE623E009CF6C4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3BF9977718DE623E009CF6C4 /* InfoPlist.strings */; }; 3BF9977B18DE623E009CF6C4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF9977A18DE623E009CF6C4 /* main.m */; }; @@ -81,8 +80,6 @@ 3BBBA35C1903F8A700824E74 /* NSObject+MPStringTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MPStringTest.m"; sourceTree = ""; }; 3BBBA38419047FC900824E74 /* MPView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPView.h; sourceTree = ""; }; 3BBBA3941905704200824E74 /* MPRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRangeTests.m; sourceTree = ""; }; - 3BEB0F7F19074815005699AB /* MPDisplayExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPDisplayExtension.h; sourceTree = ""; }; - 3BEB0F8019074815005699AB /* MPDisplayExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPDisplayExtension.m; sourceTree = ""; }; 3BF9976B18DE623E009CF6C4 /* MathPad.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MathPad.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3BF9976E18DE623E009CF6C4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 3BF9977118DE623E009CF6C4 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -190,8 +187,6 @@ 3BB09ED419071A140080A5ED /* Categories */ = { isa = PBXGroup; children = ( - 3BEB0F7F19074815005699AB /* MPDisplayExtension.h */, - 3BEB0F8019074815005699AB /* MPDisplayExtension.m */, ); name = Categories; sourceTree = ""; @@ -415,7 +410,6 @@ files = ( 3BB09EE1190736160080A5ED /* MPSumFunctionLayout.m in Sources */, 3B87E3561900856F00259938 /* MPExpressionView.m in Sources */, - 3BEB0F8119074815005699AB /* MPDisplayExtension.m in Sources */, 3BFCFF491905AAF30001FE33 /* NSTextStorage+MPSetContents.m in Sources */, 3BB09EC91906FD830080A5ED /* MPSumFunction.m in Sources */, 3BB09EB21905DE500080A5ED /* MPExpressionStorage.m in Sources */, diff --git a/MathPad/MPExpression.h b/MathPad/MPExpression.h index 1dd29cc..7134cb6 100644 --- a/MathPad/MPExpression.h +++ b/MathPad/MPExpression.h @@ -6,7 +6,7 @@ // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // -@class MPExpression, MPFunction; +@class MPExpression, MPFunction, MPRangePath; extern NSString *MPAdditionOperator; extern NSString *MPSubtractionOperator; @@ -86,14 +86,17 @@ extern NSString *MPDivisionOperator; @end +@interface MPExpression (MPChangeNotificationExtension) + +- (void)symbolsChangedInRangePath:(MPRangePath *)rangePath replacementLength:(NSUInteger)length; + +@end + @interface MPMutableExpression : MPExpression - (void)replaceSymbolsInRange:(NSRange)range withSymbols:(NSArray *)symbols; -- (void)beginEditing; -- (void)endEditing; - @end @interface MPMutableExpression (MPMutableExpressionExtensionMethods) diff --git a/MathPad/MPExpression.m b/MathPad/MPExpression.m index 5d31f1e..9045d25 100644 --- a/MathPad/MPExpression.m +++ b/MathPad/MPExpression.m @@ -9,9 +9,10 @@ #import "MPExpression.h" #import "MPFunction.h" #import "MPException.h" +#import "MPRangePath.h" #import "NSObject+MPStringTest.h" -#import "NSIndexPath+MPRemoveFirstIndex.h" +#import "NSIndexPath+MPReverseIndexPath.h" NSString *MPAdditionOperator = @"+"; NSString *MPSubtractionOperator = @"-"; @@ -22,7 +23,6 @@ NSString *MPDivisionOperator = @"/"; - (NSInteger)lengthOfSymbol:(id)symbol; - (void)validateSymbols:(NSArray *)symbols; -- (NSArray *)fixedSymbols:(NSArray *)symbols; - (void)getSplitOffset:(out NSUInteger *)offset inSymbolAtIndex:(out NSUInteger *)symbolIndex forSplitLocation:(NSUInteger)loc; @@ -53,7 +53,25 @@ NSString *MPDivisionOperator = @"/"; - (void)fixSymbols { - _symbols = [self fixedSymbols:_symbols]; + NSMutableArray *mutableSymbols = [_symbols mutableCopy]; + for (NSInteger index = 0; index < mutableSymbols.count; index++) { + id next = index+1 < mutableSymbols.count ? mutableSymbols[index+1] : nil; + id current = mutableSymbols[index]; + if ([current isString]) { + if ([current length] == 0) { + [mutableSymbols removeObjectAtIndex:index]; + index--; + } else if ([next isString]) { + NSString *new = [NSString stringWithFormat:@"%@%@", current, next]; + [mutableSymbols replaceObjectAtIndex:index withObject:new]; + [mutableSymbols removeObjectAtIndex:index+1]; + index--; + } + } else { + [(MPFunction *)current setParent:self]; + } + } + _symbols = [mutableSymbols copy]; } #pragma mark Primitive Methods @@ -127,29 +145,6 @@ NSString *MPDivisionOperator = @"/"; } } -- (NSArray *)fixedSymbols:(NSArray *)symbols -{ - NSMutableArray *mutableSymbols = [symbols mutableCopy]; - for (NSInteger index = 0; index < mutableSymbols.count; index++) { - id next = index+1 < mutableSymbols.count ? mutableSymbols[index+1] : nil; - id current = mutableSymbols[index]; - if ([current isString]) { - if ([current length] == 0) { - [mutableSymbols removeObjectAtIndex:index]; - index--; - } else if ([next isString]) { - NSString *new = [NSString stringWithFormat:@"%@%@", current, next]; - [mutableSymbols replaceObjectAtIndex:index withObject:new]; - [mutableSymbols removeObjectAtIndex:index+1]; - index--; - } - } else { - [(MPFunction *)current setParent:self]; - } - } - return [mutableSymbols copy]; -} - - (void)getSplitOffset:(out NSUInteger *)offset inSymbolAtIndex:(out NSUInteger *)symbolIndex forSplitLocation:(NSUInteger)loc @@ -420,9 +415,24 @@ NSString *MPDivisionOperator = @"/"; @end +@implementation MPExpression (MPChangeNotificationExtension) + +- (void)symbolsChangedInRangePath:(MPRangePath *)rangePath replacementLength:(NSUInteger)length +{ + if (!self.parent) { + return; + } + NSUInteger selfIndex = [self.parent indexOfChild:self]; + NSIndexPath *newLocation = [rangePath.location indexPathByPrecedingIndex:selfIndex]; + MPRangePath *newPath = [[MPRangePath alloc] initWithLocation:newLocation length:rangePath.length]; + [self.parent symbolsChangedInRangePath:newPath replacementLength:length]; +} + +@end + @implementation MPMutableExpression { - @protected - NSInteger _editCount; + NSRange editedRange; + NSRange replacementRange; } - (instancetype)initWithSymbols:(NSArray *)symbols @@ -430,6 +440,8 @@ NSString *MPDivisionOperator = @"/"; [self validateSymbols:symbols]; self = [super initWithSymbols:nil]; if (self) { + editedRange = NSMakeRange(0, 0); + replacementRange = NSMakeRange(0, 0); _symbols = [[NSMutableArray alloc] initWithArray:symbols copyItems:YES]; [self fixSymbols]; @@ -439,7 +451,38 @@ NSString *MPDivisionOperator = @"/"; - (void)fixSymbols { - _symbols = [[self fixedSymbols:_symbols] mutableCopy]; + NSMutableArray *mutableSymbols = (NSMutableArray *)_symbols; + for (NSInteger index = 0; index < mutableSymbols.count; index++) { + id next = index+1 < mutableSymbols.count ? mutableSymbols[index+1] : nil; + id current = mutableSymbols[index]; + if ([current isString]) { + if ([current length] == 0) { + [mutableSymbols removeObjectAtIndex:index]; + if (index < replacementRange.location) { + replacementRange.location--; + } else if (index < NSMaxRange(replacementRange)-1) { + replacementRange.length--; + } else if (index == NSMaxRange(replacementRange)) { + editedRange.length++; + } + index--; + } else if ([next isString]) { + NSString *new = [NSString stringWithFormat:@"%@%@", current, next]; + [mutableSymbols replaceObjectAtIndex:index withObject:new]; + [mutableSymbols removeObjectAtIndex:index+1]; + if (index < replacementRange.location) { + replacementRange.location--; + } else if (index < NSMaxRange(replacementRange)-1) { + replacementRange.length--; + } else if (index == NSMaxRange(replacementRange)-1) { + editedRange.length++; + } + index--; + } + } else { + [(MPFunction *)current setParent:self]; + } + } } - (NSArray *)symbols @@ -460,22 +503,27 @@ NSString *MPDivisionOperator = @"/"; // Locate the position, split the symbols NSUInteger startIndex; + BOOL didSplitStart = NO; if ([self numberOfSymbols] == 0) { startIndex = 0; } else { [self splitSymbolsAtLocation:range.location - insertionIndex:&startIndex]; + insertionIndex:&startIndex + didSplit:&didSplitStart]; } // Perform the deletion + NSUInteger endIndex; + BOOL didSplitEnd = NO; + [self splitSymbolsAtLocation:NSMaxRange(range) + insertionIndex:&endIndex + didSplit:&didSplitEnd]; if (range.length > 0) { - NSUInteger endIndex; - [self splitSymbolsAtLocation:NSMaxRange(range) - insertionIndex:&endIndex]; NSMutableIndexSet *indexes = [[NSMutableIndexSet alloc] init]; for (NSUInteger index = startIndex; index < endIndex; index++) { [indexes addIndex:index]; } + // TODO: Replace with removeObjectsInRange: [(NSMutableArray *)_symbols removeObjectsAtIndexes:indexes]; } @@ -486,15 +534,20 @@ NSString *MPDivisionOperator = @"/"; withObjectsFromArray:newSymbols]; } - // Revalidate structure and invalidate length - if (_editCount == 0) { - [self fixSymbols]; - } + // Invalidate length and revalidate structure _length = 0; + NSUInteger editingStart = startIndex - (didSplitStart?1:0); + NSUInteger editingLength = endIndex - startIndex + (didSplitStart?1:0) + (didSplitEnd?1:0); + editedRange = NSMakeRange(editingStart, editingLength); + replacementRange = NSMakeRange(startIndex, symbols.count); + [self fixSymbols]; + MPRangePath *changePath = [[MPRangePath alloc] initWithRange:editedRange]; + [self symbolsChangedInRangePath:changePath replacementLength:replacementRange.length]; } - (void)splitSymbolsAtLocation:(NSUInteger)loc insertionIndex:(out NSUInteger *)insertionIndex + didSplit:(out BOOL *)flag; { NSUInteger splitSymbolIndex; NSUInteger splitOffset; @@ -516,25 +569,10 @@ NSString *MPDivisionOperator = @"/"; [(NSMutableArray *)_symbols insertObject:rightPart atIndex:splitSymbolIndex]; } + *flag = splitOffset != 0; *insertionIndex = splitSymbolIndex; } -- (void)beginEditing -{ - _editCount++; -} - -- (void)endEditing -{ - if (_editCount == 0) { - return; - } - _editCount--; - if (_editCount == 0) { - [self fixSymbols]; - } -} - @end @implementation MPMutableExpression (MPMutableExpressionExtensionMethods) diff --git a/MathPad/MPFunction.h b/MathPad/MPFunction.h index 35b3a0c..53864e8 100644 --- a/MathPad/MPFunction.h +++ b/MathPad/MPFunction.h @@ -6,7 +6,7 @@ // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // -@class MPFunction, MPExpression; +@class MPFunction, MPExpression, MPRangePath; @interface MPFunction : NSObject @@ -55,3 +55,9 @@ - (NSUInteger)hash; @end + +@interface MPFunction (MPDisplayExtension) + +- (void)symbolsChangedInRangePath:(MPRangePath *)rangePath replacementLength:(NSUInteger)length; + +@end diff --git a/MathPad/MPFunction.m b/MathPad/MPFunction.m index 3d9fa17..55d8afb 100644 --- a/MathPad/MPFunction.m +++ b/MathPad/MPFunction.m @@ -8,8 +8,9 @@ #import "MPFunction.h" #import "MPExpression.h" +#import "MPRangePath.h" -#import "NSIndexPath+MPRemoveFirstIndex.h" +#import "NSIndexPath+MPReverseIndexPath.h" @implementation MPFunction @@ -156,4 +157,16 @@ return 0; } +@end + +@implementation MPFunction (MPDisplayExtension) + +- (void)symbolsChangedInRangePath:(MPRangePath *)rangePath replacementLength:(NSUInteger)length +{ + NSUInteger index = [self.parent indexOfSymbol:self]; + NSIndexPath *newLocation = [rangePath.location indexPathByPrecedingIndex:index]; + MPRangePath *newRangePath = [[MPRangePath alloc] initWithLocation:newLocation length:rangePath.length]; + [self.parent symbolsChangedInRangePath:newRangePath replacementLength:length]; +} + @end \ No newline at end of file