API  0.9.10
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  CPTextView _textView;
80  BOOL _inResizing;
81 }
82 
83 
84 #pragma mark -
85 #pragma mark Init methods
86 
87 - (id)initWithContainerSize:(CGSize)aSize
88 {
89  self = [super init];
90 
91  if (self)
92  {
93  _size = aSize;
94  [self _init];
95  }
96 
97  return self;
98 }
99 
100 - (id)init
101 {
102  return [self initWithContainerSize:CPMakeSize(1e7, 1e7)];
103 }
104 
105 - (void)_init
106 {
107  _lineFragmentPadding = 0.0;
108 
109  _layoutManager = [[CPLayoutManager alloc] init];
110  [_layoutManager addTextContainer:self];
111 }
112 
113 #pragma mark -
114 #pragma mark Setter methods
115 
116 - (void)setContainerSize:(CGSize)someSize
117 {
118  var oldSize = _size;
119 
120  _size = CGSizeMakeCopy(someSize);
121 
122  if (oldSize.width != _size.width)
123  {
124  _inResizing = YES;
125  [_layoutManager invalidateLayoutForCharacterRange:CPMakeRange(0, [[_layoutManager textStorage] length])
126  isSoft:NO
127  actualCharacterRange:NULL];
128 
129  [_layoutManager _validateLayoutAndGlyphs];
130  [_textView sizeToFit]; // this is necessary to adopt the height of CPTextView in case of rewrapping
131  _inResizing = NO;
132  }
133 }
134 
135 // Controls whether the receiver adjusts the width of its bounding rectangle when its text view is resized.
136 - (void)setWidthTracksTextView:(BOOL)flag
137 {
138  [_textView setPostsFrameChangedNotifications:flag];
139 
140  if (flag)
141  {
143  selector:@selector(textViewFrameChanged:)
144  name:CPViewFrameDidChangeNotification
145  object:_textView];
146  }
147  else
148  {
150  name:CPViewFrameDidChangeNotification
151  object:_textView];
152  }
153 }
154 
155 - (void)textViewFrameChanged:(CPNotification)aNotification
156 {
157  var newSize = CGSizeMake([_textView frame].size.width, _size.height);
158 
159  [self setContainerSize:newSize];
160 }
161 
162 - (void)setTextView:(CPTextView)aTextView
163 {
164  if (_textView)
165  {
166  [self _removeAllLines];
167  [_textView setTextContainer:nil];
168  }
169 
170  _textView = aTextView;
171 
172  if (_textView)
173  [_textView setTextContainer:self];
174 
175  [_layoutManager textContainerChangedTextView:self];
176 }
177 
178 - (BOOL)containsPoint:(CGPoint)aPoint
179 {
180  return CGRectContainsPoint(CGRectMake(0, 0, _size.width, _size.height), aPoint);
181 }
182 
184 {
185  return YES;
186 }
187 
188 - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect
189  sweepDirection:(CPLineSweepDirection)sweep
190  movementDirection:(CPLineMovementDirection)movement
191  remainingRect:(CGRectPointer)remainingRect
192 {
193  var resultRect = CGRectCreateCopy(proposedRect);
194 
195  if (sweep != CPLineSweepRight || movement != CPLineMovesDown)
196  {
197  CPLog.trace(@"FIXME: unsupported sweep (" + sweep + ") or movement (" + movement + ")");
198  return CGRectMakeZero();
199  }
200 
201  if (resultRect.origin.x + resultRect.size.width > _size.width)
202  resultRect.size.width = _size.width - resultRect.origin.x;
203 
204  if (resultRect.size.width < 0)
205  resultRect = CGRectMakeZero();
206 
207  if (remainingRect)
208  {
209  remainingRect.origin.x = resultRect.origin.x + resultRect.size.width;
210  remainingRect.origin.y = resultRect.origin.y;
211  remainingRect.size.height = resultRect.size.height;
212  remainingRect.size.width = _size.width - (resultRect.origin.x + resultRect.size.width);
213  }
214 
215  return resultRect;
216 }
217 
218 @end
219 
220 
221 var CPTextContainerSizeKey = @"CPTextContainerSizeKey",
222  CPTextContainerLayoutManagerKey = @"CPTextContainerLayoutManagerKey";
223 
225 
226 - (id)initWithCoder:(CPCoder)aCoder
227 {
228  self = [super init];
229 
230  if (self)
231  {
232  [self _init];
233 
234  _size = [aCoder decodeSizeForKey:CPTextContainerSizeKey];
235 
236  _layoutManager = [aCoder decodeObjectForKey:CPTextContainerLayoutManagerKey];
237  [_layoutManager addTextContainer:self];
238  }
239 
240  return self;
241 }
242 
243 - (void)encodeWithCoder:(CPCoder)aCoder
244 {
245  [aCoder encodeSize:_size forKey:CPTextContainerSizeKey];
246  [aCoder encodeObject:_layoutManager forKey:CPTextContainerLayoutManagerKey];
247 }
248 
249 @end
250 
252 
257 {
258  return _lineFragmentPadding;
259 }
260 
264 - (void)setLineFragmentPadding:(float)aValue
265 {
266  _lineFragmentPadding = aValue;
267 }
268 
272 - (CGSize)layoutManager
273 {
274  return _size;
275 }
276 
280 - (void)setLayoutManager:(CGSize)aValue
281 {
282  _size = aValue;
283 }
284 
289 {
290  return _textView;
291 }
292 
296 - (void)setTextView:(CPTextView)aValue
297 {
298  _textView = aValue;
299 }
300 
301 @end
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
BOOL isSimpleRectangularTextContainer()
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
var CPTextContainerSizeKey
CPLineMovesUp
id alloc()
Definition: CPObject.j:130