Archived
1

Corrected errors when selecting expressions

This commit is contained in:
Kim Wittenburg
2014-09-08 22:43:20 +02:00
parent 4a3ff8606b
commit 91320385f0
3 changed files with 181 additions and 31 deletions

View File

@@ -9,6 +9,7 @@
#import "MPExpressionView.h" #import "MPExpressionView.h"
#import "MPExpressionStorage.h" #import "MPExpressionStorage.h"
#import "MPExpressionLayout.h" #import "MPExpressionLayout.h"
#import "MPFunctionLayout.h"
#import "MPRangePath.h" #import "MPRangePath.h"
@@ -48,13 +49,15 @@
- (NSRect)selectionRect; - (NSRect)selectionRect;
- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selection - (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selectionPath
selectWords:(BOOL)flag; byExtendingSelection:(BOOL)extendingSelection
- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selection selectWords:(BOOL)selectWords;
selectWords:(BOOL)flag; - (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selectionPath
byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords;
- (MPRangePath *)rangePathEnclosingAnchor:(NSIndexPath *)anchor - (MPRangePath *)rangePathEnclosingAnchorPath:(NSIndexPath *)anchor
newSelection:(NSIndexPath *)newSelection; newSelectionPath:(NSIndexPath *)newSelection;
@end @end
@@ -101,43 +104,120 @@
return selectionRect; return selectionRect;
} }
- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selection - (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selectionPath
selectWords:(BOOL)flag byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords
{ {
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[selection indexPathByRemovingLastIndex]]; NSIndexPath *targetExpressionPath = [selectionPath indexPathByRemovingLastIndex];
NSUInteger locationInTarget = selection.lastIndex; MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
NSUInteger locationInTarget = selectionPath.lastIndex;
NSUInteger locationInElement; NSUInteger locationInElement;
NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget
offset:&locationInElement]; offset:&locationInElement];
id<MPExpressionElement> targetElement; id<MPExpressionElement> targetElement;
// There is only a target element if the selection is not the last location in an expression
if (targetElementIndex < targetExpression.numberOfElements) { if (targetElementIndex < targetExpression.numberOfElements) {
targetElement = [targetExpression elementAtIndex:targetElementIndex]; targetElement = [targetExpression elementAtIndex:targetElementIndex];
} }
if (locationInElement == 0 && !flag) {
NSLog(@"Move to next"); if (!selectWords && !extendingSelection && (locationInElement == 0 || locationInTarget == targetExpression.length)) {
// Move to next element // First or last index in an element or expression
// Last element in the expression
if (locationInTarget == targetExpression.length) {
// The selection is inside a function and should proceed
if (selectionPath.length > 1) {
NSIndexPath *functionPath = [[selectionPath indexPathByRemovingLastIndex] indexPathByRemovingLastIndex];
MPFunctionLayout *functionLayout = (MPFunctionLayout *)[self.expressionStorage.rootLayout childLayoutAtIndexPath:functionPath];
NSUInteger currentChildIndex = [selectionPath indexPathByRemovingLastIndex].lastIndex;
NSUInteger newChildIndex = [functionLayout indexOfChildAfterChildAtIndex:currentChildIndex];
// The function is to be exited
if (newChildIndex == NSNotFound) {
targetExpression = [self.expressionStorage elementAtIndexPath:[functionPath indexPathByRemovingLastIndex]];
NSUInteger functionLocationInExpression = [targetExpression locationOfElementAtIndex:functionPath.lastIndex];
return [functionPath indexPathByReplacingLastIndexWithIndex:functionLocationInExpression+1];
} else {
return [[targetExpressionPath indexPathByReplacingLastIndexWithIndex:newChildIndex] indexPathByAddingIndex:0];
}
} // else the selection does not change
// First Element
} else {
if ([targetElement isString]) {
locationInTarget++;
} else {
NSIndexPath *targetFunctionPath = [selectionPath indexPathByReplacingLastIndexWithIndex:targetElementIndex];
MPFunctionLayout *functionLayout = (MPFunctionLayout *)[self.expressionStorage.rootLayout childLayoutAtIndexPath:targetFunctionPath];
NSUInteger leadingChildIndex = [functionLayout indexOfLeadingChild];
return [[targetFunctionPath indexPathByAddingIndex:leadingChildIndex] indexPathByAddingIndex:0];
}
}
} else if (locationInTarget < targetExpression.length) { } else if (locationInTarget < targetExpression.length) {
if (flag) { if (selectWords) {
locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex+1]; locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex+1];
} else { } else {
locationInTarget++; locationInTarget++;
} }
} }
return [selection indexPathByReplacingLastIndexWithIndex:locationInTarget]; return [selectionPath indexPathByReplacingLastIndexWithIndex:locationInTarget];
} }
- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selection - (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selectionPath
selectWords:(BOOL)flag byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords
{ {
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[selection indexPathByRemovingLastIndex]]; NSIndexPath *targetExpressionPath = [selectionPath indexPathByRemovingLastIndex];
NSUInteger locationInTarget = selection.lastIndex; MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
NSUInteger locationInTarget = selectionPath.lastIndex;
NSUInteger locationInElement; NSUInteger locationInElement;
NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget
offset:&locationInElement]; offset:&locationInElement];
if (locationInElement == 0 && !flag) {
// Move to previous element NSUInteger previousElementIndex = targetElementIndex - (locationInElement == 0 ? 1 : 0);
id<MPExpressionElement> previousElement;
if (locationInTarget > 0) {
previousElement = [targetExpression elementAtIndex:previousElementIndex];
}
if (!selectWords && !extendingSelection && locationInElement == 0) {
// First element in expression
if (locationInTarget == 0) {
if (selectionPath.length > 1) {
NSIndexPath *functionPath = [[selectionPath indexPathByRemovingLastIndex] indexPathByRemovingLastIndex];
MPFunctionLayout *functionLayout = (MPFunctionLayout *)[self.expressionStorage.rootLayout childLayoutAtIndexPath:functionPath];
NSUInteger currentChildIndex = [selectionPath indexPathByRemovingLastIndex].lastIndex;
NSUInteger newChildIndex = [functionLayout indexOfChildBeforeChildAtIndex:currentChildIndex];
// The function is to be exited
if (newChildIndex == NSNotFound) {
targetExpression = [self.expressionStorage elementAtIndexPath:[functionPath indexPathByRemovingLastIndex]];
NSUInteger functionLocationInExpression = [targetExpression locationOfElementAtIndex:functionPath.lastIndex];
return [functionPath indexPathByReplacingLastIndexWithIndex:functionLocationInExpression];
} else {
targetExpressionPath = [targetExpressionPath indexPathByReplacingLastIndexWithIndex:newChildIndex];
targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
return [targetExpressionPath indexPathByAddingIndex:targetExpression.length];
}
} // else the selection does not change
// Just
} else {
if ([previousElement isString]) {
locationInTarget--;
} else {
NSIndexPath *targetFunctionPath = [selectionPath indexPathByReplacingLastIndexWithIndex:previousElementIndex];
MPFunctionLayout *functionLayout = (MPFunctionLayout *)[self.expressionStorage.rootLayout childLayoutAtIndexPath:targetFunctionPath];
NSUInteger trailingChildIndex = [functionLayout indexOfTrailingChild];
targetExpressionPath = [targetFunctionPath indexPathByAddingIndex:trailingChildIndex];
targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
return [targetExpressionPath indexPathByAddingIndex:targetExpression.length];
}
}
} else if (locationInTarget > 0) { } else if (locationInTarget > 0) {
if (flag) { if (selectWords) {
if (locationInElement == 0) { if (locationInElement == 0) {
targetElementIndex--; targetElementIndex--;
} }
@@ -146,13 +226,53 @@
locationInTarget--; locationInTarget--;
} }
} }
return [selection indexPathByReplacingLastIndexWithIndex:locationInTarget]; return [selectionPath indexPathByReplacingLastIndexWithIndex:locationInTarget];
} }
- (MPRangePath *)rangePathEnclosingAnchor:(NSIndexPath *)anchor - (MPRangePath *)rangePathEnclosingAnchorPath:(NSIndexPath *)anchorPath
newSelection:(NSIndexPath *)newSelection newSelectionPath:(NSIndexPath *)newSelectionPath
{ {
if ([anchorPath isEqual:newSelectionPath]) {
return MPMakeRangePath(anchorPath, 0);
}
NSIndexPath *commonPath = [anchorPath commonIndexPathWith:newSelectionPath];
if (commonPath.length == anchorPath.length-1 && commonPath.length == newSelectionPath.length-1) {
// The two paths point to different locations in the same expression
NSUInteger anchorIndex = [anchorPath indexAtPosition:commonPath.length];
NSUInteger newIndex = [newSelectionPath indexAtPosition:commonPath.length];
NSUInteger minIndex = MIN(anchorIndex, newIndex);
NSUInteger length = MAX(anchorIndex, newIndex) - minIndex;
return MPMakeRangePath([commonPath indexPathByAddingIndex:minIndex], length);
} else {
if ((commonPath.length & 1) == 1) {
commonPath = [commonPath indexPathByRemovingLastIndex];
}
MPExpression *closestCommonAncestor = [self.expressionStorage elementAtIndexPath:commonPath];
NSUInteger anchorIndex = [anchorPath indexAtPosition:commonPath.length];
NSUInteger newIndex = [newSelectionPath indexAtPosition:commonPath.length];
if (commonPath.length < anchorPath.length-1) {
anchorIndex = [closestCommonAncestor locationOfElementAtIndex:anchorIndex];
}
if (commonPath.length < newSelectionPath.length-1) {
newIndex = [closestCommonAncestor locationOfElementAtIndex:newIndex];
}
NSUInteger minIndex = MIN(anchorIndex, newIndex);
if (commonPath.length < anchorPath.length-1 && anchorIndex != minIndex) {
anchorIndex++;
} else if (commonPath.length < newSelectionPath.length-1 && newIndex != minIndex) {
newIndex++;
}
NSUInteger length = MAX(anchorIndex, newIndex) - minIndex;
if (anchorIndex == newIndex) {
length++;
}
MPRangePath *newSelection = MPMakeRangePath([commonPath indexPathByAddingIndex:minIndex], length);
return newSelection;
}
} }
@end @end
@@ -290,6 +410,7 @@
self.selection = MPMakeRangePath(self.selection.maxRangePath, 0); self.selection = MPMakeRangePath(self.selection.maxRangePath, 0);
} else { } else {
NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:self.selection.location NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:self.selection.location
byExtendingSelection:NO
selectWords:NO]; selectWords:NO];
self.selection = MPMakeRangePath(newSelectionLocation, 0); self.selection = MPMakeRangePath(newSelectionLocation, 0);
} }
@@ -301,6 +422,7 @@
self.selection = MPMakeRangePath(self.selection.location, 0); self.selection = MPMakeRangePath(self.selection.location, 0);
} else { } else {
NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:self.selection.location NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:self.selection.location
byExtendingSelection:NO
selectWords:NO]; selectWords:NO];
self.selection = MPMakeRangePath(newSelectionLocation, 0); self.selection = MPMakeRangePath(newSelectionLocation, 0);
} }
@@ -310,6 +432,7 @@
{ {
NSIndexPath *location = self.selection.maxRangePath; NSIndexPath *location = self.selection.maxRangePath;
NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:location NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:location
byExtendingSelection:NO
selectWords:YES]; selectWords:YES];
self.selection = MPMakeRangePath(newSelectionLocation, 0); self.selection = MPMakeRangePath(newSelectionLocation, 0);
} }
@@ -318,6 +441,7 @@
{ {
NSIndexPath *location = self.selection.location; NSIndexPath *location = self.selection.location;
NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:location NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:location
byExtendingSelection:NO
selectWords:YES]; selectWords:YES];
self.selection = MPMakeRangePath(newSelectionLocation, 0); self.selection = MPMakeRangePath(newSelectionLocation, 0);
} }
@@ -342,12 +466,16 @@
NSIndexPath *maxLocation = self.selection.maxRangePath; NSIndexPath *maxLocation = self.selection.maxRangePath;
if (self.selectionModifyingStart) { if (self.selectionModifyingStart) {
location = [self selectionToTheLeftOf:location location = [self selectionToTheLeftOf:location
byExtendingSelection:YES
selectWords:NO]; selectWords:NO];
} else { } else {
maxLocation = [self selectionToTheLeftOf:maxLocation maxLocation = [self selectionToTheLeftOf:maxLocation
byExtendingSelection:YES
selectWords:NO]; selectWords:NO];
} }
self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); self.selection = [self rangePathEnclosingAnchorPath:maxLocation newSelectionPath:location];
NSLog(@"%@", self.selection);
// self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex);
} }
- (void)moveRightAndModifySelection:(id)sender - (void)moveRightAndModifySelection:(id)sender
@@ -360,9 +488,11 @@
if (self.selectionModifyingStart) { if (self.selectionModifyingStart) {
location = [self selectionToTheRightOf:location location = [self selectionToTheRightOf:location
byExtendingSelection:YES
selectWords:NO]; selectWords:NO];
} else { } else {
maxLocation = [self selectionToTheRightOf:maxLocation maxLocation = [self selectionToTheRightOf:maxLocation
byExtendingSelection:YES
selectWords:NO]; selectWords:NO];
} }
self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex);
@@ -377,12 +507,14 @@
NSIndexPath *maxLocation = self.selection.maxRangePath; NSIndexPath *maxLocation = self.selection.maxRangePath;
if (self.selectionModifyingStart) { if (self.selectionModifyingStart) {
location = [self selectionToTheRightOf:location location = [self selectionToTheRightOf:location
byExtendingSelection:YES
selectWords:YES]; selectWords:YES];
if (location.lastIndex > maxLocation.lastIndex) { if (location.lastIndex > maxLocation.lastIndex) {
location = [location indexPathByReplacingLastIndexWithIndex:maxLocation.lastIndex]; location = [location indexPathByReplacingLastIndexWithIndex:maxLocation.lastIndex];
} }
} else { } else {
maxLocation = [self selectionToTheRightOf:maxLocation maxLocation = [self selectionToTheRightOf:maxLocation
byExtendingSelection:YES
selectWords:YES]; selectWords:YES];
} }
self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex); self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex);
@@ -397,9 +529,11 @@
NSIndexPath *maxLocation = self.selection.maxRangePath; NSIndexPath *maxLocation = self.selection.maxRangePath;
if (self.selectionModifyingStart) { if (self.selectionModifyingStart) {
location = [self selectionToTheLeftOf:location location = [self selectionToTheLeftOf:location
byExtendingSelection:YES
selectWords:YES]; selectWords:YES];
} else { } else {
maxLocation = [self selectionToTheLeftOf:maxLocation maxLocation = [self selectionToTheLeftOf:maxLocation
byExtendingSelection:YES
selectWords:YES]; selectWords:YES];
if (maxLocation.lastIndex < location.lastIndex) { if (maxLocation.lastIndex < location.lastIndex) {
maxLocation = [maxLocation indexPathByReplacingLastIndexWithIndex:location.lastIndex]; maxLocation = [maxLocation indexPathByReplacingLastIndexWithIndex:location.lastIndex];
@@ -448,8 +582,8 @@
pointInView.y -= expressionOrigin.y; pointInView.y -= expressionOrigin.y;
NSIndexPath *mouseSelectionPath = [self.expressionStorage.rootLayout indexPathForMousePoint:pointInView]; NSIndexPath *mouseSelectionPath = [self.expressionStorage.rootLayout indexPathForMousePoint:pointInView];
self.selection = [self rangePathEnclosingAnchor:self.mouseAnchor self.selection = [self rangePathEnclosingAnchorPath:self.mouseAnchor
newSelection:mouseSelectionPath]; newSelectionPath:mouseSelectionPath];
} }
#pragma mark Drawing Methods #pragma mark Drawing Methods

View File

@@ -10,6 +10,7 @@
@interface NSIndexPath (MPAdditions) @interface NSIndexPath (MPAdditions)
- (NSUInteger)firstIndex;
- (NSUInteger)lastIndex; - (NSUInteger)lastIndex;
- (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)index; - (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)index;
@@ -34,7 +35,8 @@
- (NSIndexPath *)indexPathByIncrementingLastIndex; - (NSIndexPath *)indexPathByIncrementingLastIndex;
- (NSIndexPath *)indexPathByDecrementingLastIndex; - (NSIndexPath *)indexPathByDecrementingLastIndex;
- (NSIndexPath *)indexPathWithLength:(NSUInteger)length; // use length indexes from the receiver, exception if too much - (NSIndexPath *)indexPathByRemovingIndexesFrom:(NSUInteger)length; // use length indexes from the receiver, exception if too much
- (NSIndexPath *)indexPathByRemovingIndexesTo:(NSUInteger)length; // number of indexes from the beginning to exclude
- (NSIndexPath *)commonIndexPathWith:(NSIndexPath *)indexPath; - (NSIndexPath *)commonIndexPathWith:(NSIndexPath *)indexPath;

View File

@@ -10,6 +10,11 @@
@implementation NSIndexPath (MPAdditions) @implementation NSIndexPath (MPAdditions)
- (NSUInteger)firstIndex
{
return [self indexAtPosition:0];
}
- (NSUInteger)lastIndex - (NSUInteger)lastIndex
{ {
return [self indexAtPosition:self.length-1]; return [self indexAtPosition:self.length-1];
@@ -58,7 +63,7 @@
return [[self indexPathByRemovingLastIndex] indexPathByAddingIndex:lastIndex]; return [[self indexPathByRemovingLastIndex] indexPathByAddingIndex:lastIndex];
} }
- (NSIndexPath *)indexPathWithLength:(NSUInteger)length - (NSIndexPath *)indexPathByRemovingIndexesFrom:(NSUInteger)length
{ {
NSIndexPath *indexPath = [[NSIndexPath alloc] init]; NSIndexPath *indexPath = [[NSIndexPath alloc] init];
for (NSUInteger position = 0; position < length; position++) { for (NSUInteger position = 0; position < length; position++) {
@@ -67,6 +72,15 @@
return indexPath; return indexPath;
} }
- (NSIndexPath *)indexPathByRemovingIndexesTo:(NSUInteger)length
{
NSIndexPath *indexPath = [[NSIndexPath alloc] init];
for (NSUInteger position = length; position < self.length; position++) {
indexPath = [indexPath indexPathByAddingIndex:[self indexAtPosition:position]];
}
return indexPath;
}
- (NSIndexPath *)commonIndexPathWith:(NSIndexPath *)indexPath - (NSIndexPath *)commonIndexPathWith:(NSIndexPath *)indexPath
{ {
NSIndexPath *commonPath = [[NSIndexPath alloc] init]; NSIndexPath *commonPath = [[NSIndexPath alloc] init];