Archived
1

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:
Kim Wittenburg
2014-08-31 15:41:17 +02:00
parent 9aa4bca234
commit 4a3ea0cede
23 changed files with 885 additions and 262 deletions

View File

@@ -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);
}