Archived
1

Started to Implement Evaluation

Corrected Some Errors
Cleaned Code
This commit is contained in:
Kim Wittenburg
2014-09-06 01:53:22 +02:00
parent 4a3ea0cede
commit a69b5273ee
13 changed files with 112 additions and 107 deletions

View File

@@ -22,15 +22,28 @@
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="lcd-Ip-jjR" customClass="MPExpressionView"> <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"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView> </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> </subviews>
<constraints> <constraints>
<constraint firstItem="lcd-Ip-jjR" firstAttribute="leading" secondItem="gIp-Ho-8D9" secondAttribute="leading" constant="20" symbolic="YES" id="8Li-0i-x3o"/> <constraint firstAttribute="bottom" secondItem="lvU-8o-qPV" secondAttribute="bottom" constant="20" symbolic="YES" id="5ws-Hh-dXO"/>
<constraint firstItem="lcd-Ip-jjR" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" constant="20" symbolic="YES" id="MPQ-lK-4d0"/> <constraint firstItem="lvU-8o-qPV" firstAttribute="top" secondItem="lcd-Ip-jjR" secondAttribute="bottom" constant="20" symbolic="YES" id="CEh-81-Hu6"/>
<constraint firstAttribute="bottom" secondItem="lcd-Ip-jjR" secondAttribute="bottom" constant="20" symbolic="YES" id="hi3-fp-zJn"/> <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="xiK-zs-2rs"/> <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> </constraints>
</view> </view>
<connections> <connections>

View File

@@ -10,9 +10,8 @@
@interface MPDocument : NSDocument @interface MPDocument : NSDocument
@property (weak) IBOutlet MPExpressionView *termExpressionView;
@property (weak) IBOutlet MPExpressionView *resultExpressionView; @property (weak) IBOutlet MPExpressionView *resultExpressionView;
- (IBAction)changeExpression:(id)sender; - (IBAction)evaluateExpressiom:(id)sender;
@end @end

View File

@@ -7,7 +7,6 @@
// //
#import "MPDocument.h" #import "MPDocument.h"
#import "MPModel.h"
#import "MPView.h" #import "MPView.h"
@implementation MPDocument @implementation MPDocument
@@ -59,8 +58,12 @@
} }
#pragma mark Actions #pragma mark Actions
- (IBAction)changeExpression:(id)sender { - (IBAction)evaluateExpressiom:(id)sender {
[self.resultExpressionView.expressionStorage insertElement:@"abc" atLocation:6]; NSError *error;
NSLog(@"Result: %f", [self.resultExpressionView.expressionStorage evaluateExpression:&error]);
if (error) {
NSLog(@"Error: %@", error);
}
} }
@end @end

View File

