API  1.0.0
CPTextStorage.j
Go to the documentation of this file.
1 /*
2  * CPTextStorage.j
3  * AppKit
4  *
5  * Created by Emmanuel Maillard on 27/02/2010.
6  * Copyright Emmanuel Maillard 2010.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 
25 
26 
29 
30 CPTextStorageWillProcessEditingNotification = @"CPTextStorageWillProcessEditingNotification";
31 CPTextStorageDidProcessEditingNotification = @"CPTextStorageDidProcessEditingNotification";
32 
33 @protocol CPTextStorageDelegate <CPObject>
34 
35 - (void)textStorageWillProcessEditing:(CPNotification)aNotification;
36 - (void)textStorageDidProcessEditing:(CPNotification)aNotification;
37 
38 @end
39 
40 
43 
48 {
49  CPColor _foregroundColor;
50  CPFont _font;
51  CPMutableArray _layoutManagers;
52  CPRange _editedRange;
53  id <CPTextStorageDelegate> _delegate @accessors(property=delegate);
54  int _changeInLength;
55  unsigned _editedMask;
56 
57  int _editCount; // {begin,end}Editing counter
58  unsigned _implementedDelegateMethods;
59 }
60 
61 
62 #pragma mark -
63 #pragma mark Init methods
64 
65 - (id)initWithString:(CPString)aString attributes:(CPDictionary)attributes
66 {
67  self = [super initWithString:aString attributes:attributes];
68 
69  if (self)
70  {
71  _layoutManagers = [[CPMutableArray alloc] init];
72  _editedRange = CPMakeRange(CPNotFound, 0);
73  _changeInLength = 0;
74  _editedMask = 0;
75  }
76 
77  return self;
78 }
79 
80 - (id)initWithString:(CPString)aString
81 {
82  return [self initWithString:aString attributes:nil];
83 }
84 
85 - (id)init
86 {
87  return [self initWithString:@"" attributes:nil];
88 }
89 
90 
91 #pragma mark -
92 #pragma mark Delegate methods
93 
94 - (void)setDelegate:(id <CPTextStorageDelegate>)aDelegate
95 {
96  if (_delegate === aDelegate)
97  return;
98 
99  _implementedDelegateMethods = 0;
100  _delegate = aDelegate;
101 
102  if (_delegate)
103  {
104  if ([_delegate respondsToSelector:@selector(textStorageWillProcessEditing:)])
105  _implementedDelegateMethods |= CPTextStorageDelegate_textStorageWillProcessEditing_;
106 
107  if ([_delegate respondsToSelector:@selector(textStorageDidProcessEditing:)])
108  _implementedDelegateMethods |= CPTextStorageDelegate_textStorageDidProcessEditing_;
109  }
110 }
111 
112 
113 #pragma mark -
114 #pragma mark Layout manager methods
115 
116 - (void)addLayoutManager:(CPLayoutManager)aManager
117 {
118  if ([_layoutManagers containsObject:aManager])
119  return
120 
121  [aManager setTextStorage:self];
122  [_layoutManagers addObject:aManager];
123 }
124 
125 - (void)removeLayoutManager:(CPLayoutManager)aManager
126 {
127  if (![_layoutManagers containsObject:aManager])
128  return
129 
130  [aManager setTextStorage:nil];
131  [_layoutManagers removeObject:aManager];
132 }
133 
134 - (void)invalidateAttributesInRange:(CPRange)aRange
135 {
136  /* FIXME: stub */
137 }
138 
139 
140 #pragma mark -
141 #pragma mark Editing methods
142 
143 - (void)processEditing
144 {
145  [self _sendDelegateWillProcessEditingNotification];
147  [self _sendDelegateDidProcessEditingNotification];
148 
149  var c = [_layoutManagers count];
150 
151  for (var i = 0; i < c; i++)
152  {
153  [[_layoutManagers objectAtIndex:i] textStorage:self
154  edited:_editedMask
155  range:_editedRange
156  changeInLength:_changeInLength
157  invalidatedRange:_editedRange];
158  }
159 
160  _editedRange.location = CPNotFound;
161  _editedMask = 0;
162  _changeInLength = 0;
163 }
164 
165 - (void)beginEditing
166 {
167  if (_editCount == 0)
168  _editedRange = CPMakeRange(CPNotFound, 0);
169 
170  _editCount++;
171 }
172 
173 - (void)endEditing
174 {
175  _editCount--;
176 
177  if (_editCount == 0)
178  [self processEditing];
179 }
180 
181 - (void)edited:(unsigned)editedMask range:(CPRange)aRange changeInLength:(int)lengthChange
182 {
183  var copyRange = CPMakeRangeCopy(aRange);
184 
185  if (_editCount == 0) // used outside a beginEditing/endEditing
186  {
187  _editedMask = editedMask;
188  _changeInLength = lengthChange;
189  copyRange.length += lengthChange;
190  _editedRange = copyRange;
191  [self processEditing];
192  }
193  else
194  {
195  _editedMask |= editedMask;
196  _changeInLength += lengthChange;
197  copyRange.length += lengthChange;
198 
199  if (_editedRange.location == CPNotFound)
200  _editedRange = copyRange;
201  else
202  _editedRange = CPUnionRange(_editedRange,copyRange);
203  }
204 }
205 
206 - (void)removeAttribute:(CPString)anAttribute range:(CPRange)aRange
207 {
208  [self beginEditing];
209  [super removeAttribute:anAttribute range:aRange];
210  [self edited:CPTextStorageEditedAttributes range:aRange changeInLength:0];
211  [self endEditing];
212 }
213 
214 - (void)addAttributes:(CPDictionary)aDictionary range:(CPRange)aRange
215 {
216  [self beginEditing];
217  [super addAttributes:aDictionary range:aRange];
218  [self edited:CPTextStorageEditedAttributes range:aRange changeInLength:0];
219  [self endEditing];
220 }
221 
222 - (void)deleteCharactersInRange:(CPRange)aRange
223 {
224  [self beginEditing];
225  [super deleteCharactersInRange:aRange];
226  [self edited:CPTextStorageEditedCharacters range:aRange changeInLength:-aRange.length];
227  [self endEditing];
228 }
229 
230 - (void)replaceCharactersInRange:(CPRange)aRange withString:(CPString)aString
231 {
232  [self beginEditing];
233  [super replaceCharactersInRange:aRange withString:aString];
234  [self edited:CPTextStorageEditedCharacters range:aRange changeInLength:([aString length] - aRange.length)];
235  [self endEditing];
236 }
237 
238 - (void)replaceCharactersInRange:(CPRange)aRange withAttributedString:(CPAttributedString)aString
239 {
240  [self beginEditing];
241  [super replaceCharactersInRange:aRange withAttributedString:aString];
242  [self edited:(CPTextStorageEditedAttributes | CPTextStorageEditedCharacters) range:aRange changeInLength:([aString length] - aRange.length)];
243  [self endEditing];
244 }
245 
246 - (CPAttributedString)attributedSubstringFromRange:(CPRange)aRange
247 {
248  if (!aRange.length)
249  return [CPAttributedString new];
250 
251  return [super attributedSubstringFromRange:aRange];
252 }
253 
254 @end
255 
256 
258 
259 - (void)_sendDelegateWillProcessEditingNotification
260 {
261  if (_implementedDelegateMethods & CPTextStorageDelegate_textStorageWillProcessEditing_)
262  [_delegate textStorageWillProcessEditing:[[CPNotification alloc] initWithName:CPTextStorageWillProcessEditingNotification object:self userInfo:nil]];
263 
264  [[CPNotificationCenter defaultCenter] postNotificationName:CPTextStorageWillProcessEditingNotification object:self];
265 }
266 
267 - (void)_sendDelegateDidProcessEditingNotification
268 {
269  if (_implementedDelegateMethods & CPTextStorageDelegate_textStorageDidProcessEditing_)
270  [_delegate textStorageWillProcessEditing:[[CPNotification alloc] initWithName:CPTextStorageDidProcessEditingNotification object:self userInfo:nil]];
271 
272  [[CPNotificationCenter defaultCenter] postNotificationName:CPTextStorageDidProcessEditingNotification object:self];
273 }
274 
275 @end
276 
277 
279 
280 - (id)initWithCoder:(CPCoder)aCoder
281 {
282  self = [super initWithCoder:aCoder];
283 
284  if (self)
285  {
286 
287  }
288 
289  return self;
290 }
291 
292 - (void)encodeWithCoder:(CPCoder)aCoder
293 {
294  [super encodeWithCoder:aCoder];
295 }
296 
297 @end
298 
300 
304 - (CPColor)foregroundColor
305 {
306  return _foregroundColor;
307 }
308 
312 - (void)setForegroundColor:(CPColor)aValue
313 {
314  _foregroundColor = aValue;
315 }
316 
320 - (CPFont)font
321 {
322  return _font;
323 }
324 
328 - (void)setFont:(CPFont)aValue
329 {
330  _font = aValue;
331 }
332 
336 - (CPMutableArray)layoutManagers
337 {
338  return _layoutManagers;
339 }
340 
344 - (CPRange)editedRange
345 {
346  return _editedRange;
347 }
348 
352 - (int)changeInLength
353 {
354  return _changeInLength;
355 }
356 
360 - (void)setChangeInLength:(int)aValue
361 {
362  _changeInLength = aValue;
363 }
364 
368 - (unsigned)editedMask
369 {
370  return _editedMask;
371 }
372 
376 - (void)setEditedMask:(unsigned)aValue
377 {
378  _editedMask = aValue;
379 }
380 
381 @end
Definition: CPFont.h:2
void invalidateAttributesInRange:(CPRange aRange)
function CPUnionRange(lhsRange, rhsRange)
Definition: CPRange.j:106
id init()
Definition: CALayer.j:126
id delegate()
Definition: CALayer.j:965
void postNotificationName:object:(CPString aNotificationName, [object] id anObject)
void addAttributes:range:(CPDictionary aDictionary, [range] CPRange aRange)
CPAttributedString attributedSubstringFromRange:(CPRange aRange)
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
Definition: CPDictionary.h:2
void edited:range:changeInLength:(unsigned editedMask, [range] CPRange aRange, [changeInLength] int lengthChange)
A mutable character string with attributes.
CPRange editedRange()
id initWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
An immutable string (collection of characters).
Definition: CPString.h:2
CPTextStorageWillProcessEditingNotification
Definition: CPTextStorage.j:30
var CPTextStorageDelegate_textStorageWillProcessEditing_
Definition: CPTextStorage.j:41
CPTextStorageEditedAttributes
Definition: CPTextStorage.j:27
void encodeWithCoder:(CPCoder aCoder)
id< CPTextStorageDelegate > _delegate accessors(property=delegate)
int length()
Definition: CPString.j:186
void removeAttribute:range:(CPString anAttribute, [range] CPRange aRange)
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
id initWithString:attributes:(CPString aString, [attributes] CPDictionary attributes)
var CPTextStorageDelegate_textStorageDidProcessEditing_
Definition: CPTextStorage.j:42
function CPMakeRangeCopy(aRange)
Definition: CPRange.j:48
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
CPNotFound
Definition: CPObjJRuntime.j:62
id initWithCoder:(CPCoder aCoder)
id initWithString:attributes:(CPString aString, [attributes] CPDictionary attributes)
Definition: CPTextStorage.j:65
Sends messages (CPNotification) between objects.
id new()
Definition: CPObject.j:122
void replaceCharactersInRange:withAttributedString:(CPRange aRange, [withAttributedString] CPAttributedString aString)
CPTextStorageDidProcessEditingNotification
Definition: CPTextStorage.j:31
CPTextStorageEditedCharacters
Definition: CPTextStorage.j:28
void replaceCharactersInRange:withString:(CPRange aRange, [withString] CPString aString)
void deleteCharactersInRange:(CPRange aRange)
CPRange function CPMakeRange(location, length)
Definition: CPRange.j:37
id alloc()
Definition: CPObject.j:130