Added MPExpressionLayout, MPFunctionLayout and MPExpressionStorage as Rendering System for Expressions
This commit is contained in:
63
MathPad/MPExpressionLayout.h
Normal file
63
MathPad/MPExpressionLayout.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// MPExpressionLayout.h
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 22.04.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class MPExpressionLayout, MPFunctionLayout, MPExpressionStorage, MPExpression;
|
||||||
|
|
||||||
|
@interface MPExpressionLayout : NSObject {
|
||||||
|
BOOL _valid;
|
||||||
|
NSSize _cachedSize;
|
||||||
|
NSMutableArray *_symbolCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Creation Methods
|
||||||
|
|
||||||
|
// -init not supported
|
||||||
|
- (id)initRootLayoutWithExpressionStorage:(MPExpressionStorage *)expressionStorage;
|
||||||
|
- (id)initWithExpressionPath:(NSIndexPath *)expressionPath
|
||||||
|
parent:(MPFunctionLayout *)parent;
|
||||||
|
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
@property (readonly, nonatomic, weak) MPFunctionLayout *parent;
|
||||||
|
|
||||||
|
@property (readonly, nonatomic, weak) MPExpressionStorage *expressionStorage;
|
||||||
|
@property (readonly, nonatomic, strong) NSIndexPath *expressionPath;
|
||||||
|
|
||||||
|
- (MPExpression *)expression; // Convenience
|
||||||
|
- (NSLayoutManager *)layoutManager;
|
||||||
|
- (NSTextContainer *)textContainer;
|
||||||
|
- (NSTextStorage *)textStorage;
|
||||||
|
|
||||||
|
#pragma mark Cache Methods
|
||||||
|
|
||||||
|
- (void)invalidate;
|
||||||
|
- (void)expressionEditedInRange:(NSRange)range
|
||||||
|
replacementLength:(NSUInteger)length;
|
||||||
|
|
||||||
|
- (BOOL)hasCacheForSymbolAtIndex:(NSUInteger)index;
|
||||||
|
- (MPFunctionLayout *)functionLayoutForFunctionAtIndex:(NSUInteger)index;
|
||||||
|
- (NSSize)cachedSizeForSymbolAtIndex:(NSUInteger)index;
|
||||||
|
- (void)cacheSize:(NSSize)size forSymbolAtIndex:(NSUInteger)index;
|
||||||
|
|
||||||
|
#pragma mark Sizes Calculation Methods
|
||||||
|
|
||||||
|
- (NSSize)sizeForAllSymbols;
|
||||||
|
- (NSSize)sizeForSymbolAtIndex:(NSUInteger)index;
|
||||||
|
- (NSSize)sizeForSymbolsInRange:(NSRange)range;
|
||||||
|
|
||||||
|
#pragma mark Drawing Methods
|
||||||
|
|
||||||
|
- (void)drawSymbolAtIndex:(NSUInteger)index
|
||||||
|
atPoint:(NSPoint)point;
|
||||||
|
- (void)drawSymbolsInRange:(NSRange)range
|
||||||
|
atPoint:(NSPoint)point;
|
||||||
|
- (void)drawAllSymbolsAtPoint:(NSPoint)point;
|
||||||
|
|
||||||
|
@end
|
||||||
209
MathPad/MPExpressionLayout.m
Normal file
209
MathPad/MPExpressionLayout.m
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
//
|
||||||
|
// MPExpressionLayout.m
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 22.04.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPExpressionLayout.h"
|
||||||
|
#import "MPExpressionStorage.h"
|
||||||
|
#import "MPFunctionLayout.h"
|
||||||
|
#import "MPModel.h"
|
||||||
|
|
||||||
|
@implementation MPExpressionLayout
|
||||||
|
|
||||||
|
#pragma mark Creation Methods
|
||||||
|
|
||||||
|
- (instancetype)initRootLayoutWithExpressionStorage:(MPExpressionStorage *)expressionStorage
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_symbolCache = [[NSMutableArray alloc] init];
|
||||||
|
_expressionStorage = expressionStorage;
|
||||||
|
_expressionPath = [[NSIndexPath alloc] init];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithExpressionPath:(NSIndexPath *)expressionPath
|
||||||
|
parent:(MPFunctionLayout *)parent
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_symbolCache = [[NSMutableArray alloc] init];
|
||||||
|
_expressionPath = expressionPath;
|
||||||
|
_parent = parent;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
@synthesize expressionStorage = _expressionStorage;
|
||||||
|
- (MPExpressionStorage *)expressionStorage
|
||||||
|
{
|
||||||
|
if (_expressionStorage) {
|
||||||
|
return _expressionStorage;
|
||||||
|
}
|
||||||
|
return self.parent.expressionStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MPExpression *)expression
|
||||||
|
{
|
||||||
|
return [self.expressionStorage symbolAtIndexPath:self.expressionPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSLayoutManager *)layoutManager
|
||||||
|
{
|
||||||
|
return self.expressionStorage.layoutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTextContainer *)textContainer
|
||||||
|
{
|
||||||
|
return self.expressionStorage.textContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTextStorage *)textStorage
|
||||||
|
{
|
||||||
|
return self.expressionStorage.textStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Cache Methods
|
||||||
|
|
||||||
|
- (void)invalidate
|
||||||
|
{
|
||||||
|
_valid = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)expressionEditedInRange:(NSRange)range replacementLength:(NSUInteger)length
|
||||||
|
{
|
||||||
|
while (_symbolCache.count < self.expression.numberOfSymbols) {
|
||||||
|
[_symbolCache addObject:[NSNull null]];
|
||||||
|
}
|
||||||
|
NSMutableArray *newPlaceholders = [[NSMutableArray alloc] initWithCapacity:length];
|
||||||
|
while (newPlaceholders.count < length) {
|
||||||
|
[newPlaceholders addObject:[NSNull null]];
|
||||||
|
}
|
||||||
|
[_symbolCache replaceObjectsInRange:range withObjectsFromArray:newPlaceholders];
|
||||||
|
_valid = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCacheForSymbolAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
if (index >= _symbolCache.count) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return _symbolCache[index] != [NSNull null];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MPFunctionLayout *)functionLayoutForFunctionAtIndex:(NSUInteger)index;
|
||||||
|
{
|
||||||
|
if ([self hasCacheForSymbolAtIndex:index]) {
|
||||||
|
return _symbolCache[index];
|
||||||
|
}
|
||||||
|
MPFunctionLayout *layout = [MPFunctionLayout functionLayoutForFunctionAtIndexPath:[self.expressionPath indexPathByAddingIndex:index] parent:self];
|
||||||
|
while (index >= _symbolCache.count) {
|
||||||
|
[_symbolCache addObject:[NSNull null]];
|
||||||
|
}
|
||||||
|
_symbolCache[index] = layout;
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSSize)cachedSizeForSymbolAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
id cachedSymbol = _symbolCache[index];
|
||||||
|
if ([cachedSymbol isKindOfClass:[NSValue class]]) {
|
||||||
|
return [cachedSymbol sizeValue];
|
||||||
|
}
|
||||||
|
return [(MPFunctionLayout *)cachedSymbol sizeOfFunction];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cacheSize:(NSSize)size forSymbolAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
while (index >= _symbolCache.count) {
|
||||||
|
[_symbolCache addObject:[NSNull null]];
|
||||||
|
}
|
||||||
|
_symbolCache[index] = [NSValue valueWithSize:size];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Size Calculation Methods
|
||||||
|
|
||||||
|
- (NSSize)sizeForAllSymbols
|
||||||
|
{
|
||||||
|
if (!_valid) {
|
||||||
|
_cachedSize = [self sizeForSymbolsInRange:NSMakeRange(0, self.expression.numberOfSymbols)];
|
||||||
|
_valid = YES;
|
||||||
|
}
|
||||||
|
return _cachedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSSize)sizeForSymbolsInRange:(NSRange)range
|
||||||
|
{
|
||||||
|
NSSize size = NSMakeSize(0, 0);
|
||||||
|
for (NSUInteger index = range.location; index < NSMaxRange(range); index++) {
|
||||||
|
NSSize symbolSize = [self sizeForSymbolAtIndex:index];
|
||||||
|
size.width += symbolSize.width;
|
||||||
|
size.height = MAX(size.height, symbolSize.height);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSSize)sizeForSymbolAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
if ([self hasCacheForSymbolAtIndex:index]) {
|
||||||
|
return [self cachedSizeForSymbolAtIndex:index];
|
||||||
|
}
|
||||||
|
id symbol = [self.expression symbolAtIndex:index];
|
||||||
|
if ([symbol isString]) {
|
||||||
|
[self.textStorage setString:symbol];
|
||||||
|
NSRange glyphRange = [self.layoutManager glyphRangeForTextContainer:self.textContainer];
|
||||||
|
NSSize symbolSize = [self.layoutManager boundingRectForGlyphRange:glyphRange
|
||||||
|
inTextContainer:self.textContainer].size;
|
||||||
|
[self cacheSize:symbolSize
|
||||||
|
forSymbolAtIndex:index];
|
||||||
|
|
||||||
|
return symbolSize;
|
||||||
|
} else {
|
||||||
|
MPFunctionLayout *layout = [self functionLayoutForFunctionAtIndex:index];
|
||||||
|
return [layout sizeOfFunction];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Drawing Methods
|
||||||
|
|
||||||
|
- (void)drawSymbolAtIndex:(NSUInteger)index
|
||||||
|
atPoint:(NSPoint)point
|
||||||
|
{
|
||||||
|
id symbol = [self.expression symbolAtIndex:index];
|
||||||
|
if ([symbol isString]) {
|
||||||
|
[self.textStorage setString:symbol];
|
||||||
|
NSRange glyphRange = [self.layoutManager glyphRangeForTextContainer:self.textContainer];
|
||||||
|
[self.layoutManager drawGlyphsForGlyphRange:glyphRange
|
||||||
|
atPoint:point];
|
||||||
|
} else {
|
||||||
|
MPFunctionLayout *layout = [self functionLayoutForFunctionAtIndex:index];
|
||||||
|
[layout drawFunctionAtPoint:point];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawSymbolsInRange:(NSRange)range
|
||||||
|
atPoint:(NSPoint)point
|
||||||
|
{
|
||||||
|
NSSize overallSize = [self sizeForSymbolsInRange:range];
|
||||||
|
CGFloat x = point.x;
|
||||||
|
for (NSUInteger index = range.location; index < NSMaxRange(range); index++) {
|
||||||
|
NSSize symbolSize = [self sizeForSymbolAtIndex:index];
|
||||||
|
CGFloat dy = (overallSize.height - symbolSize.height) / 2;
|
||||||
|
[self drawSymbolAtIndex:index
|
||||||
|
atPoint:NSMakePoint(x, point.y + dy)];
|
||||||
|
x += symbolSize.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawAllSymbolsAtPoint:(NSPoint)point
|
||||||
|
{
|
||||||
|
[self drawSymbolsInRange:NSMakeRange(0, [self.expression numberOfSymbols]) atPoint:point];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
21
MathPad/MPExpressionStorage.h
Normal file
21
MathPad/MPExpressionStorage.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// MPExpressionStorage.h
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 22.04.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPExpression.h"
|
||||||
|
|
||||||
|
@class MPExpressionStorage, MPExpressionLayout;
|
||||||
|
|
||||||
|
@interface MPExpressionStorage : MPMutableExpression
|
||||||
|
|
||||||
|
@property (nonatomic, strong) MPExpressionLayout *expressionLayout;
|
||||||
|
|
||||||
|
- (NSLayoutManager *)layoutManager;
|
||||||
|
- (NSTextContainer *)textContainer;
|
||||||
|
- (NSTextStorage *)textStorage;
|
||||||
|
|
||||||
|
@end
|
||||||
60
MathPad/MPExpressionStorage.m
Normal file
60
MathPad/MPExpressionStorage.m
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// MPExpressionStorage.m
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 22.04.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPExpressionStorage.h"
|
||||||
|
#import "MPExpressionLayout.h"
|
||||||
|
|
||||||
|
@interface MPExpressionStorage ()
|
||||||
|
@property (nonatomic, strong) NSLayoutManager *layoutManager;
|
||||||
|
@property (nonatomic, strong) NSTextContainer *textContainer;
|
||||||
|
@property (nonatomic, strong) NSTextStorage *textStorage;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MPExpressionStorage
|
||||||
|
|
||||||
|
- (instancetype)initWithSymbols:(NSArray *)symbols
|
||||||
|
{
|
||||||
|
self = [super initWithSymbols:symbols];
|
||||||
|
if (self) {
|
||||||
|
_expressionLayout = [[MPExpressionLayout alloc] initRootLayoutWithExpressionStorage:self];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSLayoutManager *)layoutManager
|
||||||
|
{
|
||||||
|
[self ensureTextSystemObjects];
|
||||||
|
return _layoutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTextContainer *)textContainer
|
||||||
|
{
|
||||||
|
[self ensureTextSystemObjects];
|
||||||
|
return _textContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTextStorage *)textStorage
|
||||||
|
{
|
||||||
|
[self ensureTextSystemObjects];
|
||||||
|
return _textStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)ensureTextSystemObjects
|
||||||
|
{
|
||||||
|
if (_layoutManager == nil || _textContainer == nil || _textStorage == nil) {
|
||||||
|
_textStorage = [[NSTextStorage alloc] init];
|
||||||
|
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
|
||||||
|
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
|
||||||
|
[layoutManager addTextContainer:textContainer];
|
||||||
|
[_textStorage addLayoutManager:layoutManager];
|
||||||
|
_textContainer = textContainer;
|
||||||
|
_layoutManager = layoutManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -6,13 +6,24 @@
|
|||||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// TODO: Undo/Redo + Delegate
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
@class MPExpressionView, MPRange;
|
@class MPExpressionView, MPExpressionStorage, MPExpressionLayout, MPRangePath;
|
||||||
|
|
||||||
@interface MPExpressionView : NSView
|
@interface MPExpressionView : NSView <NSUserInterfaceValidations>
|
||||||
|
|
||||||
|
#pragma mark Creation Methods
|
||||||
|
|
||||||
|
- (id)initWithFrame:(NSRect)frameRect;
|
||||||
|
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
@property (readonly, nonatomic, copy) MPExpressionStorage *expressionStorage;
|
||||||
|
- (MPExpressionLayout *)expressionLayout; // Convenience Method
|
||||||
|
|
||||||
@property (nonatomic, getter = isEditable) BOOL editable;
|
@property (nonatomic, getter = isEditable) BOOL editable;
|
||||||
@property (nonatomic, strong) MPRange *selection;
|
@property (nonatomic, strong) MPRangePath *selection;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,23 +7,73 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "MPExpressionView.h"
|
#import "MPExpressionView.h"
|
||||||
|
#import "MPExpressionLayout.h"
|
||||||
|
#import "MPExpressionStorage.h"
|
||||||
|
|
||||||
|
#import "NSObject+MPStringTest.h"
|
||||||
|
|
||||||
|
#import "MPSumFunction.h"
|
||||||
|
|
||||||
|
@interface MPExpressionView ()
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation MPExpressionView
|
@implementation MPExpressionView
|
||||||
|
|
||||||
|
#pragma mark Creation Methods
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
[self initializeObjects];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(NSRect)frame
|
- (id)initWithFrame:(NSRect)frame
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:frame];
|
self = [super initWithFrame:frame];
|
||||||
if (self) {
|
if (self) {
|
||||||
// Initialization code here.
|
[self initializeObjects];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id)initWithCoder:(NSCoder *)aDecoder
|
||||||
|
{
|
||||||
|
self = [super initWithCoder:aDecoder];
|
||||||
|
if (self) {
|
||||||
|
[self initializeObjects];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initializeObjects
|
||||||
|
{
|
||||||
|
MPExpressionStorage *expressionStorage = [[MPExpressionStorage alloc] initWithSymbols:@[@"12345", [[MPSumFunction alloc] init]]];
|
||||||
|
_expressionStorage = expressionStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
- (MPExpressionLayout *)expressionLayout
|
||||||
|
{
|
||||||
|
return self.expressionStorage.expressionLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Drawing Methods
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)dirtyRect
|
- (void)drawRect:(NSRect)dirtyRect
|
||||||
{
|
{
|
||||||
[super drawRect:dirtyRect];
|
[super drawRect:dirtyRect];
|
||||||
|
[[NSColor whiteColor] set];
|
||||||
// Drawing code here.
|
NSRectFill(self.bounds);
|
||||||
|
[[NSColor blackColor] set];
|
||||||
|
NSSize expressionSize = [self.expressionLayout sizeForAllSymbols];
|
||||||
|
CGFloat y = (self.bounds.size.height - expressionSize.height) / 2;
|
||||||
|
NSLog(@"%f", self.bounds.origin.y);
|
||||||
|
NSPoint point = NSMakePoint(self.bounds.origin.x, self.bounds.origin.y + y);
|
||||||
|
[self.expressionLayout drawAllSymbolsAtPoint:point];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
56
MathPad/MPFunctionLayout.h
Normal file
56
MathPad/MPFunctionLayout.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// MPFunctionLayout.h
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 22.04.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class MPFunctionLayout, MPExpressionLayout, MPExpressionStorage, MPFunction;
|
||||||
|
|
||||||
|
@interface MPFunctionLayout : NSObject {
|
||||||
|
@protected
|
||||||
|
BOOL _valid;
|
||||||
|
NSSize _cachedSize;
|
||||||
|
NSMutableArray *_childCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Creation Methods
|
||||||
|
|
||||||
|
+ (instancetype)functionLayoutForFunctionAtIndexPath:(NSIndexPath *)functionPath
|
||||||
|
parent:(MPExpressionLayout *)parent;
|
||||||
|
|
||||||
|
- (id)initWithFunctionPath:(NSIndexPath *)functionPath
|
||||||
|
parent:(MPExpressionLayout *)parent;
|
||||||
|
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
@property (readonly, nonatomic, weak) MPExpressionLayout *parent;
|
||||||
|
|
||||||
|
@property (readonly, nonatomic, strong) NSIndexPath *functionPath;
|
||||||
|
|
||||||
|
- (MPExpressionStorage *)expressionStorage;
|
||||||
|
- (MPFunction *)function; // Convenience
|
||||||
|
- (NSLayoutManager *)layoutManager;
|
||||||
|
- (NSTextContainer *)textContainer;
|
||||||
|
- (NSTextStorage *)textStorage;
|
||||||
|
|
||||||
|
#pragma mark Cache Methods
|
||||||
|
|
||||||
|
- (void)invalidate;
|
||||||
|
|
||||||
|
- (BOOL)hasCacheForChildAtIndex:(NSUInteger)index;
|
||||||
|
- (MPExpressionLayout *)expressionLayoutForChildAtIndex:(NSUInteger)index;
|
||||||
|
|
||||||
|
#pragma mark Size Calculation Methods
|
||||||
|
|
||||||
|
- (NSSize)sizeOfFunction;
|
||||||
|
- (NSSize)calculateSize;
|
||||||
|
|
||||||
|
#pragma mark Drawing Methods
|
||||||
|
|
||||||
|
- (void)drawFunctionAtPoint:(NSPoint)point;
|
||||||
|
|
||||||
|
@end
|
||||||
121
MathPad/MPFunctionLayout.m
Normal file
121
MathPad/MPFunctionLayout.m
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
//
|
||||||
|
// MPFunctionLayout.m
|
||||||
|
// MathPad
|
||||||
|
//
|
||||||
|
// Created by Kim Wittenburg on 22.04.14.
|
||||||
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPFunctionLayout.h"
|
||||||
|
#import "MPExpressionLayout.h"
|
||||||
|
#import "MPExpressionStorage.h"
|
||||||
|
#import "MPFunction.h"
|
||||||
|
|
||||||
|
#import "MPSumFunction.h"
|
||||||
|
#import "MPSumFunctionLayout.h"
|
||||||
|
|
||||||
|
@implementation MPFunctionLayout
|
||||||
|
|
||||||
|
#pragma mark Creation Methods
|
||||||
|
|
||||||
|
+ (instancetype)functionLayoutForFunctionAtIndexPath:(NSIndexPath *)functionPath
|
||||||
|
parent:(MPExpressionLayout *)parent
|
||||||
|
{
|
||||||
|
MPFunction *function = [parent.expressionStorage symbolAtIndexPath:functionPath];
|
||||||
|
Class class = [function class];
|
||||||
|
if (class == [MPSumFunction class]) {
|
||||||
|
return [[MPSumFunctionLayout alloc] initWithFunctionPath:functionPath parent:parent];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithFunctionPath:(NSIndexPath *)functionPath
|
||||||
|
parent:(MPExpressionLayout *)parent
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_functionPath = functionPath;
|
||||||
|
_parent = parent;
|
||||||
|
_childCache = [[NSMutableArray alloc] init];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Properties
|
||||||
|
|
||||||
|
- (MPExpressionStorage *)expressionStorage
|
||||||
|
{
|
||||||
|
return self.parent.expressionStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MPFunction *)function
|
||||||
|
{
|
||||||
|
return [self.expressionStorage symbolAtIndexPath:self.functionPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSLayoutManager *)layoutManager
|
||||||
|
{
|
||||||
|
return self.expressionStorage.layoutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTextContainer *)textContainer
|
||||||
|
{
|
||||||
|
return self.expressionStorage.textContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSTextStorage *)textStorage
|
||||||
|
{
|
||||||
|
return self.expressionStorage.textStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Cache Methods
|
||||||
|
|
||||||
|
- (void)invalidate
|
||||||
|
{
|
||||||
|
_valid = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasCacheForChildAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
if (index >= _childCache.count) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return _childCache[index] != [NSNull null];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MPExpressionLayout *)expressionLayoutForChildAtIndex:(NSUInteger)index
|
||||||
|
{
|
||||||
|
if ([self hasCacheForChildAtIndex:index]) {
|
||||||
|
return _childCache[index];
|
||||||
|
}
|
||||||
|
while (index >= _childCache.count) {
|
||||||
|
[_childCache addObject:[NSNull null]];
|
||||||
|
}
|
||||||
|
MPExpressionLayout *expressionLayout = [[MPExpressionLayout alloc] initWithExpressionPath:[self.functionPath indexPathByAddingIndex:index] parent:self];
|
||||||
|
_childCache[index] = expressionLayout;
|
||||||
|
return expressionLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Size Calculation Methods
|
||||||
|
|
||||||
|
- (NSSize)sizeOfFunction
|
||||||
|
{
|
||||||
|
if (!_valid) {
|
||||||
|
_cachedSize = [self calculateSize];
|
||||||
|
_valid = YES;
|
||||||
|
}
|
||||||
|
return _cachedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSSize)calculateSize
|
||||||
|
{
|
||||||
|
return NSMakeSize(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark Drawing Methods
|
||||||
|
|
||||||
|
- (void)drawFunctionAtPoint:(NSPoint)point
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
Reference in New Issue
Block a user