Archived
1
This repository has been archived on 2022-08-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
mathpad/MathPad/MPExpressionLayout.m
Kim Wittenburg 60760b8b3d Internal Redesign:
- Combined MPExpression and MPMutableExpression
- Abstracted children of MPExpression into MPExpressionElement protocol
- Abstracted most of MPExpressionLayout and MPFunctionLayout into common superclass MPLayout
2014-08-11 13:57:48 +02:00

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