// // MPFunctionsViewController.m // MathPad // // Created by Kim Wittenburg on 28.09.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPFunctionsViewController.h" #import "MPFunction.h" #import "MPFunctionLayout.h" #import "MPSumFunction.h" #import "MPParenthesisFunction.h" #import "MPPowerFunction.h" #import "MPFractionFunction.h" @class MPFunctionTemplateItem; @interface MPFunctionsCollectionView : NSCollectionView @property (nonatomic, weak) MPFunctionTemplateItem *hoverItem; @property (nonatomic, weak) id target; @property (nonatomic) SEL action; @end @interface MPFunctionTemplateView : NSView @property (nonatomic, strong) MPFunction *functionTemplate; @property (readonly, nonatomic, strong) MPFunctionLayout *functionTemplateLayout; @property (nonatomic, strong) NSTrackingArea *trackingArea; @property (nonatomic) BOOL mouseOver; @end @interface MPFunctionTemplateItem : NSCollectionViewItem @property (nonatomic, copy) NSString *templateName; @end @implementation MPFunctionsCollectionView - (void)mouseDown:(NSEvent *)theEvent { } - (void)mouseUp:(NSEvent *)theEvent { NSPoint pointInView = [self convertPoint:theEvent.locationInWindow fromView:nil]; for (NSUInteger index = 0; index < self.content.count; index++) { NSCollectionViewItem *viewItem = [self itemAtIndex:index]; if (NSMouseInRect(pointInView, viewItem.view.frame, self.isFlipped)) { if (self.target && self.action) { [self.target performSelector:self.action withObject:[[viewItem.representedObject objectForKey:@"function" ] copy] afterDelay:0.0]; } break; } } } @end @implementation MPFunctionTemplateView - (void)updateTrackingAreas { if (!self.trackingArea) { self.trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited|NSTrackingActiveInKeyWindow|NSTrackingInVisibleRect owner:self userInfo:nil]; [self addTrackingArea:self.trackingArea]; } [super updateTrackingAreas]; } - (void)mouseEntered:(NSEvent *)theEvent { self.mouseOver = YES; self.needsDisplay = YES; } - (void)mouseExited:(NSEvent *)theEvent { self.mouseOver = NO; self.needsDisplay = YES; } - (void)setFunctionTemplate:(MPFunction *)functionTemplate { _functionTemplate = functionTemplate; _functionTemplateLayout = nil; } @synthesize functionTemplateLayout = _functionTemplateLayout; - (MPFunctionLayout *)functionTemplateLayout { if (!_functionTemplateLayout) { _functionTemplateLayout = [MPFunctionLayout functionLayoutForFunction:self.functionTemplate parent:nil]; _functionTemplateLayout.usesSmallSize = YES; } return _functionTemplateLayout; } - (NSSize)intrinsicContentSize { return [self.functionTemplateLayout bounds].size; } - (BOOL)isOpaque { return NO; } - (void)drawRect:(NSRect)dirtyRect { if (self.mouseOver) { [[NSColor selectedTextBackgroundColor] set]; NSBezierPath *background = [NSBezierPath bezierPathWithRoundedRect:self.bounds xRadius:10 yRadius:10]; [background fill]; } [[NSColor textColor] set]; NSPoint origin = NSMakePoint((self.bounds.size.width - self.functionTemplateLayout.bounds.size.width) / 2, (self.bounds.size.height - self.functionTemplateLayout.bounds.size.height) / 2); origin.y -= self.functionTemplateLayout.bounds.origin.y; [self.functionTemplateLayout drawAtPoint:origin]; } @end @implementation MPFunctionTemplateItem static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMouseOverContext"; - (id)awakeAfterUsingCoder:(NSCoder *)aDecoder { return [super awakeAfterUsingCoder:aDecoder]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == MPFunctionTemplateViewMouseOverContext) { MPFunctionTemplateView *view = (MPFunctionTemplateView *)self.view; ((MPFunctionsCollectionView *)self.collectionView).hoverItem = view.mouseOver ? self : nil; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (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]; } @end @interface MPFunctionsViewController () @end @implementation MPFunctionsViewController - (id)init { return [self initWithNibName:@"MPFunctionsViewController" bundle:[NSBundle bundleForClass:[self class]]]; } - (void)awakeFromNib { MPFunction *sumFunction = [[MPSumFunction alloc] init]; MPFunction *parenthesisFunction = [[MPParenthesisFunction alloc] init]; MPFunction *powerFunction = [[MPPowerFunction alloc] init]; MPPowerFunction *squareFunction = [[MPPowerFunction alloc] init]; squareFunction.exponentExpression = [[MPExpression alloc] initWithElement:@"2"]; MPPowerFunction *cubicFunction = [[MPPowerFunction alloc] init]; cubicFunction.exponentExpression = [[MPExpression alloc] initWithElement:@"3"]; MPFractionFunction *fractionFunction = [[MPFractionFunction alloc] init]; self.functionPrototypes = @[ @{@"function": sumFunction, @"name": NSLocalizedString(@"Sum", @"Sum Function Name")}, @{@"function": parenthesisFunction, @"name": NSLocalizedString(@"Parenthesis", @"Parenthesis Function Name")}, @{@"function": squareFunction, @"name": NSLocalizedString(@"Square", @"Square Function Name")}, @{@"function": cubicFunction, @"name": NSLocalizedString(@"Cubic", @"Cubic Function Name")}, @{@"function": powerFunction, @"name": NSLocalizedString(@"Power", @"Power Function Name")}, @{@"function": fractionFunction, @"name": NSLocalizedString(@"Fraction", @"Fraction Function Name")} ]; [self.collectionView addObserver:self forKeyPath:@"hoverItem" options:0 context:MPCollectionViewHoverItemChangeContext]; self.collectionView.target = self.target; self.collectionView.action = self.action; } static void *MPCollectionViewHoverItemChangeContext = @"MPCollectionViewHoverItemChangeContext"; - (void)setView:(NSView *)view { [super setView:view]; } - (void)setTarget:(id)target { _target = target; if (self.collectionView) { self.collectionView.target = target; } } - (void)setAction:(SEL)action { _action = action; if (self.collectionView) { self.collectionView.action = action; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == MPCollectionViewHoverItemChangeContext) { self.currentDescription = self.collectionView.hoverItem.templateName; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } @end