Improved Functions Template Chooser
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
@interface MPExpressionView ()
|
@interface MPExpressionView ()
|
||||||
|
|
||||||
@property (nonatomic, weak) NSButton *functionsButton;
|
@property (nonatomic, strong) NSButton *functionsButton;
|
||||||
@property (nonatomic, strong) NSPopover *functionsPopover;
|
@property (nonatomic, strong) NSPopover *functionsPopover;
|
||||||
@property (nonatomic, strong) MPFunctionsViewController *functionsViewController;
|
@property (nonatomic, strong) MPFunctionsViewController *functionsViewController;
|
||||||
|
|
||||||
@@ -312,30 +312,31 @@
|
|||||||
expressionStorage.expressionView = self;
|
expressionStorage.expressionView = self;
|
||||||
_expressionStorage = expressionStorage;
|
_expressionStorage = expressionStorage;
|
||||||
|
|
||||||
NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]];
|
[self initializeButtons];
|
||||||
NSImage *image = [frameworkBundle imageForResource:@"FunctionsButtonDisclosure"];
|
|
||||||
[image setName:@"FunctionsButtonDisclosure"];
|
|
||||||
// Setup the Functions Button
|
|
||||||
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
|
|
||||||
button.target = self;
|
|
||||||
button.action = @selector(showFunctions:);
|
|
||||||
button.buttonType = NSMomentaryChangeButton;
|
|
||||||
button.bezelStyle = NSShadowlessSquareBezelStyle;
|
|
||||||
button.bordered = NO;
|
|
||||||
NSFont *font = [NSFont fontWithName:@"Times New Roman" size:25.0];
|
|
||||||
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:@"Σ" attributes:@{NSFontAttributeName: font, NSForegroundColorAttributeName: [NSColor colorWithWhite:.61 alpha:1]}];
|
|
||||||
button.attributedTitle = attributedTitle;
|
|
||||||
button.imagePosition = NSImageLeft;
|
|
||||||
button.image = image;
|
|
||||||
self.functionsButton = button;
|
|
||||||
[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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)initializeButtons
|
||||||
|
{
|
||||||
|
NSButton *functionsButton = self.functionsButton;
|
||||||
|
[self addSubview:functionsButton];
|
||||||
|
NSDictionary *variableBindings = NSDictionaryOfVariableBindings(functionsButton);
|
||||||
|
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[functionsButton]-10-|"
|
||||||
|
options:0
|
||||||
|
metrics:nil
|
||||||
|
views:variableBindings]];
|
||||||
|
[self addConstraint:[NSLayoutConstraint constraintWithItem:functionsButton
|
||||||
|
attribute:NSLayoutAttributeCenterY
|
||||||
|
relatedBy:NSLayoutRelationEqual
|
||||||
|
toItem:self
|
||||||
|
attribute:NSLayoutAttributeCenterY
|
||||||
|
multiplier:1
|
||||||
|
constant:0]];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark Properties
|
#pragma mark Properties
|
||||||
- (void)setExpressionStorage:(MPExpressionStorage *)expressionStorage
|
- (void)setExpressionStorage:(MPExpressionStorage *)expressionStorage
|
||||||
{
|
{
|
||||||
@@ -358,6 +359,29 @@
|
|||||||
self.needsDisplay = YES;
|
self.needsDisplay = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSButton *)functionsButton
|
||||||
|
{
|
||||||
|
if (!_functionsButton) {
|
||||||
|
NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]];
|
||||||
|
NSImage *image = [frameworkBundle imageForResource:@"FunctionsButtonDisclosure"];
|
||||||
|
[image setName:@"FunctionsButtonDisclosure"];
|
||||||
|
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
|
||||||
|
button.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
button.target = self;
|
||||||
|
button.action = @selector(showFunctions:);
|
||||||
|
button.buttonType = NSMomentaryChangeButton;
|
||||||
|
button.bezelStyle = NSShadowlessSquareBezelStyle;
|
||||||
|
button.bordered = NO;
|
||||||
|
NSFont *font = [NSFont fontWithName:@"Times New Roman" size:25.0];
|
||||||
|
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:@"Σ" attributes:@{NSFontAttributeName: font, NSForegroundColorAttributeName: [NSColor colorWithWhite:.61 alpha:1]}];
|
||||||
|
button.attributedTitle = attributedTitle;
|
||||||
|
button.imagePosition = NSImageLeft;
|
||||||
|
button.image = image;
|
||||||
|
_functionsButton = button;
|
||||||
|
}
|
||||||
|
return _functionsButton;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark Actions
|
#pragma mark Actions
|
||||||
- (void)showFunctions:(id)sender
|
- (void)showFunctions:(id)sender
|
||||||
{
|
{
|
||||||
@@ -429,16 +453,6 @@
|
|||||||
[super setFrame:frameRect];
|
[super setFrame:frameRect];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)layout
|
|
||||||
{
|
|
||||||
NSSize buttonSize = [self.functionsButton fittingSize];
|
|
||||||
self.functionsButton.frame = NSMakeRect(self.bounds.size.width - buttonSize.width - 10,
|
|
||||||
(self.bounds.size.height - buttonSize.height) / 2,
|
|
||||||
buttonSize.width,
|
|
||||||
buttonSize.height);
|
|
||||||
[super layout];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSSize)intrinsicContentSize
|
- (NSSize)intrinsicContentSize
|
||||||
{
|
{
|
||||||
NSSize size = self.expressionStorage.rootLayout.bounds.size;
|
NSSize size = self.expressionStorage.rootLayout.bounds.size;
|
||||||
@@ -458,7 +472,7 @@
|
|||||||
NSString *characters = theEvent.characters;
|
NSString *characters = theEvent.characters;
|
||||||
|
|
||||||
if ([characters isEqualToString:@"("]) {
|
if ([characters isEqualToString:@"("]) {
|
||||||
[self insertParenthesisFunction];
|
[self insertParenthesisFunction:nil];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,7 +480,7 @@
|
|||||||
|
|
||||||
NSString *decimalSeparator = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]];
|
NSString *decimalSeparator = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]];
|
||||||
NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
|
NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||||
[allowedCharacters addCharactersInString:[NSString stringWithFormat:@"+-*= %@", decimalSeparator]];
|
[allowedCharacters addCharactersInString:[NSString stringWithFormat:@"+-*= !%@", decimalSeparator]];
|
||||||
|
|
||||||
if (characters.length == 1 && [characters stringByTrimmingCharactersInSet:allowedCharacters].length == 0) {
|
if (characters.length == 1 && [characters stringByTrimmingCharactersInSet:allowedCharacters].length == 0) {
|
||||||
[self.expressionStorage replaceSymbolsInRangePath:self.selection withElements:@[characters]];
|
[self.expressionStorage replaceSymbolsInRangePath:self.selection withElements:@[characters]];
|
||||||
@@ -476,7 +490,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)insertParenthesisFunction
|
- (void)insertParenthesisFunction:(id)sender
|
||||||
{
|
{
|
||||||
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection];
|
MPExpression *selectedElementsExpression = [self.expressionStorage subexpressionWithRangePath:self.selection];
|
||||||
MPParenthesisFunction *function = [[MPParenthesisFunction alloc] init];
|
MPParenthesisFunction *function = [[MPParenthesisFunction alloc] init];
|
||||||
@@ -700,7 +714,7 @@
|
|||||||
MPExpression *newTargetExpression = [self.expressionStorage elementAtIndexPath:newTargetExpressionPath];
|
MPExpression *newTargetExpression = [self.expressionStorage elementAtIndexPath:newTargetExpressionPath];
|
||||||
NSIndexPath *newSelectionLocation = [functionPath indexPathByReplacingLastIndexWithIndex:[newTargetExpression locationOfElementAtIndex:functionPath.lastIndex]];
|
NSIndexPath *newSelectionLocation = [functionPath indexPathByReplacingLastIndexWithIndex:[newTargetExpression locationOfElementAtIndex:functionPath.lastIndex]];
|
||||||
|
|
||||||
[self.expressionStorage replaceSymbolsInRangePath:MPMakeRangePath(functionPath, 1) withElements:remainder];
|
[self.expressionStorage replaceSymbolsInRangePath:MPMakeRangePath(newSelectionLocation, 1) withElements:remainder];
|
||||||
self.selection = MPMakeRangePath(newSelectionLocation, 0);
|
self.selection = MPMakeRangePath(newSelectionLocation, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
#import "MPParenthesisFunction.h"
|
#import "MPParenthesisFunction.h"
|
||||||
|
|
||||||
|
|
||||||
@class MPFunctionTemplatePrototype;
|
@class MPFunctionTemplateItem;
|
||||||
|
|
||||||
@interface MPFunctionsCollectionView : NSCollectionView
|
@interface MPFunctionsCollectionView : NSCollectionView
|
||||||
|
|
||||||
@property (nonatomic, weak) MPFunctionTemplatePrototype *hoverItem;
|
@property (nonatomic, weak) MPFunctionTemplateItem *hoverItem;
|
||||||
|
|
||||||
@property (nonatomic, weak) id target;
|
@property (nonatomic, weak) id target;
|
||||||
@property (nonatomic) SEL action;
|
@property (nonatomic) SEL action;
|
||||||
@@ -37,7 +37,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@interface MPFunctionTemplatePrototype : NSCollectionViewItem
|
@interface MPFunctionTemplateItem : NSCollectionViewItem
|
||||||
|
@property (nonatomic, copy) NSString *templateName;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
if (NSMouseInRect(pointInView, viewItem.view.frame, self.isFlipped)) {
|
if (NSMouseInRect(pointInView, viewItem.view.frame, self.isFlipped)) {
|
||||||
if (self.target && self.action) {
|
if (self.target && self.action) {
|
||||||
[self.target performSelector:self.action
|
[self.target performSelector:self.action
|
||||||
withObject:[viewItem.representedObject copy]
|
withObject:[[viewItem.representedObject objectForKey:@"function" ] copy]
|
||||||
afterDelay:0.0];
|
afterDelay:0.0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -103,6 +104,7 @@
|
|||||||
@synthesize functionTemplateLayout = _functionTemplateLayout;
|
@synthesize functionTemplateLayout = _functionTemplateLayout;
|
||||||
- (MPFunctionLayout *)functionTemplateLayout
|
- (MPFunctionLayout *)functionTemplateLayout
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!_functionTemplateLayout) {
|
if (!_functionTemplateLayout) {
|
||||||
_functionTemplateLayout = [MPFunctionLayout functionLayoutForFunction:self.functionTemplate
|
_functionTemplateLayout = [MPFunctionLayout functionLayoutForFunction:self.functionTemplate
|
||||||
parent:nil];
|
parent:nil];
|
||||||
@@ -140,21 +142,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@implementation MPFunctionTemplatePrototype
|
@implementation MPFunctionTemplateItem
|
||||||
|
|
||||||
static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMouseOverContext";
|
static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMouseOverContext";
|
||||||
|
|
||||||
- (id)initWithCoder:(NSCoder *)aDecoder
|
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
|
||||||
{
|
{
|
||||||
self = [super initWithCoder:aDecoder];
|
return [super awakeAfterUsingCoder:aDecoder];
|
||||||
if (self) {
|
|
||||||
MPFunctionTemplateView *view = (MPFunctionTemplateView *)self.view;
|
|
||||||
[view addObserver:self
|
|
||||||
forKeyPath:@"mouseOver"
|
|
||||||
options:0
|
|
||||||
context:MPFunctionTemplateViewMouseOverContext];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||||
@@ -175,8 +169,14 @@ static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMo
|
|||||||
|
|
||||||
- (void)setRepresentedObject:(id)representedObject
|
- (void)setRepresentedObject:(id)representedObject
|
||||||
{
|
{
|
||||||
|
MPFunctionTemplateView *view = (MPFunctionTemplateView *)self.view;
|
||||||
|
view.functionTemplate = [representedObject objectForKey:@"function"];
|
||||||
|
self.templateName = [representedObject objectForKey:@"name"];
|
||||||
|
[view addObserver:self
|
||||||
|
forKeyPath:@"mouseOver"
|
||||||
|
options:0
|
||||||
|
context:MPFunctionTemplateViewMouseOverContext];
|
||||||
[super setRepresentedObject:representedObject];
|
[super setRepresentedObject:representedObject];
|
||||||
((MPFunctionTemplateView *)self.view).functionTemplate = representedObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -195,21 +195,14 @@ static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMo
|
|||||||
bundle:[NSBundle bundleForClass:[self class]]];
|
bundle:[NSBundle bundleForClass:[self class]]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithNibName:(NSString *)nibNameOrNil
|
- (void)awakeFromNib
|
||||||
bundle:(NSBundle *)nibBundleOrNil
|
|
||||||
{
|
{
|
||||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
self.functionPrototypes = @[
|
||||||
if (self) {
|
@{@"function": [[MPSumFunction alloc] init],
|
||||||
self.functionPrototypes = @[[[MPSumFunction alloc] init], [[MPParenthesisFunction alloc] init]];
|
@"name": NSLocalizedString(@"Sum", @"Sum Function Name")},
|
||||||
}
|
@{@"function": [[MPParenthesisFunction alloc] init],
|
||||||
return self;
|
@"name": NSLocalizedString(@"Parenthesis", @"Parenthesis Function Name")}
|
||||||
}
|
];
|
||||||
|
|
||||||
static void *MPCollectionViewHoverItemChangeContext = @"MPCollectionViewHoverItemChangeContext";
|
|
||||||
|
|
||||||
- (void)loadView
|
|
||||||
{
|
|
||||||
[super loadView];
|
|
||||||
[self.collectionView addObserver:self
|
[self.collectionView addObserver:self
|
||||||
forKeyPath:@"hoverItem"
|
forKeyPath:@"hoverItem"
|
||||||
options:0
|
options:0
|
||||||
@@ -218,6 +211,13 @@ static void *MPCollectionViewHoverItemChangeContext = @"MPCollectionViewHoverIte
|
|||||||
self.collectionView.action = self.action;
|
self.collectionView.action = self.action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *MPCollectionViewHoverItemChangeContext = @"MPCollectionViewHoverItemChangeContext";
|
||||||
|
|
||||||
|
- (void)setView:(NSView *)view
|
||||||
|
{
|
||||||
|
[super setView:view];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setTarget:(id)target
|
- (void)setTarget:(id)target
|
||||||
{
|
{
|
||||||
_target = target;
|
_target = target;
|
||||||
@@ -240,7 +240,7 @@ static void *MPCollectionViewHoverItemChangeContext = @"MPCollectionViewHoverIte
|
|||||||
context:(void *)context
|
context:(void *)context
|
||||||
{
|
{
|
||||||
if (context == MPCollectionViewHoverItemChangeContext) {
|
if (context == MPCollectionViewHoverItemChangeContext) {
|
||||||
self.currentDescription = [[self.collectionView.hoverItem.representedObject class] performSelector:@selector(localizedFunctionName)];
|
self.currentDescription = self.collectionView.hoverItem.templateName;
|
||||||
} else {
|
} else {
|
||||||
[super observeValueForKeyPath:keyPath
|
[super observeValueForKeyPath:keyPath
|
||||||
ofObject:object
|
ofObject:object
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
<point key="canvasLocation" x="-101" y="140.5"/>
|
<point key="canvasLocation" x="-101" y="140.5"/>
|
||||||
</customView>
|
</customView>
|
||||||
<collectionViewItem id="4Wf-e2-Nmy" customClass="MPFunctionTemplatePrototype">
|
<collectionViewItem id="4Wf-e2-Nmy" customClass="MPFunctionTemplateItem">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="view" destination="dE9-Vu-psk" id="hX8-fz-7FR"/>
|
<outlet property="view" destination="dE9-Vu-psk" id="hX8-fz-7FR"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|||||||
Reference in New Issue
Block a user