Some Code Improvements
Added Parenthesis Function
This commit is contained in:
16
MathPad/MPParenthesisFunctionLayout.h
Normal file
16
MathPad/MPParenthesisFunctionLayout.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// MPParenthesisFunctionLayout.h
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 17.09.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPFunctionLayout.h"
|
||||||
|
#import "MPParenthesisFunction.h"
|
||||||
|
|
||||||
|
@interface MPParenthesisFunctionLayout : MPFunctionLayout
|
||||||
|
|
||||||
|
- (MPParenthesisFunction *)parenthesisFunction;
|
||||||
|
|
||||||
|
@end
|
||||||
189
MathPad/MPParenthesisFunctionLayout.m
Normal file
189
MathPad/MPParenthesisFunctionLayout.m
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
//
|
||||||
|
// MPParenthesisFunctionLayout.m
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 17.09.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPParenthesisFunctionLayout.h"
|
||||||
|
|
||||||
|
#define MPParenthesisFunctionOpeningParensOffset 2
|
||||||
|
#define MPParenthesisFunctionClosingParensOffset 0
|
||||||
|
|
||||||
|
@interface MPParenthesisFunctionLayout ()
|
||||||
|
|
||||||
|
- (NSBezierPath *)openingParens;
|
||||||
|
- (NSBezierPath *)closingParens;
|
||||||
|
|
||||||
|
- (NSBezierPath *)transformedOpeningParens;
|
||||||
|
- (NSBezierPath *)transformedClosingParens;
|
||||||
|
|
||||||
|
- (NSAffineTransform *)parenthesisTransform;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MPParenthesisFunctionLayout
|
||||||
|
|
||||||
|
- (MPParenthesisFunction *)parenthesisFunction
|
||||||
|
{
|
||||||
|
return (MPParenthesisFunction *)self.function;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSBezierPath *)openingParens
|
||||||
|
{
|
||||||
|
NSBezierPath *parens = [self objectForPrivateCacheIndex:0 generator:^id{
|
||||||
|
CTLineRef line = [self createLineForString:@"("];
|
||||||
|
CFArrayRef glyphRuns = CTLineGetGlyphRuns(line);
|
||||||
|
CFRetain(glyphRuns);
|
||||||
|
CTRunRef glyphRun = CFArrayGetValueAtIndex(glyphRuns, 0);
|
||||||
|
CFRetain(glyphRun);
|
||||||
|
|
||||||
|
CGGlyph *glyphs = malloc(1 * sizeof(CGGlyph));
|
||||||
|
CTRunGetGlyphs(glyphRun, CFRangeMake(0, 1), glyphs);
|
||||||
|
NSGlyph glyph = glyphs[0];
|
||||||
|
|
||||||
|
NSBezierPath *path = [[NSBezierPath alloc] init];
|
||||||
|
[path moveToPoint:NSZeroPoint];
|
||||||
|
[path appendBezierPathWithGlyph:glyph
|
||||||
|
inFont:self.font];
|
||||||
|
|
||||||
|
CFRelease(line);
|
||||||
|
CFRelease(glyphRuns);
|
||||||
|
CFRelease(glyphRun);
|
||||||
|
free(glyphs);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}];
|
||||||
|
return parens;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSBezierPath *)closingParens
|
||||||
|
{
|
||||||
|
NSBezierPath *parens = [self objectForPrivateCacheIndex:1 generator:^id{
|
||||||
|
CTLineRef line = [self createLineForString:@")"];
|
||||||
|
CFArrayRef glyphRuns = CTLineGetGlyphRuns(line);
|
||||||
|
CFRetain(glyphRuns);
|
||||||
|
CTRunRef glyphRun = CFArrayGetValueAtIndex(glyphRuns, 0);
|
||||||
|
CFRetain(glyphRun);
|
||||||
|
|
||||||
|
CGGlyph *glyphs = malloc(1 * sizeof(CGGlyph));
|
||||||
|
CTRunGetGlyphs(glyphRun, CFRangeMake(0, 1), glyphs);
|
||||||
|
NSGlyph glyph = glyphs[0];
|
||||||
|
|
||||||
|
NSBezierPath *path = [[NSBezierPath alloc] init];
|
||||||
|
[path moveToPoint:NSZeroPoint];
|
||||||
|
[path appendBezierPathWithGlyph:glyph
|
||||||
|
inFont:self.font];
|
||||||
|
|
||||||
|
CFRelease(line);
|
||||||
|
CFRelease(glyphRuns);
|
||||||
|
CFRelease(glyphRun);
|
||||||
|
free(glyphs);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}];
|
||||||
|
return parens;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSBezierPath *)transformedOpeningParens
|
||||||
|
{
|
||||||
|
NSBezierPath *parens = self.openingParens.copy;
|
||||||
|
[parens transformUsingAffineTransform:self.parenthesisTransform];
|
||||||
|
return parens;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSBezierPath *)transformedClosingParens
|
||||||
|
{
|
||||||
|
NSBezierPath *parens = self.closingParens.copy;
|
||||||
|
[parens transformUsingAffineTransform:self.parenthesisTransform];
|
||||||
|
return parens;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSAffineTransform *)parenthesisTransform
|
||||||
|
{
|
||||||
|
NSRect parensBounds = self.openingParens.bounds;
|
||||||
|
NSRect expressionBounds = [self childLayoutAtIndex:0].bounds;
|
||||||
|
NSAffineTransform *transform = [NSAffineTransform transform];
|
||||||
|
if (expressionBounds.size.height >= parensBounds.size.height) {
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
CGFloat scaleFactor = expressionBounds.size.height / parensBounds.size.height;
|
||||||
|
[transform scaleXBy:1
|
||||||
|
yBy:scaleFactor];
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
if (index == 0) {
|
||||||
|
return NSMakePoint(self.openingParens.bounds.size.width + MPParenthesisFunctionOpeningParensOffset, 0);
|
||||||
|
}
|
||||||
|
return NSZeroPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSIndexPath *)indexPathForLocalMousePoint:(NSPoint)point
|
||||||
|
{
|
||||||
|
#warning Missing Implementation
|
||||||
|
return [NSIndexPath indexPathWithIndex:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)indexOfLeadingChild
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)indexOfTrailingChild
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSIndexSet *)indexesOfRemainingChildren
|
||||||
|
{
|
||||||
|
return [NSIndexSet indexSetWithIndex:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSRect)generateBounds
|
||||||
|
{
|
||||||
|
NSRect openingParensBounds = self.transformedOpeningParens.bounds;
|
||||||
|
NSRect closingParensBounds = self.transformedClosingParens.bounds;
|
||||||
|
NSRect bounds = [self childLayoutAtIndex:0].bounds;
|
||||||
|
|
||||||
|
if (openingParensBounds.size.height > bounds.size.height) {
|
||||||
|
bounds.size.height = openingParensBounds.size.height;
|
||||||
|
}
|
||||||
|
if (closingParensBounds.size.height > bounds.size.height) {
|
||||||
|
bounds.size.height = closingParensBounds.size.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds.size.width += MPParenthesisFunctionOpeningParensOffset;
|
||||||
|
bounds.size.width += openingParensBounds.size.width;
|
||||||
|
bounds.size.width += MPParenthesisFunctionClosingParensOffset;
|
||||||
|
bounds.size.width += closingParensBounds.size.width;
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)draw
|
||||||
|
{
|
||||||
|
NSBezierPath *openingParens = self.transformedOpeningParens;
|
||||||
|
MPLayout *expressionLayout = [self childLayoutAtIndex:0];
|
||||||
|
NSBezierPath *closingParens = self.transformedClosingParens;
|
||||||
|
|
||||||
|
CGFloat x = 0;
|
||||||
|
|
||||||
|
[openingParens fill];
|
||||||
|
x += openingParens.bounds.size.width;
|
||||||
|
x += MPParenthesisFunctionOpeningParensOffset;
|
||||||
|
[expressionLayout drawAtPoint:NSMakePoint(x, 0)];
|
||||||
|
x += expressionLayout.bounds.size.width;
|
||||||
|
x += MPParenthesisFunctionClosingParensOffset;
|
||||||
|
|
||||||
|
NSAffineTransform *transform = [NSAffineTransform transform];
|
||||||
|
[transform translateXBy:x
|
||||||
|
yBy:0];
|
||||||
|
[closingParens transformUsingAffineTransform:transform];
|
||||||
|
[closingParens fill];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#import "NSIndexPath+MPAdditions.h"
|
#import "NSIndexPath+MPAdditions.h"
|
||||||
|
|
||||||
#define kSumFunctionStartExpressionOffset 3
|
#define kSumFunctionStartExpressionOffset 0
|
||||||
#define kSumFunctionTargetExpressionOffset 0
|
#define kSumFunctionTargetExpressionOffset 0
|
||||||
#define kSumFunctionSumExpressionOffset 3
|
#define kSumFunctionSumExpressionOffset 3
|
||||||
#define kSumFunctionTrailingOffset 5
|
#define kSumFunctionTrailingOffset 5
|
||||||
@@ -41,10 +41,27 @@
|
|||||||
return [super indexOfChildAfterChildAtIndex:index];
|
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
|
||||||
{
|
{
|
||||||
CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{
|
CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{
|
||||||
return [self createLineForString:@"∑"];
|
return [self createLineForString:@"∑"
|
||||||
|
usingFont:[NSFont fontWithName:@"Times New Roman"
|
||||||
|
size:self.fontSize]];
|
||||||
}];
|
}];
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@@ -52,7 +69,9 @@
|
|||||||
- (NSRect)localLineBounds
|
- (NSRect)localLineBounds
|
||||||
{
|
{
|
||||||
NSRect lineBounds = CTLineGetBoundsWithOptions(self.line, 0);
|
NSRect lineBounds = CTLineGetBoundsWithOptions(self.line, 0);
|
||||||
CGFloat width = MAX(MAX([self childLayoutAtIndex:0].bounds.size.width, [self childLayoutAtIndex:1].bounds.size.width), lineBounds.size.width);
|
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;
|
CGFloat xPosition = (width - lineBounds.size.width) / 2;
|
||||||
return NSMakeRect(xPosition, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height);
|
return NSMakeRect(xPosition, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height);
|
||||||
}
|
}
|
||||||
@@ -65,11 +84,11 @@
|
|||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
// Start Expression
|
// Start Expression
|
||||||
offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2;
|
offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2;
|
||||||
offset.y = -kSumFunctionStartExpressionOffset - childBounds.size.height;
|
offset.y = localLineBounds.origin.y - kSumFunctionStartExpressionOffset - childBounds.size.height - childBounds.origin.y;
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
// Target Expression
|
// Target Expression
|
||||||
offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2;
|
offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2;
|
||||||
offset.y = localLineBounds.size.height + kSumFunctionTargetExpressionOffset;
|
offset.y = kSumFunctionTargetExpressionOffset + localLineBounds.size.height + localLineBounds.origin.y - childBounds.origin.y;
|
||||||
} else {
|
} else {
|
||||||
// Sum Expression
|
// Sum Expression
|
||||||
MPLayout *startExpressionLayout = [self childLayoutAtIndex:0];
|
MPLayout *startExpressionLayout = [self childLayoutAtIndex:0];
|
||||||
@@ -81,23 +100,13 @@
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSIndexPath *)indexPathForMousePoint:(NSPoint)point
|
- (BOOL)childAtIndexUsesSmallSize:(NSUInteger)index
|
||||||
{
|
{
|
||||||
// A single index is used to communicate back wether the
|
return (index == 0 || index == 1) ? YES : self.usesSmallSize;
|
||||||
// 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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSIndexPath *)indexPathForLocalMousePoint:(NSPoint)point
|
||||||
|
{
|
||||||
if (point.x < CTLineGetBoundsWithOptions(self.line, 0).size.width / 2) {
|
if (point.x < CTLineGetBoundsWithOptions(self.line, 0).size.width / 2) {
|
||||||
return [NSIndexPath indexPathWithIndex:0];
|
return [NSIndexPath indexPathWithIndex:0];
|
||||||
} else {
|
} else {
|
||||||
@@ -115,20 +124,30 @@
|
|||||||
|
|
||||||
bounds.size.width = MAX(lineBounds.size.width, startExpressionBounds.size.width);
|
bounds.size.width = MAX(lineBounds.size.width, startExpressionBounds.size.width);
|
||||||
bounds.size.height += startExpressionBounds.size.height + kSumFunctionStartExpressionOffset;
|
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.width = MAX(bounds.size.width, targetExpressionBounds.size.width);
|
||||||
bounds.size.height += targetExpressionBounds.size.height + kSumFunctionTargetExpressionOffset;
|
bounds.size.height += targetExpressionBounds.size.height + kSumFunctionTargetExpressionOffset;
|
||||||
|
|
||||||
bounds.size.width += kSumFunctionSumExpressionOffset + sumExpressionBounds.size.width;
|
bounds.size.width += kSumFunctionSumExpressionOffset + sumExpressionBounds.size.width;
|
||||||
bounds.size.height = MAX(bounds.size.height, sumExpressionBounds.size.height);
|
bounds.size.height = MAX(bounds.size.height, sumExpressionBounds.size.height);
|
||||||
|
|
||||||
bounds.origin.y -= targetExpressionBounds.size.height + kSumFunctionStartExpressionOffset;
|
|
||||||
bounds.size.width += kSumFunctionTrailingOffset;
|
bounds.size.width += kSumFunctionTrailingOffset;
|
||||||
|
|
||||||
|
// The Bounds are a little bigger than the drawn function
|
||||||
|
bounds.size.height += 6;
|
||||||
|
bounds.origin.y -= 3;
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)draw
|
- (void)draw
|
||||||
{
|
{
|
||||||
|
#ifdef MPDEBUG_DRAW_BASELINE
|
||||||
|
[[NSColor redColor] set];
|
||||||
|
NSRectFill(NSMakeRect(0, -1, self.bounds.size.width, 1));
|
||||||
|
[[NSColor textColor] set];
|
||||||
|
#endif
|
||||||
|
|
||||||
// Get the current context
|
// Get the current context
|
||||||
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
||||||
|
|
||||||
@@ -142,25 +161,24 @@
|
|||||||
CGContextSetTextPosition(context, localLineBounds.origin.x, 0);
|
CGContextSetTextPosition(context, localLineBounds.origin.x, 0);
|
||||||
CTLineDraw(line, context);
|
CTLineDraw(line, context);
|
||||||
|
|
||||||
|
#ifdef MPDEBUG_DRAW_FUNCTION_BOUNDS
|
||||||
|
[[NSColor blueColor] set];
|
||||||
|
[[NSBezierPath bezierPathWithRect:localLineBounds] stroke];
|
||||||
|
[[NSColor textColor] set];
|
||||||
|
#endif
|
||||||
|
|
||||||
// Draw the start function
|
// Draw the start function
|
||||||
MPLayout *startExpressionLayout = [self childLayoutAtIndex:0];
|
MPLayout *startExpressionLayout = [self childLayoutAtIndex:0];
|
||||||
NSPoint startExpressionLocation = NSMakePoint(localLineBounds.origin.x + localLineBounds.size.width / 2, 0);
|
NSPoint startExpressionLocation = [self offsetOfChildLayoutAtIndex:0];
|
||||||
startExpressionLocation.x -= startExpressionLayout.bounds.size.width / 2;
|
|
||||||
startExpressionLocation.y -= startExpressionLayout.bounds.size.height + kSumFunctionStartExpressionOffset;
|
|
||||||
[startExpressionLayout drawAtPoint:startExpressionLocation];
|
[startExpressionLayout drawAtPoint:startExpressionLocation];
|
||||||
|
|
||||||
// Draw the target function
|
// Draw the target function
|
||||||
MPLayout *targetExpressionLayout = [self childLayoutAtIndex:1];
|
MPLayout *targetExpressionLayout = [self childLayoutAtIndex:1];
|
||||||
NSPoint targetExpressionLocation = NSMakePoint(localLineBounds.origin.x + localLineBounds.size.width / 2, localLineBounds.size.height);
|
[targetExpressionLayout drawAtPoint:[self offsetOfChildLayoutAtIndex:1]];
|
||||||
targetExpressionLocation.x -= targetExpressionLayout.bounds.size.width / 2;
|
|
||||||
targetExpressionLocation.y += kSumFunctionTargetExpressionOffset;
|
|
||||||
[targetExpressionLayout drawAtPoint:targetExpressionLocation];
|
|
||||||
|
|
||||||
// Draw the sum function
|
// Draw the sum function
|
||||||
MPLayout *sumExpressionLayout = [self childLayoutAtIndex:2];
|
MPLayout *sumExpressionLayout = [self childLayoutAtIndex:2];
|
||||||
CGFloat sumWidth = MAX(MAX(localLineBounds.origin.x + localLineBounds.size.width, startExpressionLayout.bounds.size.width), targetExpressionLayout.bounds.size.width);
|
[sumExpressionLayout drawAtPoint:[self offsetOfChildLayoutAtIndex:2]];
|
||||||
sumWidth += kSumFunctionSumExpressionOffset;
|
|
||||||
[sumExpressionLayout drawAtPoint:NSMakePoint(sumWidth, 0)];
|
|
||||||
|
|
||||||
CFRelease(line);
|
CFRelease(line);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user