// // MPSumFunctionLayout.m // MathPad // // Created by Kim Wittenburg on 23.04.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPSumFunctionLayout.h" #import "MPSumFunction.h" #import "NSIndexPath+MPAdditions.h" #define kSumFunctionStartExpressionOffset 0 #define kSumFunctionTargetExpressionOffset 0 #define kSumFunctionSumExpressionOffset 3 #define kSumFunctionTrailingOffset 5 @implementation MPSumFunctionLayout - (MPSumFunction *)sumFunction { return (MPSumFunction *)self.function; } - (NSUInteger)indexOfLeadingChild { return 2; } - (NSUInteger)indexOfTrailingChild { return 2; } - (NSUInteger)indexOfChildAfterChildAtIndex:(NSUInteger)index { if (index != 2) { return 2; } return [super indexOfChildAfterChildAtIndex:index]; } - (NSUInteger)indexOfChildBelowChildAtIndex:(NSUInteger)index { return 0; } - (NSUInteger)indexOfChildAboveChildAtIndex:(NSUInteger)index { return 1; } - (NSIndexSet *)indexesOfRemainingChildren { return [NSIndexSet indexSetWithIndex:2]; } - (CTLineRef)line { CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{ return [self createLineForString:@"∑" usingFont:[NSFont fontWithName:@"Times New Roman" size:self.fontSize]]; }]; return line; } - (NSRect)localLineBounds { NSRect lineBounds = CTLineGetBoundsWithOptions(self.line, 0); NSRect startExpressionBounds = [self childLayoutAtIndex:0].bounds; NSRect targetExpressionBounds = [self childLayoutAtIndex:1].bounds; CGFloat width = MAX(MAX(startExpressionBounds.size.width, targetExpressionBounds.size.width), lineBounds.size.width); CGFloat xPosition = (width - lineBounds.size.width) / 2; return NSMakeRect(xPosition, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height); } - (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index { NSRect childBounds = [self childLayoutAtIndex:index].bounds; NSRect localLineBounds = [self localLineBounds]; NSPoint offset; if (index == 0) { // Start Expression offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2; offset.y = localLineBounds.origin.y - kSumFunctionStartExpressionOffset - childBounds.size.height - childBounds.origin.y; } else if (index == 1) { // Target Expression offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2; offset.y = kSumFunctionTargetExpressionOffset + localLineBounds.size.height + localLineBounds.origin.y - childBounds.origin.y; } else { // Sum Expression MPLayout *startExpressionLayout = [self childLayoutAtIndex:0]; MPLayout *targetExpressionLayout = [self childLayoutAtIndex:1]; CGFloat sumWidth = MAX(MAX(localLineBounds.origin.x + localLineBounds.size.width, startExpressionLayout.bounds.size.width), targetExpressionLayout.bounds.size.width); offset.x = sumWidth + kSumFunctionSumExpressionOffset; offset.y = 0; } return offset; } - (BOOL)childAtIndexUsesSmallSize:(NSUInteger)index { return (index == 0 || index == 1) ? YES : self.usesSmallSize; } - (NSIndexPath *)indexPathForLocalMousePoint:(NSPoint)point { if (point.x < CTLineGetBoundsWithOptions(self.line, 0).size.width / 2) { return [NSIndexPath indexPathWithIndex:0]; } else { return [NSIndexPath indexPathWithIndex:1]; } } - (NSRect)generateBounds { NSRect lineBounds = CTLineGetBoundsWithOptions(self.line, 0); NSRect startExpressionBounds = [self childLayoutAtIndex:0].bounds; NSRect targetExpressionBounds = [self childLayoutAtIndex:1].bounds; NSRect sumExpressionBounds = [self childLayoutAtIndex:2].bounds; NSRect bounds = lineBounds; bounds.size.width = MAX(lineBounds.size.width, startExpressionBounds.size.width); bounds.size.height += startExpressionBounds.size.height + kSumFunctionStartExpressionOffset; bounds.origin.y -= startExpressionBounds.size.height + kSumFunctionStartExpressionOffset; bounds.size.width = MAX(bounds.size.width, targetExpressionBounds.size.width); bounds.size.height += targetExpressionBounds.size.height + kSumFunctionTargetExpressionOffset; bounds.size.width += kSumFunctionSumExpressionOffset + sumExpressionBounds.size.width; bounds.size.height = MAX(bounds.size.height, sumExpressionBounds.size.height); bounds.size.width += kSumFunctionTrailingOffset; // The Bounds are a little bigger than the drawn function bounds.size.height += 6; bounds.origin.y -= 3; return bounds; } - (void)draw { // Get the current context CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; // Set the text matrix CGContextSetTextMatrix(context, CGAffineTransformIdentity); // Draw the sum symbol CTLineRef line = [self line]; CFRetain(line); NSRect localLineBounds = [self localLineBounds]; CGContextSetTextPosition(context, localLineBounds.origin.x, 0); CTLineDraw(line, context); // Draw the start function MPLayout *startExpressionLayout = [self childLayoutAtIndex:0]; NSPoint startExpressionLocation = [self offsetOfChildLayoutAtIndex:0]; [startExpressionLayout drawAtPoint:startExpressionLocation]; // Draw the target function MPLayout *targetExpressionLayout = [self childLayoutAtIndex:1]; [targetExpressionLayout drawAtPoint:[self offsetOfChildLayoutAtIndex:1]]; // Draw the sum function MPLayout *sumExpressionLayout = [self childLayoutAtIndex:2]; [sumExpressionLayout drawAtPoint:[self offsetOfChildLayoutAtIndex:2]]; CFRelease(line); } @end