- Combined MPExpression and MPMutableExpression - Abstracted children of MPExpression into MPExpressionElement protocol - Abstracted most of MPExpressionLayout and MPFunctionLayout into common superclass MPLayout
126 lines
3.9 KiB
Objective-C
126 lines
3.9 KiB
Objective-C
//
|
|
// MPExpressionLayout.m
|
|
// MathPad
|
|
//
|
|
// Created by Kim Wittenburg on 07.08.14.
|
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
#import "MPExpressionLayout.h"
|
|
#import "MPFunctionLayout.h"
|
|
|
|
@interface MPExpressionLayout (MPPathGeneration)
|
|
|
|
- (NSBezierPath *)bezierPathForChildAtIndex:(NSUInteger)index;
|
|
- (NSBezierPath *)generateBezierPathForString:(NSString *)aString;
|
|
|
|
|
|
@end
|
|
|
|
@implementation MPExpressionLayout (MPPathGeneration)
|
|
|
|
- (NSBezierPath *)bezierPathForChildAtIndex:(NSUInteger)index
|
|
{
|
|
id symbol = [self.expression elementAtIndex:index];
|
|
if ([symbol isString]) {
|
|
return [self cachableObjectForIndex:index
|
|
generator:^id{
|
|
return [self generateBezierPathForString:symbol];
|
|
}];
|
|
} else {
|
|
MPLayout *layout = [self childLayoutAtIndex:index];
|
|
return layout.bezierPath;
|
|
}
|
|
}
|
|
|
|
- (NSBezierPath *)generateBezierPathForString:(NSString *)aString
|
|
{
|
|
NSAttributedString *text = [[NSAttributedString alloc] initWithString:aString
|
|
attributes:@{NSFontAttributeName: [NSFont fontWithName:@"Lucida Grande" size:18.0]}];
|
|
self.textStorage.attributedString = text;
|
|
NSRange glyphRange = [self.layoutManager glyphRangeForTextContainer:self.textContainer];
|
|
NSGlyph glyphs[glyphRange.length+1];
|
|
NSUInteger actualGlyphCount = [self.layoutManager getGlyphs:glyphs
|
|
range:glyphRange];
|
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
|
[path moveToPoint:NSZeroPoint];
|
|
[path appendBezierPathWithGlyphs:glyphs
|
|
count:actualGlyphCount
|
|
inFont:[NSFont fontWithName:@"Lucida Grande" size:18.0]];
|
|
return path;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation MPExpressionLayout
|
|
|
|
# pragma mark Creation Methods
|
|
- (instancetype)initRootLayoutWithExpressionStorage:(MPExpressionStorage *)expressionStorage
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
_expressionStorage = expressionStorage;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
#pragma mark Properties
|
|
@synthesize expressionStorage = _expressionStorage;
|
|
- (MPExpressionStorage *)expressionStorage
|
|
{
|
|
if (_expressionStorage) {
|
|
return _expressionStorage;
|
|
}
|
|
return self.parent.expressionStorage;
|
|
}
|
|
|
|
- (MPExpression *)expression
|
|
{
|
|
return [self.expressionStorage elementAtIndexPath:self.path];
|
|
}
|
|
|
|
#pragma mark Cache Methods
|
|
- (MPLayout *)childLayoutAtIndex:(NSUInteger)index
|
|
{
|
|
id cachedObject = [self cachableObjectForIndex:index generator:^id{
|
|
NSIndexPath *indexPath = [self.path indexPathByAddingIndex:index];
|
|
MPFunctionLayout *layout = [MPFunctionLayout functionLayoutForFunctionAtIndexPath:indexPath
|
|
parent:self];
|
|
return layout;
|
|
}];
|
|
if ([cachedObject isKindOfClass:[NSBezierPath class]]) {
|
|
return nil;
|
|
}
|
|
return cachedObject;
|
|
}
|
|
|
|
- (NSSize)sizeForChildAtIndex:(NSUInteger)index
|
|
{
|
|
id symbol = [self.expression elementAtIndex:index];
|
|
if ([symbol isString]) {
|
|
return [self bezierPathForChildAtIndex:index].bounds.size;
|
|
} else {
|
|
return [self childLayoutAtIndex:index].size;
|
|
}
|
|
}
|
|
|
|
#pragma mark Drawing Methods
|
|
- (NSBezierPath *)generateBezierPath
|
|
{
|
|
NSBezierPath *fullPath = [NSBezierPath bezierPath];
|
|
[fullPath moveToPoint:NSZeroPoint];
|
|
NSUInteger x = 0;
|
|
for (NSInteger index = 0; index < self.expression.numberOfElements; ++index) {
|
|
NSAffineTransform *transform = [NSAffineTransform transform];
|
|
// TODO: Translate by the right amount
|
|
[transform translateXBy:x yBy:0];
|
|
NSBezierPath *path = [self bezierPathForChildAtIndex:index].copy;
|
|
[path transformUsingAffineTransform:transform];
|
|
[fullPath appendBezierPath:path];
|
|
x += path.bounds.size.width;
|
|
}
|
|
return fullPath;
|
|
}
|
|
|
|
@end
|