Corrected MPExpression -itemAtIndex:referenceFrame:MPSymbolReferenceFrame
Corrected Deformed Number Format Added "arcsin", "arccos", "arctan", "lg", "log", "ln" Elementary Functions
This commit is contained in:
@@ -39,17 +39,21 @@
|
||||
} else if ([function isEqualToString:@"tan"]) {
|
||||
func = &tan;
|
||||
takesArc = YES;
|
||||
} else if ([function isEqualToString:@"asin"]) {
|
||||
} else if ([function isEqualToString:@"asin"] || [function isEqualToString:@"arcsin"]) {
|
||||
func = &asin;
|
||||
returnsArc = YES;
|
||||
} else if ([function isEqualToString:@"acos"]) {
|
||||
} else if ([function isEqualToString:@"acos"] || [function isEqualToString:@"arccos"]) {
|
||||
func = &acos;
|
||||
returnsArc = YES;
|
||||
} else if ([function isEqualToString:@"atan"]) {
|
||||
} else if ([function isEqualToString:@"atan"] || [function isEqualToString:@"arctan"]) {
|
||||
func = &atan;
|
||||
returnsArc = YES;
|
||||
} else if ([function isEqualToString:@"lg"] || [function isEqualToString:@"log"]) {
|
||||
func = &log10;
|
||||
} else if ([function isEqualToString:@"ln"]) {
|
||||
func = &log;
|
||||
} 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
|
||||
takesArcValue:takesArc
|
||||
|
||||
@@ -269,18 +269,17 @@ NSString *const MPIllegalElementExceptionElementKey = @"MPIllegalElementExceptio
|
||||
|
||||
case MPSymbolReferenceFrame:
|
||||
{
|
||||
NSUInteger location = 0;
|
||||
NSUInteger elementIndex = 0;
|
||||
id <MPExpressionElement> element = nil;
|
||||
while (location < anIndex) {
|
||||
element = _elements[elementIndex++];
|
||||
location += element.length;
|
||||
}
|
||||
if (location == anIndex && element.isFunction) {
|
||||
NSUInteger offsetInElement;
|
||||
NSUInteger elementIndex = [self convertIndex:anIndex
|
||||
fromReferenceFrame:MPSymbolReferenceFrame
|
||||
toReferenceFrame:MPElementReferenceFrame
|
||||
offset:&offsetInElement];
|
||||
id<MPExpressionElement> element = [self elementAtIndex:elementIndex];
|
||||
if ([element isFunction]) {
|
||||
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:
|
||||
|
||||
@@ -259,8 +259,9 @@
|
||||
// Set the text matrix
|
||||
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
|
||||
|
||||
// Track the x position
|
||||
// Track the x position and the bounds of the last element
|
||||
CGFloat x = 0;
|
||||
NSRect lastElementBounds = NSMakeRect(0, kMPEmptyBoxYOrigin, kMPEmptyBoxWidth, kMPEmptyBoxHeight);
|
||||
|
||||
for (NSUInteger index = 0; index < self.expression.countElements; index++) {
|
||||
// The current element
|
||||
@@ -279,17 +280,16 @@
|
||||
CTLineDraw(line, context);
|
||||
|
||||
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 {
|
||||
// Let the child layout draw itself
|
||||
MPLayout *layout = [self childLayoutAtIndex:index];
|
||||
if ([layout isKindOfClass:[MPPowerFunctionLayout class]]) {
|
||||
((MPPowerFunctionLayout *)layout).baseBounds = lastElementBounds;
|
||||
}
|
||||
[layout drawAtPoint:NSMakePoint(x, 0)];
|
||||
}
|
||||
x += elementBounds.size.width;
|
||||
lastElementBounds = elementBounds;
|
||||
}
|
||||
CGContextRestoreGState(context);
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@
|
||||
NSString *regexStringFormat = @"\\A(?:"
|
||||
@"([\\*∙⋅])|"
|
||||
@"([+-](?:\\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
|
||||
@"(sin|cos|tan|asin|acos|atan)|"
|
||||
@"(sin|cos|tan|asin|arcsin|acos|arccos|atan|arctan|lg|log|ln)|"
|
||||
@"([A-Za-z])|"
|
||||
@"(!)|"
|
||||
@"(=)|"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#import "MPParenthesisFunction.h"
|
||||
#import "MPFractionFunction.h"
|
||||
|
||||
#import "MPToken.h"
|
||||
#import "MPRangePath.h"
|
||||
#import "MPMathRules.h"
|
||||
|
||||
@@ -648,6 +649,10 @@
|
||||
[self insertParenthesisFunction:nil];
|
||||
return;
|
||||
}
|
||||
if ([characters isEqualToString:@")"]) {
|
||||
[self insertClosingParenthesis];
|
||||
return;
|
||||
}
|
||||
if (theEvent.keyCode == 10) {
|
||||
[self insertPowerFunction];
|
||||
return;
|
||||
@@ -692,6 +697,29 @@
|
||||
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
|
||||
{
|
||||
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection
|
||||
@@ -712,6 +740,41 @@
|
||||
|
||||
- (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
|
||||
referenceFrame:MPSymbolReferenceFrame];
|
||||
MPFractionFunction *function = [[MPFractionFunction alloc] init];
|
||||
@@ -725,6 +788,7 @@
|
||||
toReferenceFrame:MPElementReferenceFrame];
|
||||
NSIndexPath *functionPath = [self.selection.location indexPathByReplacingLastIndexWithIndex:functionElementIndex];
|
||||
self.selection = MPMakeRangePath([[functionPath indexPathByAddingIndex:0] indexPathByAddingIndex:0], 0);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)insertNewline:(id)sender
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
- (NSIndexSet *)indexesOfRemainingChildren
|
||||
{
|
||||
return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 1)];
|
||||
return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
|
||||
}
|
||||
|
||||
- (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
- (NSFont *)specialFontWithSize:(CGFloat)size
|
||||
{
|
||||
return [NSFont fontWithName:@"CMU Sans Serif Oblique"
|
||||
return [NSFont fontWithName:@"CMU Serif Italic"
|
||||
size:size];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user