Archived
1

Corrected MPExpression -itemAtIndex:referenceFrame:MPSymbolReferenceFrame

Corrected Deformed Number Format
Added "arcsin", "arccos", "arctan", "lg", "log", "ln" Elementary Functions
This commit is contained in:
Kim Wittenburg
2014-12-11 15:32:06 +01:00
parent 98e4a6dde6
commit c367b1dbe8
7 changed files with 105 additions and 38 deletions

View File

@@ -39,17 +39,21 @@
} else if ([function isEqualToString:@"tan"]) { } else if ([function isEqualToString:@"tan"]) {
func = &tan; func = &tan;
takesArc = YES; takesArc = YES;
} else if ([function isEqualToString:@"asin"]) { } else if ([function isEqualToString:@"asin"] || [function isEqualToString:@"arcsin"]) {
func = &asin; func = &asin;
returnsArc = YES; returnsArc = YES;
} else if ([function isEqualToString:@"acos"]) { } else if ([function isEqualToString:@"acos"] || [function isEqualToString:@"arccos"]) {
func = &acos; func = &acos;
returnsArc = YES; returnsArc = YES;
} else if ([function isEqualToString:@"atan"]) { } else if ([function isEqualToString:@"atan"] || [function isEqualToString:@"arctan"]) {
func = &atan; func = &atan;
returnsArc = YES; returnsArc = YES;
} else if ([function isEqualToString:@"lg"] || [function isEqualToString:@"log"]) {
func = &log10;
} else if ([function isEqualToString:@"ln"]) {
func = &log;
} else { } else {
NSAssert(true, @"function must be one of (sin, cos, tan, asin, acos, atan)."); NSAssert(true, @"function must be one of (sin, cos, tan, asin, acos, atan, lg, log, ln).");
} }
[self setFunction:func [self setFunction:func
takesArcValue:takesArc takesArcValue:takesArc

View File

@@ -269,18 +269,17 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
case MPSymbolReferenceFrame: case MPSymbolReferenceFrame:
{ {
NSUInteger location = 0; NSUInteger offsetInElement;
NSUInteger elementIndex = 0; NSUInteger elementIndex = [self convertIndex:anIndex
id <MPExpressionElement> element = nil; fromReferenceFrame:MPSymbolReferenceFrame
while (location < anIndex) { toReferenceFrame:MPElementReferenceFrame
element = _elements[elementIndex++]; offset:&offsetInElement];
location += element.length; id<MPExpressionElement> element = [self elementAtIndex:elementIndex];
} if ([element isFunction]) {
if (location == anIndex && element.isFunction) {
return element; return element;
} else {
return [((NSString *)element) substringWithRange:NSMakeRange(offsetInElement, 1)];
} }
NSUInteger indexInString = location - element.length + anIndex;
return [((NSString *)element) substringWithRange:NSMakeRange(indexInString, 1)];
} }
case MPTokenReferenceFrame: case MPTokenReferenceFrame:

View File

@@ -259,8 +259,9 @@
// Set the text matrix // Set the text matrix
CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextSetTextMatrix(context, CGAffineTransformIdentity);
// Track the x position // Track the x position and the bounds of the last element
CGFloat x = 0; CGFloat x = 0;
NSRect lastElementBounds = NSMakeRect(0, kMPEmptyBoxYOrigin, kMPEmptyBoxWidth, kMPEmptyBoxHeight);
for (NSUInteger index = 0; index < self.expression.countElements; index++) { for (NSUInteger index = 0; index < self.expression.countElements; index++) {
// The current element // The current element
@@ -279,17 +280,16 @@
CTLineDraw(line, context); CTLineDraw(line, context);
CFRelease(line); CFRelease(line);
if (index < self.expression.countElements-1 && [[self.expression elementAtIndex:index+1] isKindOfClass:[MPPowerFunction class]]) {
MPPowerFunctionLayout *layout = (MPPowerFunctionLayout *)[self childLayoutAtIndex:index+1];
layout.baseBounds = elementBounds;
}
} else { } else {
// Let the child layout draw itself // Let the child layout draw itself
MPLayout *layout = [self childLayoutAtIndex:index]; MPLayout *layout = [self childLayoutAtIndex:index];
if ([layout isKindOfClass:[MPPowerFunctionLayout class]]) {
((MPPowerFunctionLayout *)layout).baseBounds = lastElementBounds;
}
[layout drawAtPoint:NSMakePoint(x, 0)]; [layout drawAtPoint:NSMakePoint(x, 0)];
} }
x += elementBounds.size.width; x += elementBounds.size.width;
lastElementBounds = elementBounds;
} }
CGContextRestoreGState(context); CGContextRestoreGState(context);
} }

View File

@@ -49,9 +49,9 @@
NSString *regexStringFormat = @"\\A(?:" NSString *regexStringFormat = @"\\A(?:"
@"([\\*∙⋅])|" @"([\\*∙⋅])|"
@"([+-](?:\\s*[+-])*)|" @"([+-](?:\\s*[+-])*)|"
@"((?:\\d+%@(?!\\d+))|(?:(?:\\d*%@){2,}\\d*)|%@)|" // Substitute with decimal separator 3 times @"((?:\\d+%@(?!\\d+))|(?:(?:\\d*%@){2,}\\d*)|%@(?!\\d+))|" // Substitute with decimal separator 3 times
@"((?:\\d+(?:%@\\d+)?)|(?:%@\\d+))|" // Substitute with decimal separator 2 times @"((?:\\d+(?:%@\\d+)?)|(?:%@\\d+))|" // Substitute with decimal separator 2 times
@"(sin|cos|tan|asin|acos|atan)|" @"(sin|cos|tan|asin|arcsin|acos|arccos|atan|arctan|lg|log|ln)|"
@"([A-Za-z])|" @"([A-Za-z])|"
@"(!)|" @"(!)|"
@"(=)|" @"(=)|"

