Improved Model
Added Keyboard Selection Support Added Mouse Selection Support Added Keyboard Editing Support Corrected Some Bugs Abstracted the Layout System further Added Functions Button (test)
This commit is contained in:
@@ -9,6 +9,13 @@
|
||||
#import "MPSumFunctionLayout.h"
|
||||
#import "MPSumFunction.h"
|
||||
|
||||
#import "NSIndexPath+MPAdditions.h"
|
||||
|
||||
#define kSumFunctionStartExpressionOffset 3
|
||||
#define kSumFunctionTargetExpressionOffset 0
|
||||
#define kSumFunctionSumExpressionOffset 3
|
||||
#define kSumFunctionTrailingOffset 5
|
||||
|
||||
@implementation MPSumFunctionLayout
|
||||
|
||||
- (MPSumFunction *)sumFunction
|
||||
@@ -21,7 +28,7 @@
|
||||
CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{
|
||||
NSAttributedString *text =
|
||||
[[NSAttributedString alloc] initWithString:@"∑"
|
||||
attributes:@{NSFontAttributeName: [NSFont fontWithName:@"Lucida Grande" size:18.0]}];
|
||||
attributes:@{NSFontAttributeName: self.font}];
|
||||
CFAttributedStringRef attributedString = CFBridgingRetain(text);
|
||||
CTLineRef line = CTLineCreateWithAttributedString(attributedString);
|
||||
CFRelease(attributedString); // TODO: Is this release appropriate
|
||||
@@ -30,31 +37,119 @@
|
||||
return line;
|
||||
}
|
||||
|
||||
- (NSSize)generateSize
|
||||
- (NSRect)localLineBounds
|
||||
{
|
||||
CTLineRef line = [self line];
|
||||
CFRetain(line);
|
||||
CGSize size = CTLineGetBoundsWithOptions(line, /*kCTLineBoundsUseOpticalBounds*/0).size;
|
||||
CFRelease(line);
|
||||
return size;
|
||||
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);
|
||||
CGFloat xPosition = (width - lineBounds.size.width) / 2;
|
||||
return NSMakeRect(xPosition, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height);
|
||||
}
|
||||
|
||||
- (void)drawAtPoint:(NSPoint)point
|
||||
- (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 = -kSumFunctionStartExpressionOffset - childBounds.size.height;
|
||||
} else if (index == 1) {
|
||||
// Target Expression
|
||||
offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2;
|
||||
offset.y = localLineBounds.size.height + kSumFunctionTargetExpressionOffset;
|
||||
} 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;
|
||||
}
|
||||
|
||||
- (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];
|
||||
}
|
||||
}
|
||||
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.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.origin.y -= targetExpressionBounds.size.height + kSumFunctionStartExpressionOffset;
|
||||
bounds.size.width += kSumFunctionTrailingOffset;
|
||||
return bounds;
|
||||
}
|
||||
|
||||
- (void)draw
|
||||
{
|
||||
// Get the current context
|
||||
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
||||
|
||||
|
||||
// Set the text matrix
|
||||
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
|
||||
|
||||
// Get the line of text
|
||||
// Draw the sum symbol
|
||||
CTLineRef line = [self line];
|
||||
CFRetain(line);
|
||||
|
||||
// Draw the line
|
||||
CGContextSetTextPosition(context, point.x, point.y);
|
||||
NSRect localLineBounds = [self localLineBounds];
|
||||
CGContextSetTextPosition(context, localLineBounds.origin.x, 0);
|
||||
CTLineDraw(line, context);
|
||||
|
||||
// Draw the start function
|
||||
MPLayout *startExpressionLayout = [self childLayoutAtIndex:0];
|
||||
NSPoint startExpressionLocation = NSMakePoint(localLineBounds.origin.x + localLineBounds.size.width / 2, 0);
|
||||
startExpressionLocation.x -= startExpressionLayout.bounds.size.width / 2;
|
||||
startExpressionLocation.y -= startExpressionLayout.bounds.size.height + kSumFunctionStartExpressionOffset;
|
||||
[startExpressionLayout drawAtPoint:startExpressionLocation];
|
||||
|
||||
// Draw the target function
|
||||
MPLayout *targetExpressionLayout = [self childLayoutAtIndex:1];
|
||||
NSPoint targetExpressionLocation = NSMakePoint(localLineBounds.origin.x + localLineBounds.size.width / 2, localLineBounds.size.height);
|
||||
targetExpressionLocation.x -= targetExpressionLayout.bounds.size.width / 2;
|
||||
targetExpressionLocation.y += kSumFunctionTargetExpressionOffset;
|
||||
[targetExpressionLayout drawAtPoint:targetExpressionLocation];
|
||||
|
||||
// Draw the sum function
|
||||
MPLayout *sumExpressionLayout = [self childLayoutAtIndex:2];
|
||||
CGFloat sumWidth = MAX(MAX(localLineBounds.origin.x + localLineBounds.size.width, startExpressionLayout.bounds.size.width), targetExpressionLayout.bounds.size.width);
|
||||
sumWidth += kSumFunctionSumExpressionOffset;
|
||||
[sumExpressionLayout drawAtPoint:NSMakePoint(sumWidth, 0)];
|
||||
|
||||
CFRelease(line);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user