-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSSYTokenField.m
151 lines (132 loc) · 4.41 KB
/
SSYTokenField.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#import "SSYTokenField.h"
#import "SSYTokenFieldCell.h"
/*
@interface RedXView : NSView {
}
@end
@implementation RedXView
- (void)drawRect:(NSRect)rect {
NSRect frame = [self frame] ;
NSBezierPath* bp = [NSBezierPath bezierPathWithRect:frame] ;
[bp moveToPoint:frame.origin] ;
[bp relativeLineToPoint:NSMakePoint(frame.size.width, frame.size.height)] ;
[bp moveToPoint:NSMakePoint(frame.origin.x, frame.origin.y+frame.size.height)] ;
[bp relativeLineToPoint:NSMakePoint(frame.size.width, -frame.size.height)] ;
[self lockFocus] ;
[bp setLineWidth:4.0] ;
[[NSColor redColor] set] ;
[bp stroke] ;
[self unlockFocus] ;
[super drawRect:rect] ;
}
@end
*/
@interface SSYTokenField ()
@end
@implementation SSYTokenField
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect] ;
SSYTokenFieldCell* cell = [[SSYTokenFieldCell alloc] initTextCell:@""] ;
[self setCell:cell] ;
[cell release] ;
return self ;
}
- (void)sizeToOneLine {
NSRect frame = [self frame] ;
[self sizeToFit] ;
CGFloat height = [self frame].size.height ;
[self setFrame:NSMakeRect(
frame.origin.x,
NSMidY(frame) - height/2,
frame.size.width,
height)] ;
}
/*
Bug: The following code does not work, because it never executes, because -setObjectValue:
never executes in this method when invoked by bindings. I think maybe it might work if it was moved in to
SSYTokenFieldCell, whose -setObjectValue: method does execute.
*/
- (void)sizeHeightToFit {
NSArray* allTokens = [self objectValue] ;
NSInteger allTokensCount = [allTokens count] ;
CGFloat availableWidth = [self frame].size.width ;
NSInteger nRows = 1 ;
NSInteger startingToken = 0 ;
NSInteger nTokensInThisRow = 0 ;
NSInteger nTokensPlaced = 0 ;
CGFloat height = 0.0 ;
CGFloat totalHeightWithOneRow = 0.0 ;
CGFloat tokenHeight = 0.0 ;
CGFloat interrowSpace = 2.0 ; // Determined empirically
while (nTokensPlaced < allTokensCount) {
NSRange tokenRange = NSMakeRange(startingToken, nTokensInThisRow + 1) ;
NSArray* currentRowTokens = [allTokens subarrayWithRange:tokenRange] ;
if (!m_objectValueIsOk) {
[self setObjectValue:currentRowTokens] ;
}
[self sizeToFit] ;
if (totalHeightWithOneRow == 0.0) {
totalHeightWithOneRow = [self frame].size.height ;
tokenHeight = totalHeightWithOneRow - interrowSpace ;
// Initial height: one token, plus space above, plus space below
height = (tokenHeight + 2 * interrowSpace) ;
}
CGFloat requiredWidth = [self frame].size.width ;
if (requiredWidth > availableWidth) {
nRows++ ;
if (nRows == 1) {
// This would only happen if the first token by itself was too wide
// to fit in a row, which would be very rare
height += (tokenHeight + 2 * interrowSpace) ;
}
else {
height += (tokenHeight + interrowSpace) ;
}
// Bug fix contributed by francesco-romano, 2012-07-07, supposedly
// to keep this from becoming an infinite loop if token's required
// width is larger than the availableWidth
if (!nTokensInThisRow) {
// This happens if one tag is too long to be added in one row,
// so we want to add a row with a lone tag. It will be
// truncated by the NSTokenField. We now increase the height of
// the field.
height += (tokenHeight + interrowSpace) ;
// The above counts another row for the too-long tag
// We now count a fake row with one tag
nRows++;
nTokensInThisRow = 1;
nTokensPlaced++;
}
startingToken = startingToken + nTokensInThisRow ;
nTokensInThisRow = 0 ;
}
else {
nTokensInThisRow++ ;
nTokensPlaced++ ;
}
}
[self setFrame:NSMakeRect(
[self frame].origin.x,
[self frame].origin.y,
availableWidth,
height
)] ;
// Restore all tokens
if (!m_objectValueIsOk) {
[self setObjectValue:allTokens] ;
}
}
- (void)setTokenizingCharacter:(unichar)tchar {
// NSTokenFieldCell raises an exception if you set tokenizing
// character set to {0}. I've seen this happen in BookMacster
// when a document is closing. I'm not sure if it's due to
// some other bug, but as defensive programming…
if (tchar == 0) {
return ;
}
[[self cell] setTokenizingCharacter:tchar] ;
}
- (unichar)tokenizingCharacter {
return [[self cell] tokenizingCharacter] ;
}
@end