View File

@@ -16,6 +16,7 @@
#import "MPParenthesisFunction.h" #import "MPParenthesisFunction.h"
#import "MPFractionFunction.h" #import "MPFractionFunction.h"
#import "MPToken.h"
#import "MPRangePath.h" #import "MPRangePath.h"
#import "MPMathRules.h" #import "MPMathRules.h"
@@ -648,6 +649,10 @@
[self insertParenthesisFunction:nil]; [self insertParenthesisFunction:nil];
return; return;
} }
if ([characters isEqualToString:@")"]) {
[self insertClosingParenthesis];
return;
}
if (theEvent.keyCode == 10) { if (theEvent.keyCode == 10) {
[self insertPowerFunction]; [self insertPowerFunction];
return; return;
@@ -692,6 +697,29 @@
self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], self.selection.length); self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], self.selection.length);
} }
- (void)insertClosingParenthesis
{
if (self.selection.length > 0) {
[self insertParenthesisFunction:self];
} else {
NSIndexPath *currentPath = [[self.selection.location indexPathByRemovingLastIndex] indexPathByRemovingLastIndex];
while (currentPath.length > 0) {
id element = [self.expressionStorage elementAtIndexPath:currentPath];
if ([element isKindOfClass:[MPParenthesisFunction class]]) {
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[currentPath indexPathByRemovingLastIndex]];
NSUInteger selectedIndex = currentPath.lastIndex + 1;
selectedIndex = [targetExpression convertIndex:selectedIndex
fromReferenceFrame:MPElementReferenceFrame
toReferenceFrame:MPSymbolReferenceFrame];
self.selection = MPMakeRangePath([currentPath indexPathByReplacingLastIndexWithIndex:selectedIndex], 0);
break;
} else {
currentPath = [[currentPath indexPathByRemovingLastIndex] indexPathByRemovingLastIndex];
}
}
}
}
- (void)insertPowerFunction - (void)insertPowerFunction
{ {
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection
@@ -712,6 +740,41 @@
- (void)insertFractionFunction - (void)insertFractionFunction
{ {
if (self.selection.length == 0) {
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
NSInteger index = self.selection.location.lastIndex;
NSRange nominatorSymbols = NSMakeRange(index, 0);
while (--index >= 0) {
id<MPExpressionElement> symbol = [targetExpression symbolAtIndex:index];
if ([symbol isString]) {
NSUInteger tokenIndex = [targetExpression convertIndex:index
fromReferenceFrame:MPSymbolReferenceFrame
toReferenceFrame:MPTokenReferenceFrame];
id<MPToken> token = [targetExpression tokenAtIndex:tokenIndex];
if (token.tokenType == MPNumberToken || token.tokenType == MPVariableToken || token.tokenType == MPElementaryFunctionToken) {
nominatorSymbols.location--;
nominatorSymbols.length++;
} else {
break;
}
} else if (nominatorSymbols.length == 0) {
nominatorSymbols.location--;
nominatorSymbols.length++;
} else {
break;
}
}
MPExpression *nominatorExpression = [targetExpression subexpressionWithRange:nominatorSymbols
referenceFrame:MPSymbolReferenceFrame];
MPFractionFunction *function = [[MPFractionFunction alloc] init];
function.nominatorExpression = nominatorExpression;
[targetExpression replaceItemsInRange:nominatorSymbols referenceFrame:MPSymbolReferenceFrame withElements:@[function]];
NSUInteger functionElementIndex = [targetExpression convertIndex:nominatorSymbols.location
fromReferenceFrame:MPSymbolReferenceFrame
toReferenceFrame:MPElementReferenceFrame];
NSUInteger selectedSubexpression = nominatorSymbols.length == 0 ? 0 : 1;
self.selection = MPMakeRangePath([[[self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex] indexPathByAddingIndex:selectedSubexpression] indexPathByAddingIndex:0], 0);
} else {
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection
referenceFrame:MPSymbolReferenceFrame]; referenceFrame:MPSymbolReferenceFrame];
MPFractionFunction *function = [[MPFractionFunction alloc] init]; MPFractionFunction *function = [[MPFractionFunction alloc] init];
@@ -725,6 +788,7 @@
toReferenceFrame:MPElementReferenceFrame]; toReferenceFrame:MPElementReferenceFrame];
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex]; NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex];
self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], 0); self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], 0);
}
} }
- (void)insertNewline:(id)sender - (void)insertNewline:(id)sender

View File

@@ -36,7 +36,7 @@
- (NSIndexSet *)indexesOfRemainingChildren - (NSIndexSet *)indexesOfRemainingChildren
{ {
return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 1)]; return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
} }
- (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index - (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index

View File

@@ -53,7 +53,7 @@
- (NSFont *)specialFontWithSize:(CGFloat)size - (NSFont *)specialFontWithSize:(CGFloat)size
{ {
return [NSFont fontWithName:@"CMU Sans Serif Oblique" return [NSFont fontWithName:@"CMU Serif Italic"
size:size]; size:size];
} }