Started to Implement Evaluation
Corrected Some Errors Cleaned Code
This commit is contained in:
@@ -22,15 +22,28 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="lcd-Ip-jjR" customClass="MPExpressionView">
|
||||
<rect key="frame" x="20" y="20" width="467" height="211"/>
|
||||
<rect key="frame" x="20" y="61" width="467" height="170"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lvU-8o-qPV">
|
||||
<rect key="frame" x="207" y="13" width="93" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Evaluate" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Zda-mn-Rjr">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="evaluateExpressiom:" target="-2" id="jUp-32-wwK"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="lcd-Ip-jjR" firstAttribute="leading" secondItem="gIp-Ho-8D9" secondAttribute="leading" constant="20" symbolic="YES" id="8Li-0i-x3o"/>
|
||||
<constraint firstItem="lcd-Ip-jjR" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" constant="20" symbolic="YES" id="MPQ-lK-4d0"/>
|
||||
<constraint firstAttribute="bottom" secondItem="lcd-Ip-jjR" secondAttribute="bottom" constant="20" symbolic="YES" id="hi3-fp-zJn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="lcd-Ip-jjR" secondAttribute="trailing" constant="20" symbolic="YES" id="xiK-zs-2rs"/>
|
||||
<constraint firstAttribute="bottom" secondItem="lvU-8o-qPV" secondAttribute="bottom" constant="20" symbolic="YES" id="5ws-Hh-dXO"/>
|
||||
<constraint firstItem="lvU-8o-qPV" firstAttribute="top" secondItem="lcd-Ip-jjR" secondAttribute="bottom" constant="20" symbolic="YES" id="CEh-81-Hu6"/>
|
||||
<constraint firstItem="lcd-Ip-jjR" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" constant="20" symbolic="YES" id="Raj-xq-imM"/>
|
||||
<constraint firstAttribute="trailing" secondItem="lcd-Ip-jjR" secondAttribute="trailing" constant="20" symbolic="YES" id="Xh2-Qb-urL"/>
|
||||
<constraint firstItem="lcd-Ip-jjR" firstAttribute="centerX" secondItem="lvU-8o-qPV" secondAttribute="centerX" id="pq6-dU-P1M"/>
|
||||
<constraint firstItem="lcd-Ip-jjR" firstAttribute="leading" secondItem="gIp-Ho-8D9" secondAttribute="leading" constant="20" symbolic="YES" id="wPr-ZO-8KR"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
|
||||
@interface MPDocument : NSDocument
|
||||
|
||||
@property (weak) IBOutlet MPExpressionView *termExpressionView;
|
||||
@property (weak) IBOutlet MPExpressionView *resultExpressionView;
|
||||
|
||||
- (IBAction)changeExpression:(id)sender;
|
||||
- (IBAction)evaluateExpressiom:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#import "MPDocument.h"
|
||||
#import "MPModel.h"
|
||||
#import "MPView.h"
|
||||
|
||||
@implementation MPDocument
|
||||
@@ -59,8 +58,12 @@
|
||||
}
|
||||
|
||||
#pragma mark Actions
|
||||
- (IBAction)changeExpression:(id)sender {
|
||||
[self.resultExpressionView.expressionStorage insertElement:@"abc" atLocation:6];
|
||||
- (IBAction)evaluateExpressiom:(id)sender {
|
||||
NSError *error;
|
||||
NSLog(@"Result: %f", [self.resultExpressionView.expressionStorage evaluateExpression:&error]);
|
||||
if (error) {
|
||||
NSLog(@"Error: %@", error);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@import Foundation;
|
||||
#import "NSString+MPExpressionElement.h"
|
||||
|
||||
@class MPExpression, MPFunction, MPRangePath;
|
||||
@class MPExpression, MPFunction, MPRangePath, MPExpressionEvaluator;
|
||||
@protocol MPExpressionElement;
|
||||
|
||||
/*!
|
||||
@@ -269,8 +269,26 @@
|
||||
- (void)replaceSymbolsInRange:(NSRange)range
|
||||
withElements:(NSArray *)elements;
|
||||
|
||||
#warning Evaluating must possibly return error
|
||||
- (double)doubleValue; // Evaluates Expression
|
||||
|
||||
/*!
|
||||
@method elements
|
||||
@brief Returns an array of all elements in the receiver.
|
||||
|
||||
@discussion The elements in the returned array are not copied before they are
|
||||
returned.
|
||||
|
||||
@return An array of all elements from the receiver.
|
||||
*/
|
||||
- (NSArray *)elements;
|
||||
|
||||
|
||||
#pragma mark Evaluating Expressions
|
||||
|
||||
- (double)evaluateExpression:(NSError *__autoreleasing *)error;
|
||||
|
||||
|
||||
// TODO: Private?
|
||||
@property (readonly, nonatomic, strong) MPExpressionEvaluator *evaluator;
|
||||
|
||||
#pragma mark Notifications
|
||||
// All notification methods should create a new rangePath with the receiver's index added to the beginning of the path and then ascend the message to it's parent
|
||||
@@ -312,7 +330,7 @@
|
||||
@return @c YES if @c anExpression is equal to the receiver, @c NO
|
||||
otherwise.
|
||||
*/
|
||||
- (BOOL)isEqualToExpression:(MPExpression *)anExpression;
|
||||
// - (BOOL)isEqualToExpression:(MPExpression *)anExpression;
|
||||
|
||||
- (NSString *)description;
|
||||
- (NSUInteger)hash;
|
||||
@@ -534,21 +552,6 @@
|
||||
- (void)deleteElementsInRange:(NSRange)range;
|
||||
|
||||
|
||||
#pragma mark Querying Expressions
|
||||
|
||||
|
||||
/*!
|
||||
@method elements
|
||||
@brief Returns an array of all elements in the receiver.
|
||||
|
||||
@discussion The elements in the returned array are not copied before they are
|
||||
returned.
|
||||
|
||||
@return An array of all elements from the receiver.
|
||||
*/
|
||||
- (NSArray *)elements;
|
||||
|
||||
|
||||
/*!
|
||||
@method mutableElements
|
||||
@brief Returns a proxy mutable array object that responds to all methods
|
||||
@@ -564,3 +567,4 @@
|
||||
// - (NSMutableArray *)mutableElements;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
// TODO: Reorganise header/implementation order. Drop the primitive/not primitive Approach
|
||||
|
||||
#import "MPExpression.h"
|
||||
#import "MPFunction.h"
|
||||
#import "MPRangePath.h"
|
||||
@@ -13,8 +15,11 @@
|
||||
#import "NSIndexPath+MPAdditions.h"
|
||||
#import "MPException.h"
|
||||
|
||||
@interface MPExpression ()
|
||||
@property (readonly, nonatomic, strong) NSMutableArray *elements;
|
||||
#import "MPExpressionEvaluator.h"
|
||||
|
||||
@interface MPExpression () {
|
||||
NSMutableArray *__strong _elements;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface MPExpression (MPExpressionPrivate)
|
||||
@@ -64,8 +69,8 @@
|
||||
NSString *splitElement = (NSString *)self.elements[splitElementIndex];
|
||||
NSString *leftPart = [splitElement substringToIndex:splitOffset];
|
||||
NSString *rightPart = [splitElement substringFromIndex:splitOffset];
|
||||
[self.elements replaceObjectsInRange:NSMakeRange(splitElementIndex, 1)
|
||||
withObjectsFromArray:@[leftPart, rightPart]];
|
||||
[_elements replaceObjectsInRange:NSMakeRange(splitElementIndex, 1)
|
||||
withObjectsFromArray:@[leftPart, rightPart]];
|
||||
++splitElementIndex;
|
||||
}
|
||||
*insertionIndex = splitElementIndex;
|
||||
@@ -81,8 +86,6 @@
|
||||
NSUInteger _replacementLength;
|
||||
}
|
||||
|
||||
@synthesize elements = _elements;
|
||||
|
||||
#pragma mark Creation Methods
|
||||
- (instancetype)init
|
||||
{
|
||||
@@ -114,14 +117,14 @@
|
||||
id<MPExpressionElement> current = self.elements[index];
|
||||
if ([current isString]) {
|
||||
if (current.length == 0) {
|
||||
[self.elements removeObjectAtIndex:index];
|
||||
[_elements removeObjectAtIndex:index];
|
||||
if (index >= _editedRange.location && index < NSMaxRange(_editedRange)) {
|
||||
--_replacementLength;
|
||||
}
|
||||
--index;
|
||||
} else if ([next isString]) {
|
||||
NSString *new = [NSString stringWithFormat:@"%@%@", current, next];
|
||||
[self.elements replaceObjectsInRange:NSMakeRange(index, 2)
|
||||
[_elements replaceObjectsInRange:NSMakeRange(index, 2)
|
||||
withObjectsFromArray:@[new]];
|
||||
NSUInteger maxReplacementIndex = _editedRange.location + _replacementLength;
|
||||
if (index == _editedRange.location - 1) {
|
||||
@@ -244,7 +247,7 @@
|
||||
// Perform the replacement
|
||||
NSMutableArray *newElements = [[NSMutableArray alloc] initWithArray:elements
|
||||
copyItems:YES];
|
||||
[self.elements replaceObjectsInRange:NSMakeRange(startIndex, endIndex-startIndex)
|
||||
[_elements replaceObjectsInRange:NSMakeRange(startIndex, endIndex-startIndex)
|
||||
withObjectsFromArray:newElements];
|
||||
|
||||
_cachedLength = 0;
|
||||
@@ -260,11 +263,23 @@
|
||||
replacementLength:_replacementLength];
|
||||
}
|
||||
|
||||
|
||||
- (double)doubleValue
|
||||
- (NSArray *)elements
|
||||
{
|
||||
#warning Unimplemented Method
|
||||
return 0;
|
||||
return _elements;
|
||||
}
|
||||
|
||||
- (double)evaluateExpression:(NSError *__autoreleasing *)error
|
||||
{
|
||||
return [self.evaluator evaluateWithError:error];
|
||||
}
|
||||
|
||||
@synthesize evaluator = _evaluator;
|
||||
- (MPExpressionEvaluator *)evaluator
|
||||
{
|
||||
if (!_evaluator) {
|
||||
_evaluator = [[MPExpressionEvaluator alloc] initWithExpression:self];
|
||||
}
|
||||
return _evaluator;
|
||||
}
|
||||
|
||||
#pragma mark Notifications
|
||||
@@ -272,8 +287,7 @@
|
||||
replacementLength:(NSUInteger)replacementLength
|
||||
{
|
||||
NSUInteger selfIndex = [self.parent indexOfChild:self];
|
||||
MPRangePath *newPath = rangePath.copy;
|
||||
newPath.location = [newPath.location indexPathByPreceedingIndex:selfIndex];
|
||||
MPRangePath *newPath = MPMakeRangePath([rangePath.location indexPathByPreceedingIndex:selfIndex], rangePath.length);
|
||||
[self.parent didChangeElementsInRangePath:newPath
|
||||
replacementLength:replacementLength];
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
@interface MPExpressionLayout (MPLineGeneration)
|
||||
|
||||
- (CTLineRef)lineForElementAtIndex:(NSUInteger)index;
|
||||
- (CTLineRef)createLineForString:(NSString *)aString;
|
||||
|
||||
@end
|
||||
|
||||
@@ -36,16 +35,6 @@
|
||||
return (__bridge CTLineRef)lineObject;
|
||||
}
|
||||
|
||||
- (CTLineRef)createLineForString:(NSString *)aString
|
||||
{
|
||||
NSAttributedString *text = [[NSAttributedString alloc] initWithString:aString
|
||||
attributes:@{NSFontAttributeName: self.font}];
|
||||
CFAttributedStringRef attributedString = CFBridgingRetain(text);
|
||||
CTLineRef line = CTLineCreateWithAttributedString(attributedString);
|
||||
CFRelease(attributedString); // TODO: Is this release appropriate?
|
||||
return line;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPExpressionLayout
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
{
|
||||
NSRect expressionBounds = [self.expressionStorage.rootLayout bounds];
|
||||
CGFloat y = (self.bounds.size.height - expressionBounds.size.height) / 2 + fabs(expressionBounds.origin.y);
|
||||
return NSMakePoint(self.bounds.origin.x, self.bounds.origin.y + y);
|
||||
return NSMakePoint(0, y);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -124,15 +124,19 @@
|
||||
|
||||
- (void)initializeExpressionView
|
||||
{
|
||||
// Setup the Expression Storage
|
||||
MPExpressionStorage *expressionStorage = [[MPExpressionStorage alloc] initWithElements:@[@"12345", [[MPSumFunction alloc] init], [[MPSumFunction alloc] init]]];
|
||||
expressionStorage.expressionView = self;
|
||||
_expressionStorage = expressionStorage;
|
||||
NSRect frame = NSMakeRect(10, 10, 500, 500);
|
||||
NSButton *button = [[NSButton alloc] initWithFrame:frame];
|
||||
|
||||
// Setup the Functions Button
|
||||
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
|
||||
button.buttonType = NSSwitchButton;
|
||||
[button setTitle:@"Functions"];
|
||||
self.functionsButton = button;
|
||||
[self addSubview:self.functionsButton];
|
||||
|
||||
// Setup Selection
|
||||
self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)];
|
||||
self.caretBlinkRate = 1.0;
|
||||
[self restartCaretTimer];
|
||||
@@ -202,7 +206,9 @@
|
||||
- (void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
NSString *characters = theEvent.characters;
|
||||
if (characters.length == 1 && [characters stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]].length == 0) {
|
||||
NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||
[allowedCharacters addCharactersInString:@"+-*/= "];
|
||||
if (characters.length == 1 && [characters stringByTrimmingCharactersInSet:allowedCharacters].length == 0) {
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
[targetExpression replaceSymbolsInRange:self.selection.rangeAtLastIndex withElements:@[characters]];
|
||||
self.selection = MPMakeRangePath([self.selection.location indexPathByIncrementingLastIndex], 0);
|
||||
@@ -277,7 +283,8 @@
|
||||
|
||||
- (void)moveToEndOfLine:(id)sender
|
||||
{
|
||||
|
||||
MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
|
||||
self.selection = MPMakeRangePath([self.selection.location indexPathByReplacingLastIndexWithIndex:targetExpression.length], 0);
|
||||
}
|
||||
|
||||
- (void)moveLeftAndModifySelection:(id)sender
|
||||
@@ -317,12 +324,12 @@
|
||||
|
||||
- (void)moveWordRightAndModifySelection:(id)sender
|
||||
{
|
||||
|
||||
#warning Unimplemented Method
|
||||
}
|
||||
|
||||
- (void)moveWordLeftAndModifySelection:(id)sender
|
||||
{
|
||||
|
||||
#warning Unimplemented Method
|
||||
}
|
||||
|
||||
- (void)selectAll:(id)sender
|
||||
@@ -361,7 +368,7 @@
|
||||
// Draw the background
|
||||
[super drawRect:dirtyRect];
|
||||
[[NSColor whiteColor] set];
|
||||
NSRectFill(self.bounds);
|
||||
NSRectFill(dirtyRect);
|
||||
|
||||
// Calculate the position of the expression (probably also forces layout of the expression the first time)
|
||||
NSPoint expressionOrigin = self.expressionOrigin;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
- (id)elementAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
#pragma mark Evaluating Functions
|
||||
- (double)doubleValue; // Override
|
||||
- (double)evaluateFunction:(NSError *__autoreleasing *)error;
|
||||
|
||||
#pragma mark Messages
|
||||
- (void)didChangeElementsInRangePath:(MPRangePath *)rangePath
|
||||
@@ -46,7 +46,7 @@
|
||||
- (void)didChangeChildAtIndex:(NSUInteger)index;
|
||||
|
||||
#pragma mark Working With Functions
|
||||
- (BOOL)isEqualToFunction:(MPFunction *)aFunction; // Override
|
||||
// - (BOOL)isEqualToFunction:(MPFunction *)aFunction; // Override
|
||||
|
||||
- (NSString *)description; // Should be overridden
|
||||
- (NSUInteger)hash;// Override
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
}
|
||||
|
||||
#pragma mark Evaluating Functions
|
||||
- (double)doubleValue
|
||||
- (double)evaluateFunction:(NSError *__autoreleasing *)error
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -92,8 +92,7 @@
|
||||
replacementLength:(NSUInteger)replacementLength
|
||||
{
|
||||
NSUInteger selfIndex = [self.parent indexOfElement:self];
|
||||
MPRangePath *newPath = rangePath.copy;
|
||||
newPath.location = [newPath.location indexPathByPreceedingIndex:selfIndex];
|
||||
MPRangePath *newPath = MPMakeRangePath([rangePath.location indexPathByPreceedingIndex:selfIndex], rangePath.length);
|
||||
[self.parent didChangeElementsInRangePath:newPath
|
||||
replacementLength:replacementLength];
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
- (void)invalidate;
|
||||
|
||||
#pragma mark Calculation and Drawing Methods
|
||||
- (CTLineRef)createLineForString:(NSString *)aString;
|
||||
|
||||
@property (nonatomic, getter = isFlipped) BOOL flipped;
|
||||
@property (nonatomic) BOOL usesSmallSize;
|
||||
- (NSRect)bounds;
|
||||
|
||||
@@ -128,6 +128,16 @@
|
||||
}
|
||||
|
||||
#pragma mark Calculation and Drawing Methods
|
||||
- (CTLineRef)createLineForString:(NSString *)aString
|
||||
{
|
||||
NSAttributedString *text = [[NSAttributedString alloc] initWithString:aString
|
||||
attributes:@{NSFontAttributeName: self.font}];
|
||||
CFAttributedStringRef attributedString = CFBridgingRetain(text);
|
||||
CTLineRef line = CTLineCreateWithAttributedString(attributedString);
|
||||
CFRelease(attributedString); // TODO: Is this release appropriate?
|
||||
return line;
|
||||
}
|
||||
|
||||
- (NSRect)bounds
|
||||
{
|
||||
if (NSEqualRects(_cachedBounds, NSZeroRect)) {
|
||||
@@ -162,32 +172,3 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPLayout (MPSubclassImplement)
|
||||
|
||||
- (MPLayout *)childLayoutAtIndex:(NSUInteger)index
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSRect)generateBounds
|
||||
{
|
||||
return NSZeroRect;
|
||||
}
|
||||
|
||||
- (NSRect)boundingRectForRange:(NSRange)range
|
||||
{
|
||||
return NSZeroRect;
|
||||
}
|
||||
|
||||
- (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index
|
||||
{
|
||||
return NSZeroPoint;
|
||||
}
|
||||
|
||||
- (void)draw
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -97,10 +97,10 @@
|
||||
}
|
||||
|
||||
#pragma mark Evaluating Functions
|
||||
- (double)doubleValue
|
||||
- (double)evaluateFunction:(NSError *__autoreleasing *)error
|
||||
{
|
||||
#warning Unimplemented Method
|
||||
return 0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#pragma mark Working With Functions
|
||||
|
||||
@@ -26,13 +26,7 @@
|
||||
- (CTLineRef)line
|
||||
{
|
||||
CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{
|
||||
NSAttributedString *text =
|
||||
[[NSAttributedString alloc] initWithString:@"∑"
|
||||
attributes:@{NSFontAttributeName: self.font}];
|
||||
CFAttributedStringRef attributedString = CFBridgingRetain(text);
|
||||
CTLineRef line = CTLineCreateWithAttributedString(attributedString);
|
||||
CFRelease(attributedString); // TODO: Is this release appropriate
|
||||
return line;
|
||||
return [self createLineForString:@"∑"];
|
||||
}];
|
||||
return line;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user