API  1.0.0
CPTextContainer.j
Go to the documentation of this file.
1 /*
2  * CPTextContainer.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  @global
27  @group CPLineSweepDirection
28 */
30 /*
31  @global
32  @group CPLineSweepDirection
33 */
35 /*
36  @global
37  @group CPLineSweepDirection
38 */
40 /*
41  @global
42  @group CPLineSweepDirection
43 */
45 
46 /*
47  @global
48  @group CPLineMovementDirection
49 */
51 /*
52  @global
53  @group CPLineMovementDirection
54 */
56 /*
57  @global
58  @group CPLineMovementDirection
59 */
61 /*
62  @global
63  @group CPLineMovementDirection
64 */
66 /*
67  @global
68  @group CPLineMovementDirection
69 */
71 
75 @implementation CPTextContainer : CPObject
76 {
77  float _lineFragmentPadding;
78  CGSize _size;
79  CPLayoutManager _layoutManager;
80  CPTextView _textView;
81  BOOL _inResizing;
82 }
83 
84 
85 #pragma mark -
86 #pragma mark Init methods
87 
88 - (id)initWithContainerSize:(CGSize)aSize
89 {
90  self = [super init];
91 
92  if (self)
93  {
94  _size = aSize;
95  [self _init];
96  }
97 
98  return self;
99 }
100 
101 - (id)init
102 {
103  return [self initWithContainerSize:CPMakeSize(1e7, 1e7)];
104 }
105 
106 - (void)_init
107 {
108  _lineFragmentPadding = 0.0;
109 
110  _layoutManager = [[CPLayoutManager alloc] init];
111  [_layoutManager addTextContainer:self];
112 }
113 
114 #pragma mark -
115 #pragma mark Setter methods
116 
117 - (void)setContainerSize:(CGSize)someSize
118 {
119  var oldSize = _size;
120 
121  _size = CGSizeMakeCopy(someSize);
122 
123  if (oldSize.width != _size.width)
124  {
125  _inResizing = YES;
126  [_layoutManager invalidateLayoutForCharacterRange:CPMakeRange(0, [[_layoutManager textStorage] length])
127  isSoft:NO
128  actualCharacterRange:NULL];
129 
130  [_layoutManager _validateLayoutAndGlyphs];
131  [_textView sizeToFit]; // this is necessary to adopt the height of CPTextView in case of rewrapping
132  _inResizing = NO;
133  }
134 }
135 
136 // Controls whether the receiver adjusts the width of its bounding rectangle when its text view is resized.
137 - (void)setWidthTracksTextView:(BOOL)flag
138 {
139  [_textView setPostsFrameChangedNotifications:flag];
140 
141  if (flag)
142  {
144  selector:@selector(textViewFrameChanged:)
145  name:CPViewFrameDidChangeNotification
146  object:_textView];
147  }
148  else
149  {
151  name:CPViewFrameDidChangeNotification
152  object:_textView];
153  }
154 }
155 
156 - (void)textViewFrameChanged:(CPNotification)aNotification
157 {
158  var newSize = CGSizeMake([_textView frame].size.width, _size.height);
159 
160  [self setContainerSize:newSize];
161 }
162 
163 - (void)setTextView:(CPTextView)aTextView
164 {
165  if (_textView)
166  [_textView setTextContainer:nil];
167 
168  _textView = aTextView;
169 
170  if (_textView)
171  [_textView setTextContainer:self];
172 
173  [_layoutManager textContainerChangedTextView:self];
174 }
175 
176 - (BOOL)containsPoint:(CGPoint)aPoint
177 {
178  return CGRectContainsPoint(CGRectMake(0, 0, _size.width, _size.height), aPoint);
179 }
180 
181 - (BOOL)isSimpleRectangularTextContainer
182 {
183  return YES;
184 }
185 
186 - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect
187  sweepDirection:(CPLineSweepDirection)sweep
188  movementDirection:(CPLineMovementDirection)movement
189  remainingRect:(CGRectPointer)remainingRect
190 {
191  var resultRect = CGRectCreateCopy(proposedRect);
192 
193  if (sweep != CPLineSweepRight || movement != CPLineMovesDown)
194  {
195  CPLog.trace(@"FIXME: unsupported sweep (" + sweep + ") or movement (" + movement + ")");
196  return CGRectMakeZero();
197  }
198 
199  if (resultRect.origin.x + resultRect.size.width > _size.width)
200  resultRect.size.width = _size.width - resultRect.origin.x;
201 
202  if (resultRect.size.width < 0)
203  resultRect = CGRectMakeZero();
204 
205  if (remainingRect)
206  {
207  remainingRect.origin.x = resultRect.origin.x + resultRect.size.width;
208  remainingRect.origin.y = resultRect.origin.y;
209  remainingRect.size.height = resultRect.size.height;
210  remainingRect.size.width = _size.width - (resultRect.origin.x + resultRect.size.width);
211  }
212 
213  return resultRect;
214 }
215 
216 @end
217 
218 
219 var CPTextContainerSizeKey = @"CPTextContainerSizeKey",
220  CPTextContainerLayoutManagerKey = @"CPTextContainerLayoutManagerKey";
221 
223 
224 - (id)initWithCoder:(CPCoder)aCoder
225 {
226  self = [super init];
227 
228  if (self)
229  {
230  [self _init];
231 
232  _size = [aCoder decodeSizeForKey:CPTextContainerSizeKey];
233 
234  _layoutManager = [aCoder decodeObjectForKey:CPTextContainerLayoutManagerKey];
235  [_layoutManager addTextContainer:self];
236  }
237 
238  return self;
239 }
240 
241 - (void)encodeWithCoder:(CPCoder)aCoder
242 {
243  [aCoder encodeSize:_size forKey:CPTextContainerSizeKey];
244  [aCoder encodeObject:_layoutManager forKey:CPTextContainerLayoutManagerKey];
245 }
246 
247 @end
248 
250 
254 - (float)lineFragmentPadding
255 {
256  return _lineFragmentPadding;
257 }
258 
262 - (void)setLineFragmentPadding:(float)aValue
263 {
264  _lineFragmentPadding = aValue;
265 }
266 
270 - (CGSize)containerSize
271 {
272  return _size;
273 }
274 
278 - (void)setContainerSize:(CGSize)aValue
279 {
280  _size = aValue;
281 }
282 
286 - (CPLayoutManager)layoutManager
287 {
288  return _layoutManager;
289 }
290 
294 - (void)setLayoutManager:(CPLayoutManager)aValue
295 {
296  _layoutManager = aValue;
297 }
298 
302 - (CPTextView)textView
303 {
304  return _textView;
305 }
306 
310 - (void)setTextView:(CPTextView)aValue
311 {
312  _textView = aValue;
313 }
314 
315 @end
id init()
Definition: CALayer.j:126
CGRect frame
CPLineMovesLeft
CPLineDoesntMoves
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
id initWithContainerSize:(CGSize aSize)
CPLineMovesDown
CPNotificationCenter defaultCenter()
CPLineSweepUp
CPLineSweepDown
void setContainerSize:(CGSize someSize)
var CPTextContainerLayoutManagerKey
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
CPLineSweepLeft
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
id init()
Definition: CPObject.j:145
Sends messages (CPNotification) between objects.
CPLineSweepRight
CPLineMovesRight
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
var CPTextContainerSizeKey
CPLineMovesUp
id alloc()
Definition: CPObject.j:130