Archived
1

Added Function Chooser as a Popover

Improved Evaluation
Added Parenthesis Function
This commit is contained in:
Kim Wittenburg
2014-09-28 23:52:29 +02:00
parent 1c8b7e3c12
commit 19a40c2907
16 changed files with 746 additions and 32 deletions

View File

@@ -0,0 +1,252 @@
//
// 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"
@class MPFunctionTemplatePrototype;
@interface MPFunctionsCollectionView : NSCollectionView
@property (nonatomic, weak) MPFunctionTemplatePrototype *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 MPFunctionTemplatePrototype : NSCollectionViewItem
@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 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 MPFunctionTemplatePrototype
static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMouseOverContext";
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
MPFunctionTemplateView *view = (MPFunctionTemplateView *)self.view;
[view addObserver:self
forKeyPath:@"mouseOver"
options:0
context:MPFunctionTemplateViewMouseOverContext];
}
return self;
}
- (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
{
[super setRepresentedObject:representedObject];
((MPFunctionTemplateView *)self.view).functionTemplate = representedObject;
}
@end
@interface MPFunctionsViewController ()
@end
@implementation MPFunctionsViewController
- (id)init
{
return [self initWithNibName:@"MPFunctionsViewController"
bundle:[NSBundle bundleForClass:[self class]]];
}
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.functionPrototypes = @[[[MPSumFunction alloc] init], [[MPParenthesisFunction alloc] init]];
}
return self;
}
static void *MPCollectionViewHoverItemChangeContext = @"MPCollectionViewHoverItemChangeContext";
- (void)loadView
{
[super loadView];
[self.collectionView addObserver:self
forKeyPath:@"hoverItem"
options:0
context:MPCollectionViewHoverItemChangeContext];
self.collectionView.target = self.target;
self.collectionView.action = self.action;
}
- (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.representedObject class] performSelector:@selector(localizedFunctionName)];
} else {
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}
@end