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 "MPExpressionStorage.h"
#import "MPExpressionLayout.h"
#import "MPFunctionLayout.h"
#import "MPRangePath.h"
@@ -48,13 +49,15 @@
- (NSRect)selectionRect;
- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selection
selectWords:(BOOL)flag;
- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selection
selectWords:(BOOL)flag;
- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selectionPath
byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords;
- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selectionPath
byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords;
- (MPRangePath *)rangePathEnclosingAnchor:(NSIndexPath *)anchor
newSelection:(NSIndexPath *)newSelection;
- (MPRangePath *)rangePathEnclosingAnchorPath:(NSIndexPath *)anchor
newSelectionPath:(NSIndexPath *)newSelection;
@end
@@ -101,43 +104,120 @@
return selectionRect;
}
- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selection
selectWords:(BOOL)flag
- (NSIndexPath *)selectionToTheRightOf:(NSIndexPath *)selectionPath
byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords
{
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[selection indexPathByRemovingLastIndex]];
NSUInteger locationInTarget = selection.lastIndex;
NSIndexPath *targetExpressionPath = [selectionPath indexPathByRemovingLastIndex];
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
NSUInteger locationInTarget = selectionPath.lastIndex;
NSUInteger locationInElement;
NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget
offset:&locationInElement];
id<MPExpressionElement> targetElement;
// There is only a target element if the selection is not the last location in an expression
if (targetElementIndex < targetExpression.numberOfElements) {
targetElement = [targetExpression elementAtIndex:targetElementIndex];
}
if (locationInElement == 0 && !flag) {
NSLog(@"Move to next");
// Move to next element
if (!selectWords && !extendingSelection && (locationInElement == 0 || locationInTarget == targetExpression.length)) {
// 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) {
if (flag) {
if (selectWords) {
locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex+1];
} else {
locationInTarget++;
}
}
return [selection indexPathByReplacingLastIndexWithIndex:locationInTarget];
return [selectionPath indexPathByReplacingLastIndexWithIndex:locationInTarget];
}
- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selection
selectWords:(BOOL)flag
- (NSIndexPath *)selectionToTheLeftOf:(NSIndexPath *)selectionPath
byExtendingSelection:(BOOL)extendingSelection
selectWords:(BOOL)selectWords
{
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[selection indexPathByRemovingLastIndex]];
NSUInteger locationInTarget = selection.lastIndex;
NSIndexPath *targetExpressionPath = [selectionPath indexPathByRemovingLastIndex];
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
NSUInteger locationInTarget = selectionPath.lastIndex;
NSUInteger locationInElement;
NSUInteger targetElementIndex = [targetExpression indexOfElementAtSymbolLocation:locationInTarget
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) {
if (flag) {
if (selectWords) {
if (locationInElement == 0) {
targetElementIndex--;
}
@@ -146,13 +226,53 @@
locationInTarget--;
}
}
return [selection indexPathByReplacingLastIndexWithIndex:locationInTarget];
return [selectionPath indexPathByReplacingLastIndexWithIndex:locationInTarget];
}
- (MPRangePath *)rangePathEnclosingAnchor:(NSIndexPath *)anchor
newSelection:(NSIndexPath *)newSelection
- (MPRangePath *)rangePathEnclosingAnchorPath:(NSIndexPath *)anchorPath
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
@@ -290,6 +410,7 @@
self.selection = MPMakeRangePath(self.selection.maxRangePath, 0);
} else {
NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:self.selection.location
byExtendingSelection:NO
selectWords:NO];
self.selection = MPMakeRangePath(newSelectionLocation, 0);
}
@@ -301,6 +422,7 @@
self.selection = MPMakeRangePath(self.selection.location, 0);
} else {
NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:self.selection.location
byExtendingSelection:NO
selectWords:NO];
self.selection = MPMakeRangePath(newSelectionLocation, 0);
}
@@ -310,6 +432,7 @@
{
NSIndexPath *location = self.selection.maxRangePath;
NSIndexPath *newSelectionLocation = [self selectionToTheRightOf:location
byExtendingSelection:NO
selectWords:YES];
self.selection = MPMakeRangePath(newSelectionLocation, 0);
}
@@ -318,6 +441,7 @@
{
NSIndexPath *location = self.selection.location;
NSIndexPath *newSelectionLocation = [self selectionToTheLeftOf:location
byExtendingSelection:NO
selectWords:YES];
self.selection = MPMakeRangePath(newSelectionLocation, 0);
}
@@ -342,12 +466,16 @@
NSIndexPath *maxLocation = self.selection.maxRangePath;
if (self.selectionModifyingStart) {
location = [self selectionToTheLeftOf:location
byExtendingSelection:YES
selectWords:NO];
} else {
maxLocation = [self selectionToTheLeftOf:maxLocation
byExtendingSelection:YES
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
@@ -360,9 +488,11 @@
if (self.selectionModifyingStart) {
location = [self selectionToTheRightOf:location
selectWords:NO];
byExtendingSelection:YES
selectWords:NO];
} else {
maxLocation = [self selectionToTheRightOf:maxLocation
byExtendingSelection:YES
selectWords:NO];
}
self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex);
@@ -377,12 +507,14 @@
NSIndexPath *maxLocation = self.selection.maxRangePath;
if (self.selectionModifyingStart) {
location = [self selectionToTheRightOf:location
byExtendingSelection:YES
selectWords:YES];
if (location.lastIndex > maxLocation.lastIndex) {
location = [location indexPathByReplacingLastIndexWithIndex:maxLocation.lastIndex];
}
} else {
maxLocation = [self selectionToTheRightOf:maxLocation
byExtendingSelection:YES
selectWords:YES];
}
self.selection = MPMakeRangePath(location, maxLocation.lastIndex-location.lastIndex);
@@ -397,9 +529,11 @@
NSIndexPath *maxLocation = self.selection.maxRangePath;
if (self.selectionModifyingStart) {
location = [self selectionToTheLeftOf:location
byExtendingSelection:YES
selectWords:YES];
} else {
maxLocation = [self selectionToTheLeftOf:maxLocation
byExtendingSelection:YES
selectWords:YES];
if (maxLocation.lastIndex < location.lastIndex) {
maxLocation = [maxLocation indexPathByReplacingLastIndexWithIndex:location.lastIndex];
@@ -448,8 +582,8 @@
pointInView.y -= expressionOrigin.y;
NSIndexPath *mouseSelectionPath = [self.expressionStorage.rootLayout indexPathForMousePoint:pointInView];
self.selection = [self rangePathEnclosingAnchor:self.mouseAnchor
newSelection:mouseSelectionPath];
self.selection = [self rangePathEnclosingAnchorPath:self.mouseAnchor
newSelectionPath:mouseSelectionPath];
}
#pragma mark Drawing Methods

View File

@@ -10,6 +10,7 @@
@interface NSIndexPath (MPAdditions)
- (NSUInteger)firstIndex;
- (NSUInteger)lastIndex;
- (NSIndexPath *)indexPathByReplacingLastIndexWithIndex:(NSUInteger)index;
@@ -34,7 +35,8 @@
- (NSIndexPath *)indexPathByIncrementingLastIndex;
- (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;

View File

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