Corrected errors when selecting expressions
This commit is contained in:
@@ -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
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user