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"/>
<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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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];
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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];
}

View File

@@ -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;

View File

@@ -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)) {
@@ -161,33 +171,4 @@
[transform concat];
}
@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
@end

View File

@@ -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

View File

@@ -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;
}