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"?>
<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>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6245"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6250"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MPDocument">
@@ -35,22 +36,22 @@
</textField>
</subviews>
<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="paI-1L-J2e"/>
<constraint firstAttribute="trailing" secondItem="4B1-d4-7wd" secondAttribute="trailing" constant="20" symbolic="YES" id="Ls8-DM-Zjx"/>
<constraint firstAttribute="bottom" secondItem="4B1-d4-7wd" secondAttribute="bottom" constant="20" symbolic="YES" id="i5Y-pJ-a4a"/>
</constraints>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="bhV-kp-c0I" secondAttribute="bottom" id="VRz-hN-lFY"/>
<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="nYd-dS-gsv"/>
<constraint firstItem="bhV-kp-c0I" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" id="png-CY-BRy"/>
<constraint firstItem="bhV-kp-c0I" firstAttribute="top" secondItem="gIp-Ho-8D9" secondAttribute="top" id="Fxa-FH-JSm"/>
<constraint firstAttribute="trailing" secondItem="bhV-kp-c0I" secondAttribute="trailing" id="OmV-Md-fan"/>
<constraint firstAttribute="bottom" secondItem="bhV-kp-c0I" secondAttribute="bottom" id="Orq-IZ-y4Z"/>
<constraint firstItem="bhV-kp-c0I" firstAttribute="leading" secondItem="gIp-Ho-8D9" secondAttribute="leading" id="ZBu-f7-Tp8"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-x8E"/>
</connections>
<point key="canvasLocation" x="-147" y="119.5"/>
<point key="canvasLocation" x="-32" y="380.5"/>
</window>
<collectionViewItem id="J9S-PW-LCL">
<connections>

View File

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

View File

@@ -6,7 +6,7 @@
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//
// TODO: Undo/Redo + Delegate
// TODO: Undo/Redo + Delegate (evaluateExpressionView:evaluate...)
@class MPExpressionView, MPExpressionStorage, MPExpressionLayout, MPRangePath;
@@ -22,7 +22,8 @@
@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) SEL action;

View File

@@ -10,6 +10,7 @@
#import "MPExpression.h"
#import "MPExpressionElement.h"
#import "MPParsedExpression.h"
#import "MPPowerFunction.h"
#import "MPParenthesisFunction.h"
@@ -20,6 +21,7 @@
#import "MPExpressionStorage.h"
#import "MPExpressionLayout.h"
#import "MPFunctionLayout.h"
#import "MPFunctionsViewController.h"
@@ -33,6 +35,9 @@
@property (nonatomic, strong) NSPopover *functionsPopover;
@property (nonatomic, strong) MPFunctionsViewController *functionsViewController;
@property (nonatomic, strong) NSPopUpButton *syntaxErrorsPopUpButton;
@property (nonatomic, strong) NSTextField *mathErrorTextField;
@property (nonatomic, strong) NSTimer *caretTimer;
@property (nonatomic) NSTimeInterval caretBlinkRate;
@property (nonatomic) BOOL caretVisible;
@@ -336,7 +341,7 @@
_expressionStorage = expressionStorage;
[self initializeButtons];
[self initializeErrorMessageTextField];
[self initializeErrorsViews];
self.selection = [[MPRangePath alloc] initWithRange:NSMakeRange(0, 0)];
self.caretBlinkRate = 1.0;
@@ -374,16 +379,27 @@
constant:0]];
}
- (void)initializeErrorMessageTextField
- (void)initializeErrorsViews
{
NSTextField *errorLabel = self.errorMessageTextField;
[self addSubview:errorLabel];
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(errorLabel);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[errorLabel]"
NSPopUpButton *syntaxErrors = self.syntaxErrorsPopUpButton;
NSTextField *mathError = self.mathErrorTextField;
[self addSubview:syntaxErrors];
[self addSubview:mathError];
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(syntaxErrors, mathError);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[syntaxErrors]"
options:0
metrics:nil
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
metrics:nil
views:variableBindings]];
@@ -405,6 +421,42 @@
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
{
if (!_radiansDegreesButton) {
@@ -447,19 +499,46 @@
return _functionsButton;
}
- (NSTextField *)errorMessageTextField
- (NSPopUpButton *)syntaxErrorsPopUpButton
{
if (!_errorMessageTextField) {
NSTextField *label = [[NSTextField alloc] initWithFrame:NSZeroRect];
label.textColor = [NSColor redColor];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.bezeled = NO;
label.drawsBackground = NO;
label.editable = NO;
label.selectable = NO;
_errorMessageTextField = label;
if (!_syntaxErrorsPopUpButton) {
NSPopUpButton *button = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 26)
pullsDown:YES];
button.translatesAutoresizingMaskIntoConstraints = NO;
[button.cell setArrowPosition:NSPopUpArrowAtBottom];
button.bezelStyle = NSRecessedBezelStyle;
button.buttonType = NSPushOnPushOffButton;
button.showsBorderOnlyWhileMouseInside = YES;
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