Archived
1

Redesigned Error Display

This commit is contained in:
Kim Wittenburg
2014-11-24 22:43:29 +01:00
parent 7a32e3b0b6
commit 6067600e81
4 changed files with 120 additions and 35 deletions

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6245" systemVersion="14A389" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6250" systemVersion="14B25" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6245"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
</dependencies> </dependencies>
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="MPDocument"> <customObject id="-2" userLabel="File's Owner" customClass="MPDocument">
@@ -35,22 +36,22 @@
</textField> </textField>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstAttribute="bottom" secondItem="4B1-d4-7wd" secondAttribute="bottom" constant="20" symbolic="YES" id="Gnf-6p-lx6"/> <constraint firstAttribute="trailing" secondItem="4B1-d4-7wd" secondAttribute="trailing" constant="20" symbolic="YES" id="Ls8-DM-Zjx"/>
<constraint firstAttribute="trailing" secondItem="4B1-d4-7wd" secondAttribute="trailing" constant="20" symbolic="YES" id="paI-1L-J2e"/> <constraint firstAttribute="bottom" secondItem="4B1-d4-7wd" secondAttribute="bottom" constant="20" symbolic="YES" id="i5Y-pJ-a4a"/>
</constraints> </constraints>
</customView> </customView>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstAttribute="bottom" secondItem="bhV-kp-c0I" secondAttribute="bottom" id="VRz-hN-lFY"/> <constraint firstItem="bhV-kp-c0I" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" id="Fxa-FH-JSm"/>
<constraint firstItem="bhV-kp-c0I" firstAttribute="leading" secondItem="gIp-Ho-8D9" secondAttribute="leading" id="WbH-hd-lvs"/> <constraint firstAttribute="trailing" secondItem="bhV-kp-c0I" secondAttribute="trailing" id="OmV-Md-fan"/>
<constraint firstAttribute="trailing" secondItem="bhV-kp-c0I" secondAttribute="trailing" id="nYd-dS-gsv"/> <constraint firstAttribute="bottom" secondItem="bhV-kp-c0I" secondAttribute="bottom" id="Orq-IZ-y4Z"/>
<constraint firstItem="bhV-kp-c0I" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" id="png-CY-BRy"/> <constraint firstItem="bhV-kp-c0I" firstAttribute="leading" secondItem="gIp-Ho-8D9" secondAttribute="leading" id="ZBu-f7-Tp8"/>
</constraints> </constraints>
</view> </view>
<connections> <connections>
<outlet property="delegate" destination="-2" id="0bl-1N-x8E"/> <outlet property="delegate" destination="-2" id="0bl-1N-x8E"/>
</connections> </connections>
<point key="canvasLocation" x="-147" y="119.5"/> <point key="canvasLocation" x="-32" y="380.5"/>
</window> </window>
<collectionViewItem id="J9S-PW-LCL"> <collectionViewItem id="J9S-PW-LCL">
<connections> <connections>

View File

@@ -8,6 +8,8 @@
#import "MPDocument.h" #import "MPDocument.h"
#import "MPParsedExpression.h"
@implementation MPDocument @implementation MPDocument
- (id)init - (id)init
@@ -60,13 +62,15 @@
#pragma mark Actions #pragma mark Actions
- (IBAction)evaluateExpression:(id)sender { - (IBAction)evaluateExpression:(id)sender {
NSError *error; NSArray *errors;
NSDecimalNumber *result = [self.expressionView.expressionStorage evaluateWithError:&error]; MPParsedExpression *parsedExpression = [self.expressionView.expressionStorage parse:&errors];
if (error) { NSError *mathError;
self.expressionView.errorMessageTextField.stringValue = error.localizedDescription; NSDecimalNumber *result;
} else { if (parsedExpression) {
self.expressionView.errorMessageTextField.stringValue = @""; result = [parsedExpression evaluate:&mathError];
} }
self.expressionView.syntaxErrors = errors;
self.expressionView.mathError = mathError;
self.resultLabel.stringValue = result != nil ? [result descriptionWithLocale:[NSLocale currentLocale]] : @""; self.resultLabel.stringValue = result != nil ? [result descriptionWithLocale:[NSLocale currentLocale]] : @"";
} }

