Model Redesign: Added Reference Frames
Added Inverse Functions UI Redesign Cleaned Code
This commit is contained in:
@@ -11,8 +11,11 @@
|
||||
#import "MPExpressionLayout.h"
|
||||
#import "MPFunctionLayout.h"
|
||||
|
||||
#import "MPPowerFunction.h"
|
||||
|
||||
#import "MPRangePath.h"
|
||||
|
||||
#import "MPMathRules.h"
|
||||
#import "NSIndexPath+MPAdditions.h"
|
||||
|
||||
#import "MPSumFunction.h"
|
||||
@@ -24,10 +27,14 @@
|
||||
|
||||
@interface MPExpressionView ()
|
||||
|
||||
@property (nonatomic, strong) NSButton *radiansDegreesButton;
|
||||
|
||||
@property (nonatomic, strong) NSButton *functionsButton;
|
||||
@property (nonatomic, strong) NSPopover *functionsPopover;
|
||||
@property (nonatomic, strong) MPFunctionsViewController *functionsViewController;
|
||||
|
||||
@property (nonatomic, strong) NSTextField *errorLabel;
|
||||
|
||||
@property (nonatomic, strong) NSTimer *caretTimer;
|
||||
@property (nonatomic) NSTimeInterval caretBlinkRate;
|
||||
@property (nonatomic) BOOL caretVisible;
|
||||
@@ -117,20 +124,22 @@
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
|
||||
NSUInteger locationInTarget = selectionPath.lastIndex;
|
||||
NSUInteger locationInElement;
|
||||
NSUInteger targetElementIndex = [targetExpression indexOfElementAtLocation:locationInTarget
|
||||
offset:&locationInElement];
|
||||
NSUInteger targetElementIndex = [targetExpression convertIndex:locationInTarget
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame
|
||||
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) {
|
||||
if (targetElementIndex < targetExpression.countElements) {
|
||||
targetElement = [targetExpression elementAtIndex:targetElementIndex];
|
||||
}
|
||||
|
||||
if (!selectWords && !extendingSelection && (locationInElement == 0 || locationInTarget == targetExpression.length)) {
|
||||
if (!selectWords && !extendingSelection && (locationInElement == 0 || locationInTarget == targetExpression.countSymbols)) {
|
||||
// First or last index in an element or expression
|
||||
|
||||
// Last element in the expression
|
||||
if (locationInTarget == targetExpression.length) {
|
||||
if (locationInTarget == targetExpression.countSymbols) {
|
||||
// The selection is inside a function and should proceed
|
||||
if (selectionPath.length > 1) {
|
||||
NSIndexPath *functionPath = [[selectionPath indexPathByRemovingLastIndex] indexPathByRemovingLastIndex];
|
||||
@@ -141,7 +150,9 @@
|
||||
// The function is to be exited
|
||||
if (newChildIndex == NSNotFound) {
|
||||
targetExpression = [self.expressionStorage elementAtIndexPath:[functionPath indexPathByRemovingLastIndex]];
|
||||
NSUInteger functionLocationInExpression = [targetExpression locationOfElementAtIndex:functionPath.lastIndex];
|
||||
NSUInteger functionLocationInExpression = [targetExpression convertIndex:functionPath.lastIndex
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
return [functionPath indexPathByReplacingLastIndexWithIndex:functionLocationInExpression+1];
|
||||
} else {
|
||||
return [[targetExpressionPath indexPathByReplacingLastIndexWithIndex:newChildIndex] indexPathByAddingIndex:0];
|
||||
@@ -159,9 +170,11 @@
|
||||
return [[targetFunctionPath indexPathByAddingIndex:leadingChildIndex] indexPathByAddingIndex:0];
|
||||
}
|
||||
}
|
||||
} else if (locationInTarget < targetExpression.length) {
|
||||
} else if (locationInTarget < targetExpression.countSymbols) {
|
||||
if (selectWords) {
|
||||
locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex+1];
|
||||
locationInTarget = [targetExpression convertIndex:targetElementIndex+1
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
} else {
|
||||
locationInTarget++;
|
||||
}
|
||||
@@ -177,8 +190,10 @@
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
|
||||
NSUInteger locationInTarget = selectionPath.lastIndex;
|
||||
NSUInteger locationInElement;
|
||||
NSUInteger targetElementIndex = [targetExpression indexOfElementAtLocation:locationInTarget
|
||||
offset:&locationInElement];
|
||||
NSUInteger targetElementIndex = [targetExpression convertIndex:locationInTarget
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame
|
||||
offset:&locationInElement];
|
||||
|
||||
NSUInteger previousElementIndex = targetElementIndex - (locationInElement == 0 ? 1 : 0);
|
||||
id<MPExpressionElement> previousElement;
|
||||
@@ -198,12 +213,14 @@
|
||||
// The function is to be exited
|
||||
if (newChildIndex == NSNotFound) {
|
||||
targetExpression = [self.expressionStorage elementAtIndexPath:[functionPath indexPathByRemovingLastIndex]];
|
||||
NSUInteger functionLocationInExpression = [targetExpression locationOfElementAtIndex:functionPath.lastIndex];
|
||||
NSUInteger functionLocationInExpression = [targetExpression convertIndex:functionPath.lastIndex
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
return [functionPath indexPathByReplacingLastIndexWithIndex:functionLocationInExpression];
|
||||
} else {
|
||||
targetExpressionPath = [targetExpressionPath indexPathByReplacingLastIndexWithIndex:newChildIndex];
|
||||
targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
|
||||
return [targetExpressionPath indexPathByAddingIndex:targetExpression.length];
|
||||
return [targetExpressionPath indexPathByAddingIndex:targetExpression.countSymbols];
|
||||
}
|
||||
} // else the selection does not change
|
||||
|
||||
@@ -218,7 +235,7 @@
|
||||
|
||||
targetExpressionPath = [targetFunctionPath indexPathByAddingIndex:trailingChildIndex];
|
||||
targetExpression = [self.expressionStorage elementAtIndexPath:targetExpressionPath];
|
||||
return [targetExpressionPath indexPathByAddingIndex:targetExpression.length];
|
||||
return [targetExpressionPath indexPathByAddingIndex:targetExpression.countSymbols];
|
||||
}
|
||||
}
|
||||
} else if (locationInTarget > 0) {
|
||||
@@ -226,7 +243,9 @@
|
||||
if (locationInElement == 0) {
|
||||
targetElementIndex--;
|
||||
}
|
||||
locationInTarget = [targetExpression locationOfElementAtIndex:targetElementIndex];
|
||||
locationInTarget = [targetExpression convertIndex:targetElementIndex
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
} else {
|
||||
locationInTarget--;
|
||||
}
|
||||
@@ -258,10 +277,14 @@
|
||||
NSUInteger newIndex = [newSelectionPath indexAtPosition:commonPath.length];
|
||||
|
||||
if (commonPath.length < anchorPath.length-1) {
|
||||
anchorIndex = [closestCommonAncestor locationOfElementAtIndex:anchorIndex];
|
||||
anchorIndex = [closestCommonAncestor convertIndex:anchorIndex
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
}
|
||||
if (commonPath.length < newSelectionPath.length-1) {
|
||||
newIndex = [closestCommonAncestor locationOfElementAtIndex:newIndex];
|
||||
newIndex = [closestCommonAncestor convertIndex:newIndex
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
}
|
||||
|
||||
NSUInteger minIndex = MIN(anchorIndex, newIndex);
|
||||
@@ -313,6 +336,7 @@
|
||||
_expressionStorage = expressionStorage;
|
||||
|
||||
[self initializeButtons];
|
||||
[self initializeErrorLabel];
|
||||
|
||||
self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)];
|
||||
self.caretBlinkRate = 1.0;
|
||||
@@ -321,10 +345,23 @@
|
||||
|
||||
- (void)initializeButtons
|
||||
{
|
||||
NSButton *radiansDegreesButton = self.radiansDegreesButton;
|
||||
[self addSubview:radiansDegreesButton];
|
||||
NSButton *functionsButton = self.functionsButton;
|
||||
[self addSubview:functionsButton];
|
||||
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(functionsButton);
|
||||
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[functionsButton]-10-|"
|
||||
|
||||
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(radiansDegreesButton, functionsButton);
|
||||
|
||||
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[radiansDegreesButton]"
|
||||
options:0
|
||||
metrics:nil
|
||||
views:variableBindings]];
|
||||
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-10-[radiansDegreesButton]"
|
||||
options:0
|
||||
metrics:nil
|
||||
views:variableBindings]];
|
||||
|
||||
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[functionsButton]-10-|"
|
||||
options:0
|
||||
metrics:nil
|
||||
views:variableBindings]];
|
||||
@@ -337,6 +374,21 @@
|
||||
constant:0]];
|
||||
}
|
||||
|
||||
- (void)initializeErrorLabel
|
||||
{
|
||||
NSTextField *errorLabel = self.errorLabel;
|
||||
[self addSubview:errorLabel];
|
||||
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(errorLabel);
|
||||
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[errorLabel]"
|
||||
options:0
|
||||
metrics:nil
|
||||
views:variableBindings]];
|
||||
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[errorLabel]-10-|"
|
||||
options:0
|
||||
metrics:nil
|
||||
views:variableBindings]];
|
||||
}
|
||||
|
||||
#pragma mark Properties
|
||||
- (void)setExpressionStorage:(MPExpressionStorage *)expressionStorage
|
||||
{
|
||||
@@ -356,16 +408,36 @@
|
||||
- (void)setError:(MPParseError *)error
|
||||
{
|
||||
_error = error;
|
||||
self.errorLabel.stringValue = error.localizedErrorMessage != nil ? error.localizedErrorMessage : @"";
|
||||
self.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (NSButton *)radiansDegreesButton
|
||||
{
|
||||
if (!_radiansDegreesButton) {
|
||||
NSButton *radiansDegreesButton = [[NSButton alloc] initWithFrame:NSZeroRect];
|
||||
radiansDegreesButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
radiansDegreesButton.buttonType = NSMomentaryPushInButton;
|
||||
radiansDegreesButton.bordered = YES;
|
||||
radiansDegreesButton.bezelStyle = NSRoundedBezelStyle;
|
||||
radiansDegreesButton.imagePosition = NSNoImage;
|
||||
radiansDegreesButton.alignment = NSCenterTextAlignment;
|
||||
radiansDegreesButton.title = NSLocalizedString([MPMathRules sharedRules].isUsingDegrees ? @"Deg" : @"Rad", nil);
|
||||
radiansDegreesButton.font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
|
||||
radiansDegreesButton.target = self;
|
||||
radiansDegreesButton.action = @selector(switchRadiansDegrees:);
|
||||
_radiansDegreesButton = radiansDegreesButton;
|
||||
}
|
||||
return _radiansDegreesButton;
|
||||
}
|
||||
|
||||
- (NSButton *)functionsButton
|
||||
{
|
||||
if (!_functionsButton) {
|
||||
NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]];
|
||||
NSImage *image = [frameworkBundle imageForResource:@"FunctionsButtonDisclosure"];
|
||||
[image setName:@"FunctionsButtonDisclosure"];
|
||||
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
|
||||
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
|
||||
button.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
button.target = self;
|
||||
button.action = @selector(showFunctions:);
|
||||
@@ -382,7 +454,28 @@
|
||||
return _functionsButton;
|
||||
}
|
||||
|
||||
- (NSTextField *)errorLabel
|
||||
{
|
||||
if (!_errorLabel) {
|
||||
NSTextField *label = [[NSTextField alloc] initWithFrame:NSZeroRect];
|
||||
label.textColor = [NSColor redColor];
|
||||
label.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
label.bezeled = NO;
|
||||
label.drawsBackground = NO;
|
||||
label.editable = NO;
|
||||
label.selectable = NO;
|
||||
_errorLabel = label;
|
||||
}
|
||||
return _errorLabel;
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
- (void)switchRadiansDegrees:(id)sender
|
||||
{
|
||||
[MPMathRules sharedRules].isUsingDegrees = ![MPMathRules sharedRules].isUsingDegrees;
|
||||
self.radiansDegreesButton.title = NSLocalizedString([MPMathRules sharedRules].isUsingDegrees ? @"Deg" : @"Rad", nil);
|
||||
}
|
||||
|
||||
- (void)showFunctions:(id)sender
|
||||
{
|
||||
if (self.functionsPopover == nil || self.functionsViewController == nil) {
|
||||
@@ -404,10 +497,14 @@
|
||||
- (void)insertFunction:(MPFunction *)function
|
||||
{
|
||||
[self.functionsPopover close];
|
||||
[self.expressionStorage replaceSymbolsInRangePath:self.selection withElements:@[function]];
|
||||
[self.expressionStorage replaceItemsInRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:@[function]];
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:[targetExpression indexOfElementAtLocation:self.selection.location.lastIndex
|
||||
offset:NULL]];
|
||||
NSUInteger functionElementIndex = [targetExpression convertIndex:self.selection.location.lastIndex
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame];
|
||||
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex];
|
||||
MPFunctionLayout *functionLayout = (MPFunctionLayout *)[self.expressionStorage.rootLayout childLayoutAtIndexPath:functionPath];
|
||||
self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:functionLayout.indexOfLeadingChild] indexPathByAddingIndex:0], 0);
|
||||
}
|
||||
@@ -475,15 +572,19 @@
|
||||
[self insertParenthesisFunction:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (theEvent.keyCode == 10) {
|
||||
[self insertPowerFunction];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *decimalSeparator = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]];
|
||||
NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||
[allowedCharacters addCharactersInString:[NSString stringWithFormat:@"+-*= !%@", decimalSeparator]];
|
||||
|
||||
if (characters.length == 1 && [characters stringByTrimmingCharactersInSet:allowedCharacters].length == 0) {
|
||||
[self.expressionStorage replaceSymbolsInRangePath:self.selection withElements:@[characters]];
|
||||
[self.expressionStorage replaceItemsInRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:@[characters]];
|
||||
self.selection = MPMakeRangePath([self.selection.location indexPathByIncrementingLastIndex], 0);
|
||||
} else {
|
||||
[self interpretKeyEvents:@[theEvent]];
|
||||
@@ -492,15 +593,37 @@
|
||||
|
||||
- (void)insertParenthesisFunction:(id)sender
|
||||
{
|
||||
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection];
|
||||
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame];
|
||||
MPParenthesisFunction *function = [[MPParenthesisFunction alloc] init];
|
||||
function.expression = selectedElementsExpression;
|
||||
[self.expressionStorage replaceSymbolsInRangePath:self.selection
|
||||
withElements:@[function]];
|
||||
[self.expressionStorage replaceItemsInRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:@[function]];
|
||||
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:[targetExpression indexOfElementAtLocation:self.selection.location.lastIndex
|
||||
offset:NULL]];
|
||||
NSUInteger functionElementIndex = [targetExpression convertIndex:self.selection.location.lastIndex
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame];
|
||||
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex];
|
||||
self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], self.selection.length);
|
||||
}
|
||||
|
||||
- (void)insertPowerFunction
|
||||
{
|
||||
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame];
|
||||
MPPowerFunction *function = [[MPPowerFunction alloc] init];
|
||||
function.exponentExpression = selectedElementsExpression;
|
||||
[self.expressionStorage replaceItemsInRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:@[function]];
|
||||
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
NSUInteger functionElementIndex = [targetExpression convertIndex:self.selection.location.lastIndex
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame];
|
||||
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex];
|
||||
self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], self.selection.length);
|
||||
}
|
||||
|
||||
@@ -563,7 +686,7 @@
|
||||
- (void)moveToEndOfLine:(id)sender
|
||||
{
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
self.selection = MPMakeRangePath([self.selection.location indexPathByReplacingLastIndexWithIndex:targetExpression.length], 0);
|
||||
self.selection = MPMakeRangePath([self.selection.location indexPathByReplacingLastIndexWithIndex:targetExpression.countSymbols], 0);
|
||||
}
|
||||
|
||||
- (void)moveLeftAndModifySelection:(id)sender
|
||||
@@ -676,22 +799,27 @@
|
||||
- (void)selectAll:(id)sender
|
||||
{
|
||||
NSIndexPath *location = [NSIndexPath indexPathWithIndex:0];
|
||||
self.selection = MPMakeRangePath(location, self.expressionStorage.length);
|
||||
self.selection = MPMakeRangePath(location, self.expressionStorage.countSymbols);
|
||||
}
|
||||
|
||||
- (void)deleteBackward:(id)sender
|
||||
{
|
||||
if (self.selection.length > 0) {
|
||||
[self.expressionStorage replaceSymbolsInRangePath:self.selection withElements:@[]];
|
||||
[self.expressionStorage replaceItemsInRangePath:self.selection
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:@[]];
|
||||
self.selection = MPMakeRangePath(self.selection.location, 0);
|
||||
} else if (self.selection.location.lastIndex > 0) {
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
id <MPExpressionElement> elementToDelete = [targetExpression elementAtIndex:[targetExpression indexOfElementAtLocation:self.selection.location.lastIndex-1
|
||||
offset:NULL]];
|
||||
id<MPExpressionElement> elementToDelete = [targetExpression elementAtIndex:[targetExpression convertIndex:self.selection.location.lastIndex-1
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame]];
|
||||
if ([elementToDelete isFunction]) {
|
||||
self.selection = MPMakeRangePath(self.selection.location.indexPathByDecrementingLastIndex, 1);
|
||||
} else {
|
||||
[targetExpression replaceSymbolsInRange:NSMakeRange(self.selection.location.lastIndex-1, 1) withElements:@[]];
|
||||
[targetExpression replaceItemsInRange:NSMakeRange(self.selection.location.lastIndex-1, 1)
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:@[]];
|
||||
self.selection = MPMakeRangePath([self.selection.location indexPathByDecrementingLastIndex], 0);
|
||||
}
|
||||
} else {
|
||||
@@ -707,14 +835,20 @@
|
||||
for (NSUInteger index = remainingIndexes.firstIndex;
|
||||
index <= remainingIndexes.lastIndex;
|
||||
index = [remainingIndexes indexGreaterThanIndex:index]) {
|
||||
[remainder addObjectsFromArray:[function childAtIndex:index].elements];
|
||||
MPExpression *expression = [function childAtIndex:index];
|
||||
[remainder addObjectsFromArray:[expression allItemsInReferenceFrame:MPElementReferenceFrame]];
|
||||
}
|
||||
|
||||
NSIndexPath *newTargetExpressionPath = [functionPath indexPathByRemovingLastIndex];
|
||||
MPExpression *newTargetExpression = [self.expressionStorage elementAtIndexPath:newTargetExpressionPath];
|
||||
NSIndexPath *newSelectionLocation = [functionPath indexPathByReplacingLastIndexWithIndex:[newTargetExpression locationOfElementAtIndex:functionPath.lastIndex]];
|
||||
NSUInteger newSelectionElementIndex = [newTargetExpression convertIndex:functionPath.lastIndex
|
||||
fromReferenceFrame:MPElementReferenceFrame
|
||||
toReferenceFrame:MPSymbolReferenceFrame];
|
||||
NSIndexPath *newSelectionLocation = [functionPath indexPathByReplacingLastIndexWithIndex:newSelectionElementIndex];
|
||||
|
||||
[self.expressionStorage replaceSymbolsInRangePath:MPMakeRangePath(newSelectionLocation, 1) withElements:remainder];
|
||||
[self.expressionStorage replaceItemsInRangePath:MPMakeRangePath(newSelectionLocation, 1)
|
||||
referenceFrame:MPSymbolReferenceFrame
|
||||
withElements:remainder];
|
||||
self.selection = MPMakeRangePath(newSelectionLocation, 0);
|
||||
}
|
||||
}
|
||||
@@ -762,6 +896,24 @@
|
||||
yBy:expressionOrigin.y];
|
||||
[transform concat];
|
||||
|
||||
// Draw the error
|
||||
if (self.error) {
|
||||
[[NSColor redColor] set];
|
||||
NSRect rect = [self.expressionStorage.rootLayout boundingRectForRangePath:self.error.rangePath];
|
||||
if (self.error.rangePath.length == 0) {
|
||||
NSBezierPath *bezierPath = [NSBezierPath bezierPath];
|
||||
[bezierPath moveToPoint:rect.origin];
|
||||
[bezierPath lineToPoint:NSMakePoint(rect.origin.x - 5, rect.origin.y - 5)];
|
||||
[bezierPath moveToPoint:rect.origin];
|
||||
[bezierPath lineToPoint:NSMakePoint(rect.origin.x + 5, rect.origin.y - 5)];
|
||||
bezierPath.lineWidth = 2.0;
|
||||
[bezierPath stroke];
|
||||
} else {
|
||||
NSRect underlineRect = NSMakeRect(rect.origin.x, rect.origin.y + 2, rect.size.width, 2);
|
||||
NSRectFill(underlineRect);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the selection
|
||||
if (self.caretVisible || self.selection.length > 0) {
|
||||
if (self.selection.length == 0) {
|
||||
|
||||
Reference in New Issue
Block a user