174 lines
4.2 KiB
Objective-C
174 lines
4.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"
|
|
#import "MPRangePath.h"
|
|
|
|
#import "NSIndexPath+MPAdditions.h"
|
|
|
|
@interface MPLayout ()
|
|
|
|
// Querying and Storing Caches
|
|
- (BOOL)hasCacheForElementAtIndex:(NSUInteger)index;
|
|
- (void)ensureCacheSizeForIndex:(NSUInteger)index;
|
|
|
|
@end
|
|
|
|
@implementation MPLayout {
|
|
NSMutableArray *_cache;
|
|
NSRect _cachedBounds;
|
|
}
|
|
|
|
#pragma mark Creation Methods
|
|
- (id)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
_cache = [[NSMutableArray alloc] init];
|
|
_cachedBounds = NSZeroRect;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithElementAtPath:(NSIndexPath *)path
|
|
inRootExpression:(MPExpression *)rootExpression
|
|
parent:(MPLayout *)parent
|
|
{
|
|
self = [self init];
|
|
if (self) {
|
|
_parent = parent;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
#pragma mark Properties
|
|
- (NSFont *)font
|
|
{
|
|
return self.usesSmallSize ? self.smallFont : self.normalFont;
|
|
}
|
|
|
|
- (CGFloat)fontSize
|
|
{
|
|
return self.usesSmallSize ? self.smallFontSize : self.normalFontSize;
|
|
}
|
|
|
|
- (NSFont *)normalFont
|
|
{
|
|
return [NSFont fontWithName:@"CMU Serif"
|
|
size:self.fontSize];
|
|
}
|
|
|
|
- (CGFloat)normalFontSize
|
|
{
|
|
return 18.0;
|
|
}
|
|
|
|
- (NSFont *)smallFont
|
|
{
|
|
return [NSFont fontWithName:@"CMU Serif"
|
|
size:self.smallFontSize];
|
|
}
|
|
|
|
- (CGFloat)smallFontSize
|
|
{
|
|
return 12.0;
|
|
}
|
|
|
|
#pragma mark Cache Tree
|
|
// Querying and Storing 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 ensureCacheSizeForIndex:index];
|
|
_cache[index] = object;
|
|
return object;
|
|
}
|
|
|
|
- (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
|
|
{
|
|
_cachedBounds = NSZeroRect;
|
|
[self.parent invalidate];
|
|
}
|
|
|
|
#pragma mark Calculation and Drawing Methods
|
|
- (CTLineRef)createLineForString:(NSString *)aString
|
|
{
|
|
NSAttributedString *text = [[NSAttributedString alloc] initWithString:aString
|
|
attributes:@{NSFontAttributeName: self.font}];
|
|
CFAttributedStringRef attributedString = CFBridgingRetain(text);
|
|
CTLineRef line = CTLineCreateWithAttributedString(attributedString);
|
|
CFRelease(attributedString); // TODO: Is this release appropriate?
|
|
return line;
|
|
}
|
|
|
|
- (NSRect)bounds
|
|
{
|
|
if (NSEqualRects(_cachedBounds, NSZeroRect)) {
|
|
_cachedBounds = [self generateBounds];
|
|
}
|
|
return _cachedBounds;
|
|
}
|
|
|
|
- (NSRect)boundingRectForRangePath:(MPRangePath *)rangePath
|
|
{
|
|
if (rangePath.location.length == 1) {
|
|
return [self boundingRectForRange:rangePath.rangeAtLastIndex];
|
|
}
|
|
NSUInteger nextIndex = [rangePath.location indexAtPosition:0];
|
|
NSIndexPath *newLocation = [rangePath.location indexPathByRemovingFirstIndex];
|
|
MPRangePath *newRangePath = [[MPRangePath alloc] initWithLocation:newLocation length:rangePath.length];
|
|
NSRect bounds = [[self childLayoutAtIndex:nextIndex] boundingRectForRangePath:newRangePath];
|
|
NSPoint offset = [self offsetOfChildLayoutAtIndex:nextIndex];
|
|
bounds.origin = NSMakePoint(bounds.origin.x + offset.x, bounds.origin.y + offset.y);
|
|
return bounds;
|
|
}
|
|
|
|
- (void)drawAtPoint:(NSPoint)point
|
|
{
|
|
NSAffineTransform *transform = [NSAffineTransform transform];
|
|
[transform translateXBy:point.x
|
|
yBy:point.y];
|
|
[transform concat];
|
|
[self draw];
|
|
[transform invert];
|
|
[transform concat];
|
|
}
|
|
|
|
@end |