View File

@@ -6,7 +6,7 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved. // Copyright (c) 2014 Kim Wittenburg. All rights reserved.
// //
// TODO: Undo/Redo + Delegate // TODO: Undo/Redo + Delegate (evaluateExpressionView:evaluate...)
@class MPExpressionView, MPExpressionStorage, MPExpressionLayout, MPRangePath; @class MPExpressionView, MPExpressionStorage, MPExpressionLayout, MPRangePath;
@@ -22,7 +22,8 @@
@property (nonatomic, strong) MPRangePath *selection; @property (nonatomic, strong) MPRangePath *selection;
@property (nonatomic, strong) NSTextField *errorMessageTextField; @property (nonatomic, strong) NSError *mathError;
@property (nonatomic, strong) NSArray *syntaxErrors;
@property (nonatomic, weak) id target; @property (nonatomic, weak) id target;
@property (nonatomic) SEL action; @property (nonatomic) SEL action;

View File

@@ -10,6 +10,7 @@
#import "MPExpression.h" #import "MPExpression.h"
#import "MPExpressionElement.h" #import "MPExpressionElement.h"
#import "MPParsedExpression.h"
#import "MPPowerFunction.h" #import "MPPowerFunction.h"
#import "MPParenthesisFunction.h" #import "MPParenthesisFunction.h"
@@ -20,6 +21,7 @@
#import "MPExpressionStorage.h" #import "MPExpressionStorage.h"
#import "MPExpressionLayout.h" #import "MPExpressionLayout.h"
#import "MPFunctionLayout.h"
#import "MPFunctionsViewController.h" #import "MPFunctionsViewController.h"
@@ -33,6 +35,9 @@
@property (nonatomic, strong) NSPopover *functionsPopover; @property (nonatomic, strong) NSPopover *functionsPopover;
@property (nonatomic, strong) MPFunctionsViewController *functionsViewController; @property (nonatomic, strong) MPFunctionsViewController *functionsViewController;
@property (nonatomic, strong) NSPopUpButton *syntaxErrorsPopUpButton;
@property (nonatomic, strong) NSTextField *mathErrorTextField;
@property (nonatomic, strong) NSTimer *caretTimer; @property (nonatomic, strong) NSTimer *caretTimer;
@property (nonatomic) NSTimeInterval caretBlinkRate; @property (nonatomic) NSTimeInterval caretBlinkRate;
@property (nonatomic) BOOL caretVisible; @property (nonatomic) BOOL caretVisible;
@@ -336,7 +341,7 @@
_expressionStorage = expressionStorage; _expressionStorage = expressionStorage;
[self initializeButtons]; [self initializeButtons];
[self initializeErrorMessageTextField]; [self initializeErrorsViews];
self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)]; self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)];
self.caretBlinkRate = 1.0; self.caretBlinkRate = 1.0;
@@ -374,16 +379,27 @@
constant:0]]; constant:0]];
} }
- (void)initializeErrorMessageTextField - (void)initializeErrorsViews
{ {
NSTextField *errorLabel = self.errorMessageTextField;
[self addSubview:errorLabel]; NSPopUpButton *syntaxErrors = self.syntaxErrorsPopUpButton;
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(errorLabel); NSTextField *mathError = self.mathErrorTextField;
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[errorLabel]" [self addSubview:syntaxErrors];
[self addSubview:mathError];
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(syntaxErrors, mathError);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[syntaxErrors]"
options:0 options:0
metrics:nil metrics:nil
views:variableBindings]]; views:variableBindings]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[errorLabel]-10-|" [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[syntaxErrors]-10-|"
options:0
metrics:nil
views:variableBindings]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[mathError]"
options:0
metrics:nil
views:variableBindings]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[mathError]-10-|"
options:0 options:0
metrics:nil metrics:nil
views:variableBindings]]; views:variableBindings]];
@@ -405,6 +421,42 @@
self.needsDisplay = YES; self.needsDisplay = YES;
} }
- (void)setSyntaxErrors:(NSArray *)syntaxErrors
{
_syntaxErrors = syntaxErrors;
[self.syntaxErrorsPopUpButton removeAllItems];
if (syntaxErrors.count == 0) {
self.syntaxErrorsPopUpButton.hidden = YES;
return;
}
self.syntaxErrorsPopUpButton.hidden = NO;
[self.syntaxErrorsPopUpButton addItemWithTitle:@""];
if (syntaxErrors.count == 1) {
NSString *title = NSLocalizedString(@"1 Syntax Error", nil);
NSDictionary *attributes = @{NSForegroundColorAttributeName: [NSColor redColor],
NSFontAttributeName: [NSFont boldSystemFontOfSize:12.0]};
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title attributes:attributes];
[self.syntaxErrorsPopUpButton itemAtIndex:0].attributedTitle = attributedTitle;
} else {
NSString *title = [NSString stringWithFormat:NSLocalizedString(@"%ld Syntax Errors", nil), syntaxErrors.count];
NSDictionary *attributes = @{NSForegroundColorAttributeName: [NSColor redColor],
NSFontAttributeName: [NSFont boldSystemFontOfSize:12.0]};
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title attributes:attributes];
[self.syntaxErrorsPopUpButton itemAtIndex:0].attributedTitle = attributedTitle;
}
NSUInteger index = 0;
for (NSError *error in syntaxErrors) {
[self.syntaxErrorsPopUpButton addItemWithTitle:error.localizedDescription];
index++;
}
}
- (void)setMathError:(NSError *)mathError
{
_mathError = mathError;
self.mathErrorTextField.stringValue = mathError != nil ? mathError.localizedDescription : @"";
}
- (NSButton *)radiansDegreesButton - (NSButton *)radiansDegreesButton
{ {
if (!_radiansDegreesButton) { if (!_radiansDegreesButton) {
@@ -447,19 +499,46 @@
return _functionsButton; return _functionsButton;
} }
- (NSTextField *)errorMessageTextField - (NSPopUpButton *)syntaxErrorsPopUpButton
{ {
if (!_errorMessageTextField) { if (!_syntaxErrorsPopUpButton) {
NSTextField *label = [[NSTextField alloc] initWithFrame:NSZeroRect]; NSPopUpButton *button = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 26)
label.textColor = [NSColor redColor]; pullsDown:YES];
label.translatesAutoresizingMaskIntoConstraints = NO; button.translatesAutoresizingMaskIntoConstraints = NO;
label.bezeled = NO; [button.cell setArrowPosition:NSPopUpArrowAtBottom];
label.drawsBackground = NO; button.bezelStyle = NSRecessedBezelStyle;
label.editable = NO; button.buttonType = NSPushOnPushOffButton;
label.selectable = NO; button.showsBorderOnlyWhileMouseInside = YES;
_errorMessageTextField = label; button.font = [NSFont boldSystemFontOfSize:12.0];
button.hidden = YES;
button.target = self;
button.action = @selector(didSelectError:);
_syntaxErrorsPopUpButton = button;
} }
return _errorMessageTextField; return _syntaxErrorsPopUpButton;
}
- (NSTextField *)mathErrorTextField
{
if (!_mathErrorTextField) {
NSTextField *textField = [[NSTextField alloc] init];
textField.translatesAutoresizingMaskIntoConstraints = NO;
textField.bordered = NO;
textField.selectable = NO;
textField.editable = NO;
textField.textColor = [NSColor redColor];
textField.font = [NSFont boldSystemFontOfSize:12.0];
_mathErrorTextField = textField;
}
return _mathErrorTextField;
}
- (void)didSelectError:(NSPopUpButton *)sender
{
NSError *error = self.syntaxErrors[sender.indexOfSelectedItem-1];
NSIndexPath *pathToExpression = error.userInfo[MPPathToExpressionKey];
pathToExpression = [pathToExpression indexPathByAddingIndex:[error.userInfo[MPErrorIndexKey] integerValue]];
self.selection = MPMakeRangePath(pathToExpression, 0);
} }
#pragma mark Actions #pragma mark Actions