// // MPFunctionLayout.m // MathPad // // Created by Kim Wittenburg on 07.08.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPFunctionLayout.h" #import "MPExpression.h" #import "MPFunction.h" #import "MPSumFunction.h" #import "MPParenthesisFunction.h" #import "MPPowerFunction.h" #import "MPFractionFunction.h" #import "MPRootFunction.h" #import "MPExpressionLayout.h" #import "MPSumFunctionLayout.h" #import "MPParenthesisFunctionLayout.h" #import "MPPowerFunctionLayout.h" #import "MPFractionFunctionLayout.h" #import "MPRootFunctionLayout.h" #import "NSIndexPath+MPAdditions.h" @implementation MPFunctionLayout #pragma mark Creation Methods + (MPFunctionLayout *)functionLayoutForFunction:(MPFunction *)function parent:(MPExpressionLayout *)parent { Class class = [function class]; if (class == [MPSumFunction class]) { return [[MPSumFunctionLayout alloc] initWithFunction:function parent:parent]; } else if (class == [MPParenthesisFunction class]) { return [[MPParenthesisFunctionLayout alloc] initWithFunction:function parent:parent]; } else if (class == [MPPowerFunction class]) { return [[MPPowerFunctionLayout alloc] initWithFunction:function parent:parent]; } else if (class == [MPFractionFunction class]) { return [[MPFractionFunctionLayout alloc] initWithFunction:function parent:parent]; } else if (class == [MPRootFunction class]) { return [[MPRootFunctionLayout alloc] initWithFunction:function parent:parent]; } return [[self alloc] initWithFunction:function parent:parent]; } - (instancetype)initWithFunction:(MPFunction *)function parent:(MPExpressionLayout *)parent { self = [super initWithParent:parent]; if (self) { _function = function; } return self; } #pragma mark Cache Methods - (CTLineRef)lineForPrivateCacheIndex:(NSUInteger)index generator:(CTLineRef (^)())generator { NSUInteger actualIndex = self.function.numberOfChildren + index; id (^actualGenerator)() = ^{ CTLineRef line = generator(); return CFBridgingRelease(line); }; id lineObject = [self cachableObjectForIndex:actualIndex generator:actualGenerator]; return (__bridge CTLineRef)(lineObject); } - (id)objectForPrivateCacheIndex:(NSUInteger)index generator:(id (^)())generator { NSUInteger actualIndex = self.function.numberOfChildren + index; return [self cachableObjectForIndex:actualIndex generator:generator]; } - (NSUInteger)numberOfChildren { return self.function.numberOfChildren; } - (MPLayout *)childLayoutAtIndex:(NSUInteger)index { return [self cachableObjectForIndex:index generator:^id{ MPExpression *child = [self.function childAtIndex:index]; MPExpressionLayout *layout = [[MPExpressionLayout alloc] initWithExpression:child parent:self]; layout.flipped = self.flipped; layout.usesSmallSize = self.usesSmallSize ? YES : [self childAtIndexUsesSmallSize:index]; return layout; }]; } - (BOOL)childAtIndexUsesSmallSize:(NSUInteger)index { return NO; } - (NSIndexPath *)indexPathForMousePoint:(NSPoint)point { // A single index is used to communicate back wether the // selection should be before or after the function. // A 0 means before, a 1 means after. for (NSUInteger index = 0; index < self.function.numberOfChildren; index++) { MPLayout *childLayout = [self childLayoutAtIndex:index]; NSRect childBounds = childLayout.bounds; NSPoint childOffset = [self offsetOfChildLayoutAtIndex:index]; childBounds.origin.x += childOffset.x; childBounds.origin.y += childOffset.y; if (NSMouseInRect(point, childBounds, self.flipped)) { NSPoint pointInChild = NSMakePoint(point.x - childOffset.x, point.y - childOffset.y); NSIndexPath *subPath = [childLayout indexPathForMousePoint:pointInChild]; return [subPath indexPathByPreceedingIndex:index]; } } return [self indexPathForLocalMousePoint:point]; } - (NSUInteger)indexOfLeadingChild { return 0; } - (NSUInteger)indexOfTrailingChild { return 0; } - (NSUInteger)indexOfChildBeforeChildAtIndex:(NSUInteger)index { return NSNotFound; } - (NSUInteger)indexOfChildAfterChildAtIndex:(NSUInteger)index { return NSNotFound; } - (NSUInteger)indexOfChildBelowChildAtIndex:(NSUInteger)index { return index; } - (NSUInteger)indexOfChildAboveChildAtIndex:(NSUInteger)index { return index; } - (NSIndexSet *)indexesOfRemainingChildren { return [NSIndexSet indexSet]; } @end