- Combined MPExpression and MPMutableExpression - Abstracted children of MPExpression into MPExpressionElement protocol - Abstracted most of MPExpressionLayout and MPFunctionLayout into common superclass MPLayout
160 lines
3.2 KiB
Objective-C
160 lines
3.2 KiB
Objective-C
//
|
|
// MPLayout.m
|
|
// MathPad
|
|
//
|
|
// Created by Kim Wittenburg on 11.08.14.
|
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
#import "MPLayout.h"
|
|
|
|
@interface MPLayout ()
|
|
|
|
// Querying Caches
|
|
- (BOOL)hasCacheForElementAtIndex:(NSUInteger)index;
|
|
|
|
// Storing Caches
|
|
- (void)cacheObject:(id)anObject
|
|
forElementAtIndex:(NSUInteger)index;
|
|
- (void)ensureCacheSizeForIndex:(NSUInteger)index;
|
|
|
|
@end
|
|
|
|
@implementation MPLayout {
|
|
NSMutableArray *_cache;
|
|
NSBezierPath *_cachedPath;
|
|
}
|
|
|
|
#pragma mark Creation Methods
|
|
- (id)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
_cache = [[NSMutableArray alloc] init];
|
|
_cachedPath = nil;
|
|
_path = [[NSIndexPath alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id)initWithPath:(NSIndexPath *)path
|
|
parent:(MPLayout *)parent
|
|
{
|
|
self = [self init];
|
|
if (self) {
|
|
_path = path;
|
|
_parent = parent;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
#pragma Text System Objects
|
|
- (MPExpressionStorage *)expressionStorage
|
|
{
|
|
return self.parent.expressionStorage;
|
|
}
|
|
|
|
- (NSLayoutManager *)layoutManager
|
|
{
|
|
return self.expressionStorage.layoutManager;
|
|
}
|
|
|
|
- (NSTextContainer *)textContainer
|
|
{
|
|
return self.expressionStorage.textContainer;
|
|
}
|
|
|
|
- (NSTextStorage *)textStorage
|
|
{
|
|
return self.expressionStorage.textStorage;
|
|
}
|
|
|
|
#pragma mark Cache Tree
|
|
// Querying Caches
|
|
- (BOOL)hasCacheForElementAtIndex:(NSUInteger)index
|
|
{
|
|
if (index >= _cache.count) {
|
|
return NO;
|
|
}
|
|
return _cache[index] != MPNull;
|
|
}
|
|
|
|
- (id)cachableObjectForIndex:(NSUInteger)index
|
|
generator:(id (^)())generator
|
|
{
|
|
if ([self hasCacheForElementAtIndex:index]) {
|
|
return _cache[index];
|
|
}
|
|
id object = generator();
|
|
[self cacheObject:object
|
|
forElementAtIndex:index];
|
|
return object;
|
|
}
|
|
|
|
// Storing Caches
|
|
- (void)cacheObject:(id)anObject
|
|
forElementAtIndex:(NSUInteger)index
|
|
{
|
|
[self ensureCacheSizeForIndex:index];
|
|
_cache[index] = anObject;
|
|
}
|
|
|
|
- (void)ensureCacheSizeForIndex:(NSUInteger)index
|
|
{
|
|
while (index >= _cache.count) {
|
|
[_cache addObject:MPNull];
|
|
}
|
|
}
|
|
|
|
// Clearing Caches
|
|
- (void)clearCacheInRange:(NSRange)range
|
|
replacementLength:(NSUInteger)replacementLength
|
|
{
|
|
NSMutableArray *placeholders = [[NSMutableArray alloc] initWithCapacity:replacementLength];
|
|
while (placeholders.count < replacementLength) {
|
|
[placeholders addObject:MPNull];
|
|
}
|
|
[_cache replaceObjectsInRange:range
|
|
withObjectsFromArray:placeholders];
|
|
[self invalidate];
|
|
}
|
|
|
|
- (void)invalidate
|
|
{
|
|
_cachedPath = nil;
|
|
[self.parent invalidate];
|
|
}
|
|
|
|
#pragma mark Calculation Methods
|
|
- (NSSize)size
|
|
{
|
|
return self.bezierPath.bounds.size;
|
|
}
|
|
|
|
- (NSBezierPath *)bezierPath
|
|
{
|
|
if (!_cachedPath) {
|
|
_cachedPath = [self generateBezierPath];
|
|
}
|
|
return _cachedPath;
|
|
}
|
|
|
|
- (NSBezierPath *)bezierPathAtOrigin:(NSPoint)point
|
|
{
|
|
NSAffineTransform *transform = [NSAffineTransform transform];
|
|
[transform translateXBy:point.x
|
|
yBy:point.y];
|
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
|
[path appendBezierPath:self.bezierPath];
|
|
[path transformUsingAffineTransform:transform];
|
|
return path;
|
|
}
|
|
|
|
- (void)drawAtPoint:(NSPoint)point
|
|
{
|
|
NSBezierPath *path = [self bezierPathAtOrigin:point];
|
|
[path fill];
|
|
}
|
|
|
|
@end
|