-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathETTextTreeBuilder.m
86 lines (82 loc) · 1.89 KB
/
ETTextTreeBuilder.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#import "EtoileText.h"
@interface ETTextTree ()
- (void)recalculateLength;
@end
@interface ETTextTree (Builder)
- (void)replaceLastChildWithText: (id<ETText>)anObject;
@end
@implementation ETTextTree (Builder)
- (void)replaceLastChildWithText: (id<ETText>)anObject
{
if ([children count] > 0)
[children removeLastObject];
[children addObject: anObject];
anObject.parent = self;
[self recalculateLength];
}
@end
@implementation ETTextTreeBuilder
@synthesize textTree;
- (id)init
{
SUPERINIT;
textTypeStack = [NSMutableArray new];
textTree = [ETTextTree new];
insertNode = textTree;
return self;
}
- (void)dealloc
{
[textTypeStack release];
[textTree release];
[super dealloc];
}
- (void)startNodeWithStyle: (id)aStyle
{
[textTypeStack addObject: aStyle];
ETTextFragment *fragment = [ETTextFragment new];
fragment.textType = aStyle;
if ([insertNode isKindOfClass: [ETTextTree class]])
{
[(ETTextTree*)insertNode appendTextFragment: fragment];
}
else
{
ETTextTree *newParent = [ETTextTree new];
ETTextTree *parent = (ETTextTree*)insertNode.parent;
newParent.textType = insertNode.textType;
insertNode.textType = nil;
[newParent appendTextFragment: insertNode];
[newParent appendTextFragment: fragment];
[parent replaceLastChildWithText: newParent];
}
insertNode = fragment;
[fragment release];
}
- (void)endNode
{
if ([textTypeStack count] == 0) { return; }
[textTypeStack removeLastObject];
id textType = [textTypeStack lastObject];
do
{
insertNode = insertNode.parent;
}
while (!((textType == insertNode.textType) ||
[textType isEqual: insertNode.textType]));
}
- (void)appendString: (NSString*)aString
{
if ([insertNode isKindOfClass: [ETTextTree class]])
{
ETTextFragment *fragment =
[[ETTextFragment alloc] initWithString: aString];
[(ETTextTree*)insertNode appendTextFragment: fragment];
[fragment release];
}
else
{
[insertNode appendString: aString];
}
}
@end