diff --git a/MathPad/MPExpressionView.m b/MathPad/MPExpressionView.m index 0624075..b15f4fc 100644 --- a/MathPad/MPExpressionView.m +++ b/MathPad/MPExpressionView.m @@ -6,8 +6,6 @@ // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // -#warning X-Origin is not working yet - #import "MPExpressionView.h" #import "MPExpressionStorage.h" #import "MPExpressionLayout.h" @@ -18,6 +16,8 @@ #import "MPSumFunction.h" + + @interface MPExpressionView () @property (nonatomic, weak) NSButton *functionsButton; @@ -28,23 +28,37 @@ @property (nonatomic, getter = isSelectionModifyingStart) BOOL selectionModifyingStart; +@property (nonatomic, strong) NSIndexPath *mouseAnchor; + @end + + @interface MPExpressionView (MPDrawing) - (NSPoint)expressionOrigin; @end + + @interface MPExpressionView (MPSelection) - (void)restartCaretTimer; - (void)updateCaret:(NSTimer *)timer; - (NSRect)selectionRect; -- (void)selectRangePathWithLocation:(NSIndexPath *)location length:(NSUInteger)length; +- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selection + selectWords:(BOOL)flag; +- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selection + selectWords:(BOOL)flag; + +- (MPRangePath *)rangePathEnclosingAnchor:(NSIndexPath *)anchor + newSelection:(NSIndexPath *)newSelection; @end + + @implementation MPExpressionView (MPDrawing) - (NSPoint)expressionOrigin @@ -56,6 +70,8 @@ @end + + @implementation MPExpressionView (MPSelection) - (void)restartCaretTimer @@ -85,22 +101,64 @@ return selectionRect; } -- (void)selectRangePathWithLocation:(NSIndexPath *)location length:(NSUInteger)length +- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selection + selectWords:(BOOL)flag { - MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[location indexPathByRemovingLastIndex]]; - NSUInteger locationIndex = location.lastIndex; - if (locationIndex > targetExpression.length) { - locationIndex = targetExpression.length; + MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[selection indexPathByRemovingLastIndex]]; + NSUInteger locationInTarget = selection.lastIndex; + NSUInteger locationInElement; + NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget + offset:&locationInElement]; + id targetElement; + if (targetElementIndex < targetExpression.numberOfElements) { + targetElement = [targetExpression elementAtIndex:targetElementIndex]; } - NSUInteger lastSelectedIndex = location.lastIndex + length; - if (lastSelectedIndex > targetExpression.length) { - lastSelectedIndex = targetExpression.length; + if (locationInElement == 0 && !flag) { + NSLog(@"Move to next"); + // Move to next element + } else if (locationInTarget < targetExpression.length) { + if (flag) { + locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex+1]; + } else { + locationInTarget++; + } } - self.selection = MPMakeRangePath([location indexPathByReplacingLastIndexWithIndex:locationIndex],lastSelectedIndex - locationIndex); + return [selection indexPathByReplacingLastIndexWithIndex:locationInTarget]; +} + +- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selection + selectWords:(BOOL)flag +{ + MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[selection indexPathByRemovingLastIndex]]; + NSUInteger locationInTarget = selection.lastIndex; + NSUInteger locationInElement; + NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget + offset:&locationInElement]; + if (locationInElement == 0 && !flag) { + // Move to previous element + } else if (locationInTarget > 0) { + if (flag) { + if (locationInElement == 0) { + targetElementIndex--; + } + locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex]; + } else { + locationInTarget--; + } + } + return [selection indexPathByReplacingLastIndexWithIndex:locationInTarget]; +} + +- (MPRangePath *)rangePathEnclosingAnchor:(NSIndexPath *)anchor + newSelection:(NSIndexPath *)newSelection +{ + } @end + + @implementation MPExpressionView #pragma mark Creation Methods @@ -125,7 +183,7 @@ - (void)initializeExpressionView { // Setup the Expression Storage - MPExpressionStorage *expressionStorage = [[MPExpressionStorage alloc] initWithElements:@[@"12345", [[MPSumFunction alloc] init], [[MPSumFunction alloc] init]]]; + MPExpressionStorage *expressionStorage = [[MPExpressionStorage alloc] initWithElements:@[@"12345", [[MPSumFunction alloc] init]]]; expressionStorage.expressionView = self; _expressionStorage = expressionStorage; @@ -207,7 +265,7 @@ { NSString *characters = theEvent.characters; NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; - [allowedCharacters addCharactersInString:@"+-*/= "]; + [allowedCharacters addCharactersInString:@"+-*= "]; if (characters.length == 1 && [characters stringByTrimmingCharactersInSet:allowedCharacters].length == 0) { MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]]; [targetExpression replaceSymbolsInRange:self.selection.rangeAtLastIndex withElements:@[characters]]; @@ -222,9 +280,9 @@ if (self.selection.length > 0) { self.selection = MPMakeRangePath(self.selection.maxRangePath, 0); } else { - NSIndexPath *newSelectionLocation = [self.selection.location indexPathByIncrementingLastIndex]; - [self selectRangePathWithLocation:newSelectionLocation - length:0]; + NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:self.selection.location + selectWords:NO]; + self.selection = MPMakeRangePath(newSelectionLocation, 0); } } @@ -232,48 +290,27 @@ { if (self.selection.length > 0) { self.selection = MPMakeRangePath(self.selection.location, 0); - [self selectRangePathWithLocation:self.selection.location length:0]; } else { - NSUInteger selectionIndex = self.selection.location.lastIndex; - if (selectionIndex > 0) { - --selectionIndex; - } - NSIndexPath *newSelectionLocation = [self.selection.location indexPathByReplacingLastIndexWithIndex:selectionIndex]; - [self selectRangePathWithLocation:newSelectionLocation - length:0]; + NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:self.selection.location + selectWords:NO]; + self.selection = MPMakeRangePath(newSelectionLocation, 0); } } - (void)moveWordRight:(id)sender { - NSIndexPath *location; - if (self.selection.length > 0) { - location = self.selection.maxRangePath; - } else { - location = self.selection.location; - } - MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[location indexPathByRemovingLastIndex]]; - NSUInteger locationInTarget = NSMaxRange(self.selection.rangeAtLastIndex); - NSUInteger offset; - NSUInteger elementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget - offset:&offset]; - NSUInteger newLocation = locationInTarget + [targetExpression elementAtIndex:elementIndex].length - offset; - [self selectRangePathWithLocation:[location indexPathByReplacingLastIndexWithIndex:newLocation] - length:0]; + NSIndexPath *location = self.selection.maxRangePath; + NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:location + selectWords:YES]; + self.selection = MPMakeRangePath(newSelectionLocation, 0); } - (void)moveWordLeft:(id)sender { - MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]]; - NSUInteger offset; - NSUInteger elementIndex = [targetExpression indexOfElementAtSymbolLocation:self.selection.location.lastIndex offset:&offset]; - NSUInteger newLocation = self.selection.location.lastIndex; - if (offset > 0) { - newLocation -= newLocation - offset > 0 ? offset : newLocation; - } else if (newLocation > 0) { - newLocation -= [targetExpression elementAtIndex:elementIndex-1].length; - } - self.selection = MPMakeRangePath([self.selection.location indexPathByReplacingLastIndexWithIndex:newLocation], 0); + NSIndexPath *location = self.selection.location; + NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:location + selectWords:YES]; + self.selection = MPMakeRangePath(newSelectionLocation, 0); } - (void)moveToBeginningOfLine:(id)sender @@ -292,17 +329,16 @@ if (self.selection.length == 0) { self.selectionModifyingStart = YES; } - NSUInteger start = self.selection.location.lastIndex; - NSUInteger length = self.selection.length; + NSIndexPath *location = self.selection.location; + NSIndexPath *maxLocation = self.selection.maxRangePath; if (self.selectionModifyingStart) { - if (start > 0) { - --start; - ++length; - } + location = [self selectionToTheLeftOf:location + selectWords:NO]; } else { - --length; + maxLocation = [self selectionToTheLeftOf:maxLocation + selectWords:NO]; } - self.selection = MPMakeRangePath([self.selection.location indexPathByReplacingLastIndexWithIndex:start], length); + self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); } - (void)moveRightAndModifySelection:(id)sender @@ -310,26 +346,57 @@ if (self.selection.length == 0) { self.selectionModifyingStart = NO; } - NSUInteger start = self.selection.location.lastIndex; - NSUInteger length = self.selection.length; + NSIndexPath *location = self.selection.location; + NSIndexPath *maxLocation = self.selection.maxRangePath; + if (self.selectionModifyingStart) { - ++start; - --length; + location = [self selectionToTheRightOf:location + selectWords:NO]; } else { - ++length; + maxLocation = [self selectionToTheRightOf:maxLocation + selectWords:NO]; } - [self selectRangePathWithLocation:[self.selection.location indexPathByReplacingLastIndexWithIndex:start] - length:length]; + self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); } - (void)moveWordRightAndModifySelection:(id)sender { -#warning Unimplemented Method + if (self.selection.length == 0) { + self.selectionModifyingStart = NO; + } + NSIndexPath *location = self.selection.location; + NSIndexPath *maxLocation = self.selection.maxRangePath; + if (self.selectionModifyingStart) { + location = [self selectionToTheRightOf:location + selectWords:YES]; + if (location.lastIndex > maxLocation.lastIndex) { + location = [location indexPathByReplacingLastIndexWithIndex:maxLocation.lastIndex]; + } + } else { + maxLocation = [self selectionToTheRightOf:maxLocation + selectWords:YES]; + } + self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); } - (void)moveWordLeftAndModifySelection:(id)sender { -#warning Unimplemented Method + if (self.selection.length == 0) { + self.selectionModifyingStart = YES; + } + NSIndexPath *location = self.selection.location; + NSIndexPath *maxLocation = self.selection.maxRangePath; + if (self.selectionModifyingStart) { + location = [self selectionToTheLeftOf:location + selectWords:YES]; + } else { + maxLocation = [self selectionToTheLeftOf:maxLocation + selectWords:YES]; + if (maxLocation.lastIndex < location.lastIndex) { + maxLocation = [maxLocation indexPathByReplacingLastIndexWithIndex:location.lastIndex]; + } + } + self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); } - (void)selectAll:(id)sender @@ -359,9 +426,23 @@ pointInView.x -= expressionOrigin.x; pointInView.y -= expressionOrigin.y; NSIndexPath *selectionPath = [self.expressionStorage.rootLayout indexPathForMousePoint:pointInView]; + self.mouseAnchor = selectionPath; self.selection = MPMakeRangePath(selectionPath, 0); } +- (void)mouseDragged:(NSEvent *)theEvent +{ + NSPoint pointInView = [self convertPoint:theEvent.locationInWindow + fromView:nil]; + NSPoint expressionOrigin = self.expressionOrigin; + pointInView.x -= expressionOrigin.x; + pointInView.y -= expressionOrigin.y; + NSIndexPath *mouseSelectionPath = [self.expressionStorage.rootLayout indexPathForMousePoint:pointInView]; + + self.selection = [self rangePathEnclosingAnchor:self.mouseAnchor + newSelection:mouseSelectionPath]; +} + #pragma mark Drawing Methods - (void)drawRect:(NSRect)dirtyRect {