@@ -9,7 +9,7 @@
@import Foundation; @import Foundation;
#import "NSString+MPExpressionElement.h" #import "NSString+MPExpressionElement.h"
@class MPExpression, MPFunction, MPRangePath; @class MPExpression, MPFunction, MPRangePath, MPExpressionEvaluator;
@protocol MPExpressionElement; @protocol MPExpressionElement;
/*! /*!
@@ -269,8 +269,26 @@
- (void)replaceSymbolsInRange:(NSRange)range - (void)replaceSymbolsInRange:(NSRange)range
withElements:(NSArray *)elements; 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 #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 // 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 @return @c YES if @c anExpression is equal to the receiver, @c NO
otherwise. otherwise.
*/ */
- (BOOL)isEqualToExpression:(MPExpression *)anExpression; // - (BOOL)isEqualToExpression:(MPExpression *)anExpression;
- (NSString *)description; - (NSString *)description;
- (NSUInteger)hash; - (NSUInteger)hash;
@@ -534,21 +552,6 @@
- (void)deleteElementsInRange:(NSRange)range; - (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 @method mutableElements
@brief Returns a proxy mutable array object that responds to all methods @brief Returns a proxy mutable array object that responds to all methods
@@ -564,3 +567,4 @@
// - (NSMutableArray *)mutableElements; // - (NSMutableArray *)mutableElements;
@end @end

View File

@@ -6,6 +6,8 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved. // Copyright (c) 2014 Kim Wittenburg. All rights reserved.
// //
// TODO: Reorganise header/implementation order. Drop the primitive/not primitive Approach
#import "MPExpression.h" #import "MPExpression.h"
#import "MPFunction.h" #import "MPFunction.h"
#import "MPRangePath.h" #import "MPRangePath.h"
@@ -13,8 +15,11 @@
#import "NSIndexPath+MPAdditions.h" #import "NSIndexPath+MPAdditions.h"
#import "MPException.h" #import "MPException.h"
@interface MPExpression () #import "MPExpressionEvaluator.h"
@property (readonly, nonatomic, strong) NSMutableArray *elements;
@interface MPExpression () {
NSMutableArray *__strong _elements;
}
@end @end
@interface MPExpression (MPExpressionPrivate) @interface MPExpression (MPExpressionPrivate)
@@ -64,8 +69,8 @@
NSString *splitElement = (NSString *)self.elements[splitElementIndex]; NSString *splitElement = (NSString *)self.elements[splitElementIndex];
NSString *leftPart = [splitElement substringToIndex:splitOffset]; NSString *leftPart = [splitElement substringToIndex:splitOffset];
NSString *rightPart = [splitElement substringFromIndex:splitOffset]; NSString *rightPart = [splitElement substringFromIndex:splitOffset];
[self.elements replaceObjectsInRange:NSMakeRange(splitElementIndex, 1) [_elements replaceObjectsInRange:NSMakeRange(splitElementIndex, 1)
withObjectsFromArray:@[leftPart, rightPart]]; withObjectsFromArray:@[leftPart, rightPart]];
++splitElementIndex; ++splitElementIndex;
} }
*insertionIndex = splitElementIndex; *insertionIndex = splitElementIndex;
@@ -81,8 +86,6 @@
NSUInteger _replacementLength; NSUInteger _replacementLength;
} }
@synthesize elements = _elements;
#pragma mark Creation Methods #pragma mark Creation Methods
- (instancetype)init - (instancetype)init
{ {
@@ -114,14 +117,14 @@
id<MPExpressionElement> current = self.elements[index]; id<MPExpressionElement> current = self.elements[index];
if ([current isString]) { if ([current isString]) {
if (current.length == 0) { if (current.length == 0) {
[self.elements removeObjectAtIndex:index]; [_elements removeObjectAtIndex:index];
if (index >= _editedRange.location && index < NSMaxRange(_editedRange)) { if (index >= _editedRange.location && index < NSMaxRange(_editedRange)) {
--_replacementLength; --_replacementLength;
} }
--index; --index;
} else if ([next isString]) { } else if ([next isString]) {
NSString *new = [NSString stringWithFormat:@"%@%@", current, next]; NSString *new = [NSString stringWithFormat:@"%@%@", current, next];
[self.elements replaceObjectsInRange:NSMakeRange(index, 2) [_elements replaceObjectsInRange:NSMakeRange(index, 2)
withObjectsFromArray:@[new]]; withObjectsFromArray:@[new]];
NSUInteger maxReplacementIndex = _editedRange.location + _replacementLength; NSUInteger maxReplacementIndex = _editedRange.location + _replacementLength;
if (index == _editedRange.location - 1) { if (index == _editedRange.location - 1) {
@@ -244,7 +247,7 @@
// Perform the replacement // Perform the replacement
NSMutableArray *newElements = [[NSMutableArray alloc] initWithArray:elements NSMutableArray *newElements = [[NSMutableArray alloc] initWithArray:elements
copyItems:YES]; copyItems:YES];
[self.elements replaceObjectsInRange:NSMakeRange(startIndex, endIndex-startIndex) [_elements replaceObjectsInRange:NSMakeRange(startIndex, endIndex-startIndex)
withObjectsFromArray:newElements]; withObjectsFromArray:newElements];
_cachedLength = 0; _cachedLength = 0;
@@ -260,11 +263,23 @@
replacementLength:_replacementLength]; replacementLength:_replacementLength];
} }
- (NSArray *)elements
- (double)doubleValue
{ {
#warning Unimplemented Method return _elements;
return 0; }
- (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 #pragma mark Notifications
@@ -272,8 +287,7 @@
replacementLength:(NSUInteger)replacementLength replacementLength:(NSUInteger)replacementLength
{ {
NSUInteger selfIndex = [self.parent indexOfChild:self]; NSUInteger selfIndex = [self.parent indexOfChild:self];
MPRangePath *newPath = rangePath.copy; MPRangePath *newPath = MPMakeRangePath([rangePath.location indexPathByPreceedingIndex:selfIndex], rangePath.length);
newPath.location = [newPath.location indexPathByPreceedingIndex:selfIndex];
[self.parent didChangeElementsInRangePath:newPath [self.parent didChangeElementsInRangePath:newPath
replacementLength:replacementLength]; replacementLength:replacementLength];
} }

View File

@@ -16,7 +16,6 @@
@interface MPExpressionLayout (MPLineGeneration) @interface MPExpressionLayout (MPLineGeneration)
- (CTLineRef)lineForElementAtIndex:(NSUInteger)index; - (CTLineRef)lineForElementAtIndex:(NSUInteger)index;
- (CTLineRef)createLineForString:(NSString *)aString;
@end @end
@@ -36,16 +35,6 @@
return (__bridge CTLineRef)lineObject; 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 @end
@implementation MPExpressionLayout @implementation MPExpressionLayout

View File

@@ -51,7 +51,7 @@
{ {
NSRect expressionBounds = [self.expressionStorage.rootLayout bounds]; NSRect expressionBounds = [self.expressionStorage.rootLayout bounds];
CGFloat y = (self.bounds.size.height - expressionBounds.size.height) / 2 + fabs(expressionBounds.origin.y); 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 @end
@@ -124,15 +124,19 @@
- (void)initializeExpressionView - (void)initializeExpressionView
{ {
// Setup the Expression Storage
MPExpressionStorage *expressionStorage = [[MPExpressionStorage alloc] initWithElements:@[@"12345", [[MPSumFunction alloc] init], [[MPSumFunction alloc] init]]]; MPExpressionStorage *expressionStorage = [[MPExpressionStorage alloc] initWithElements:@[@"12345", [[MPSumFunction alloc] init], [[MPSumFunction alloc] init]]];
expressionStorage.expressionView = self; expressionStorage.expressionView = self;
_expressionStorage = expressionStorage; _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.buttonType = NSSwitchButton;
[button setTitle:@"Functions"]; [button setTitle:@"Functions"];
self.functionsButton = button; self.functionsButton = button;
[self addSubview:self.functionsButton]; [self addSubview:self.functionsButton];
// Setup Selection
self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)]; self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)];
self.caretBlinkRate = 1.0; self.caretBlinkRate = 1.0;
[self restartCaretTimer]; [self restartCaretTimer];
@@ -202,7 +206,9 @@
- (void)keyDown:(NSEvent *)theEvent - (void)keyDown:(NSEvent *)theEvent
{ {
NSString *characters = theEvent.characters; 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]]; MPExpression *targetExpression = [self.expressionStorage elementAtIndexPath:[self.selection.location indexPathByRemovingLastIndex]];
[targetExpression replaceSymbolsInRange:self.selection.rangeAtLastIndex withElements:@[characters]]; [targetExpression replaceSymbolsInRange:self.selection.rangeAtLastIndex withElements:@[characters]];
self.selection = MPMakeRangePath([self.selection.location indexPathByIncrementingLastIndex], 0); self.selection = MPMakeRangePath([self.selection.location indexPathByIncrementingLastIndex], 0);
@@ -277,7 +283,8 @@
- (void)moveToEndOfLine:(id)sender - (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 - (void)moveLeftAndModifySelection:(id)sender
@@ -317,12 +324,12 @@
- (void)moveWordRightAndModifySelection:(id)sender - (void)moveWordRightAndModifySelection:(id)sender
{ {
#warning Unimplemented Method
} }
- (void)moveWordLeftAndModifySelection:(id)sender - (void)moveWordLeftAndModifySelection:(id)sender
{ {
#warning Unimplemented Method
} }
- (void)selectAll:(id)sender - (void)selectAll:(id)sender
@@ -361,7 +368,7 @@
// Draw the background // Draw the background
[super drawRect:dirtyRect]; [super drawRect:dirtyRect];
[[NSColor whiteColor] set]; [[NSColor whiteColor] set];
NSRectFill(self.bounds); NSRectFill(dirtyRect);
// Calculate the position of the expression (probably also forces layout of the expression the first time) // Calculate the position of the expression (probably also forces layout of the expression the first time)
NSPoint expressionOrigin = self.expressionOrigin; NSPoint expressionOrigin = self.expressionOrigin;

View File

@@ -37,7 +37,7 @@
- (id)elementAtIndexPath:(NSIndexPath *)indexPath; - (id)elementAtIndexPath:(NSIndexPath *)indexPath;
#pragma mark Evaluating Functions #pragma mark Evaluating Functions
- (double)doubleValue; // Override - (double)evaluateFunction:(NSError *__autoreleasing *)error;
#pragma mark Messages #pragma mark Messages
- (void)didChangeElementsInRangePath:(MPRangePath *)rangePath - (void)didChangeElementsInRangePath:(MPRangePath *)rangePath
@@ -46,7 +46,7 @@
- (void)didChangeChildAtIndex:(NSUInteger)index; - (void)didChangeChildAtIndex:(NSUInteger)index;
#pragma mark Working With Functions #pragma mark Working With Functions
- (BOOL)isEqualToFunction:(MPFunction *)aFunction; // Override // - (BOOL)isEqualToFunction:(MPFunction *)aFunction; // Override
- (NSString *)description; // Should be overridden - (NSString *)description; // Should be overridden
- (NSUInteger)hash;// Override - (NSUInteger)hash;// Override

View File

@@ -82,7 +82,7 @@
} }
#pragma mark Evaluating Functions #pragma mark Evaluating Functions
- (double)doubleValue - (double)evaluateFunction:(NSError *__autoreleasing *)error
{ {
return 0; return 0;
} }
@@ -92,8 +92,7 @@
replacementLength:(NSUInteger)replacementLength replacementLength:(NSUInteger)replacementLength
{ {
NSUInteger selfIndex = [self.parent indexOfElement:self]; NSUInteger selfIndex = [self.parent indexOfElement:self];
MPRangePath *newPath = rangePath.copy; MPRangePath *newPath = MPMakeRangePath([rangePath.location indexPathByPreceedingIndex:selfIndex], rangePath.length);
newPath.location = [newPath.location indexPathByPreceedingIndex:selfIndex];
[self.parent didChangeElementsInRangePath:newPath [self.parent didChangeElementsInRangePath:newPath
replacementLength:replacementLength]; replacementLength:replacementLength];
} }

View File

@@ -41,6 +41,8 @@
- (void)invalidate; - (void)invalidate;
#pragma mark Calculation and Drawing Methods #pragma mark Calculation and Drawing Methods
- (CTLineRef)createLineForString:(NSString *)aString;
@property (nonatomic, getter = isFlipped) BOOL flipped; @property (nonatomic, getter = isFlipped) BOOL flipped;
@property (nonatomic) BOOL usesSmallSize; @property (nonatomic) BOOL usesSmallSize;
- (NSRect)bounds; - (NSRect)bounds;

View File

@@ -128,6 +128,16 @@
} }
#pragma mark Calculation and Drawing Methods #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 - (NSRect)bounds
{ {
if (NSEqualRects(_cachedBounds, NSZeroRect)) { if (NSEqualRects(_cachedBounds, NSZeroRect)) {
@@ -162,32 +172,3 @@
} }
@end @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

View File

@@ -97,10 +97,10 @@
} }
#pragma mark Evaluating Functions #pragma mark Evaluating Functions
- (double)doubleValue - (double)evaluateFunction:(NSError *__autoreleasing *)error
{ {
#warning Unimplemented Method #warning Unimplemented Method
return 0; return 0.0;
} }
#pragma mark Working With Functions #pragma mark Working With Functions

View File

@@ -26,13 +26,7 @@
- (CTLineRef)line - (CTLineRef)line
{ {
CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{ CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{
NSAttributedString *text = return [self createLineForString:@"∑"];
[[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 line; return line;
} }