Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 386 lines (312 sloc) 9.211 kb
dc5be1c Initial check-in.
uli authored
1 //
2 // UKViewListView.m
3 // UKViewListView
4 //
5 // Created by Uli Kusterer on 14.10.06.
720b0e7 @uliwitness Added licensing information to the source files.
authored
6 // Copyright 2006 Uli Kusterer.
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not be
22 // misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
dc5be1c Initial check-in.
uli authored
26 //
27
28 #import "UKViewListView.h"
29 #import "NSView+SetFrameSizePinnedToTopLeft.h"
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
30 #import "UKHelperMacros.h"
31
32
33 #ifndef UKVIEWLISTVIEW_USE_CONSTRAINTS
34 #define UKVIEWLISTVIEW_USE_CONSTRAINTS 0
35 #endif // UKVIEWLISTVIEW_USE_CONSTRAINTS
dc5be1c Initial check-in.
uli authored
36
37
38 @implementation UKViewListView
39
40 - (id)initWithFrame:(NSRect)frame
41 {
42 self = [super initWithFrame:frame];
43 if( self )
44 {
45 // Initialization code here.
46 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(viewFrameDidChange:) name: NSViewFrameDidChangeNotification object: self];
47 interViewSpacing = -1;
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
48 forceToContentHeight = NO;
6b785b9 UKViewListView can animate.
uli authored
49 doAnimateResizing = NO;
dc5be1c Initial check-in.
uli authored
50 }
51 return self;
52 }
53
54
55 - (id)initWithCoder:(NSCoder*)coder
56 {
57 self = [super initWithCoder: coder];
58 if( self )
59 {
60 // Initialization code here.
61 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(viewFrameDidChange:) name: NSViewFrameDidChangeNotification object: self];
62 interViewSpacing = -1;
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
63 forceToContentHeight = NO;
6b785b9 UKViewListView can animate.
uli authored
64 doAnimateResizing = NO;
dc5be1c Initial check-in.
uli authored
65 }
66 return self;
67 }
68
69
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
70 -(void) dealloc
71 {
72 DESTROY_DEALLOC(internalConstraints);
73
74 [super dealloc];
75 }
76
dc5be1c Initial check-in.
uli authored
77
78 -(void) awakeFromNib
79 {
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
80 #if !UKVIEWLISTVIEW_USE_CONSTRAINTS
dc5be1c Initial check-in.
uli authored
81 [self reLayoutViewListViews];
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
82 #endif
dc5be1c Initial check-in.
uli authored
83 }
84
85
86 -(void) drawRect: (NSRect)rect
87 {
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
88 #if 0
89 NSDrawGrayBezel( [self bounds], [self bounds] ); // Debugging only.
90 #endif
dc5be1c Initial check-in.
uli authored
91 }
92
93
94 -(void) didAddSubview: (NSView*)subview
95 {
96 [super didAddSubview: subview];
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
97
98 #if UKVIEWLISTVIEW_USE_CONSTRAINTS
99 [self setNeedsUpdateConstraints: YES];
100 #else
101 [self reLayoutViewListViews];
102 #endif
dc5be1c Initial check-in.
uli authored
103 }
104
105
106 -(void) viewDidMoveToWindow
107 {
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
108 #if UKVIEWLISTVIEW_USE_CONSTRAINTS
109 [self setNeedsUpdateConstraints: YES];
110 #else
dc5be1c Initial check-in.
uli authored
111 [self reLayoutViewListViews];
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
112 #endif
dc5be1c Initial check-in.
uli authored
113 }
114
115
85eaed7 @uliwitness UKViewListView can now also resize the containing window to fit the v…
authored
116 -(void) setResizeWindowAndView: (BOOL)resizeBoth
117 {
118 resizeWindowAndView = resizeBoth;
119 }
120
121
dc5be1c Initial check-in.
uli authored
122 -(void) reLayoutViewListViewsAndAdjustFrame: (BOOL)adjustFrame
123 {
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
124 #if !UKVIEWLISTVIEW_USE_CONSTRAINTS
dc5be1c Initial check-in.
uli authored
125 if( !isInReLayout )
126 {
127 isInReLayout = YES;
85eaed7 @uliwitness UKViewListView can now also resize the containing window to fit the v…
authored
128 [self setHidden: YES];
129
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
130 if( forceToContentHeight && adjustFrame && [self window] )
dc5be1c Initial check-in.
uli authored
131 {
85eaed7 @uliwitness UKViewListView can now also resize the containing window to fit the v…
authored
132 BOOL isContentView = [[self window] contentView] == self;
133 if( isContentView || resizeWindowAndView )
6b785b9 UKViewListView can animate.
uli authored
134 {
135 NSWindow* wd = [self window];
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
136 NSRect oldBox = [wd contentRectForFrameRect: [wd frame]];
137 NSRect newBox = oldBox;
6b785b9 UKViewListView can animate.
uli authored
138 NSSize newSize = [self bestSize];
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
139 NSSize oldSize = [self frame].size;
140
141 // If we're not the content view or not the only view in the window, account for our distance to edges:
142 if( !isContentView )
143 {
144 newSize.width += oldBox.size.width -oldSize.width;
145 newSize.height += oldBox.size.height -oldSize.height;
146 }
147
148 // Calculate new rect, upper-left-relative:
6b785b9 UKViewListView can animate.
uli authored
149 newBox.size.width = newSize.width;
150 newBox.origin.y += newBox.size.height -newSize.height;
151 newBox.size.height = newSize.height;
152 newBox = [wd frameRectForContentRect: newBox];
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
153
154 // Actually change frame:
6b785b9 UKViewListView can animate.
uli authored
155 [wd setFrame: newBox display: YES animate: doAnimateResizing];
156 }
85eaed7 @uliwitness UKViewListView can now also resize the containing window to fit the v…
authored
157
158 if( !isContentView || resizeWindowAndView )
dc5be1c Initial check-in.
uli authored
159 [self setFrameSizePinnedToTopLeft: [self bestSize]];
160 }
161
162 NSRect myBounds = [self bounds];
6b785b9 UKViewListView can animate.
uli authored
163 NSPoint viewPos = NSMakePoint( leftMargin, isFlipped ? topMargin : (NSMaxY( myBounds ) -topMargin) );
dc5be1c Initial check-in.
uli authored
164 NSArray* subs = [[[self subviews] copy] autorelease];
165 NSEnumerator* enny = [subs objectEnumerator];
166 NSView* currSubview = nil;
167
168 while( (currSubview = [enny nextObject]) )
169 {
170 if( ![currSubview isHidden] )
171 {
172 NSRect currViewBox = [currSubview bounds];
6b785b9 UKViewListView can animate.
uli authored
173 if( !isFlipped )
174 viewPos.y -= currViewBox.size.height;
dc5be1c Initial check-in.
uli authored
175 currViewBox.origin = viewPos;
176 currViewBox.size.width = myBounds.size.width -leftMargin -rightMargin;
177 [currSubview setFrame: currViewBox];
6b785b9 UKViewListView can animate.
uli authored
178 if( !isFlipped )
179 viewPos.y -= interViewSpacing;
180 else
181 viewPos.y += currViewBox.size.height +interViewSpacing;
dc5be1c Initial check-in.
uli authored
182 }
183 }
184
185 [self setNeedsDisplay: YES];
85eaed7 @uliwitness UKViewListView can now also resize the containing window to fit the v…
authored
186 [self setHidden: NO];
dc5be1c Initial check-in.
uli authored
187 isInReLayout = NO;
188 }
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
189 #endif
dc5be1c Initial check-in.
uli authored
190 }
191
192
193 -(void) reLayoutViewListViews
194 {
195 [self reLayoutViewListViewsAndAdjustFrame: YES];
196 }
197
6b785b9 UKViewListView can animate.
uli authored
198 -(BOOL) isFlipped
199 {
200 return isFlipped;
201 }
202
203
204 -(void) setIsFlipped: (BOOL)state
205 {
206 isFlipped = state;
207 }
dc5be1c Initial check-in.
uli authored
208
209 -(NSSize) bestSize
210 {
211 NSSize bSiz = NSZeroSize;
212
213 bSiz.width = [self bounds].size.width;
214 bSiz.height = topMargin +bottomMargin;
215
216 NSEnumerator* enny = [[self subviews] objectEnumerator];
217 NSView* currSubview = nil;
218 BOOL isFirst = YES;
219
220 while( (currSubview = [enny nextObject]) )
221 {
222 if( ![currSubview isHidden] )
223 {
224 NSRect currViewBox = [currSubview bounds];
225
226 if( isFirst )
227 isFirst = NO;
228 else
229 bSiz.height += interViewSpacing;
230
231 bSiz.height += currViewBox.size.height;
232 }
233 }
234
235 return bSiz;
236 }
237
238
239 -(void) viewFrameDidChange: (NSNotification*)notif
240 {
241 [self reLayoutViewListViewsAndAdjustFrame: NO];
242 }
243
244
245 -(void) setForceToContentHeight: (BOOL)doForce
246 {
247 forceToContentHeight = doForce;
248 if( doForce )
249 [self reLayoutViewListViews];
250 }
251
252
253 -(BOOL) forceToContentHeight
254 {
255 return forceToContentHeight;
256 }
257
258
259 - (float)leftMargin
260 {
261 return leftMargin;
262 }
263
264 - (void)setLeftMargin:(float)value
265 {
266 if (leftMargin != value)
267 {
268 leftMargin = value;
269 }
270 }
271
272 - (float)rightMargin
273 {
274 return rightMargin;
275 }
276
277 - (void)setRightMargin:(float)value
278 {
279 if (rightMargin != value)
280 {
281 rightMargin = value;
282 }
283 }
284
285 - (float)topMargin
286 {
287 return topMargin;
288 }
289
290 - (void)setTopMargin:(float)value
291 {
292 if (topMargin != value)
293 {
294 topMargin = value;
295 }
296 }
297
298 - (float)bottomMargin
299 {
300 return bottomMargin;
301 }
302
303 - (void)setBottomMargin:(float)value
304 {
305 if (bottomMargin != value)
306 {
307 bottomMargin = value;
308 }
309 }
310
311 - (float)interViewSpacing
312 {
313 return interViewSpacing;
314 }
315
316 - (void)setInterViewSpacing:(float)value
317 {
318 if (interViewSpacing != value)
319 {
320 interViewSpacing = value;
321 }
322 }
323
6b785b9 UKViewListView can animate.
uli authored
324 -(void) setAnimateResizing: (BOOL)animateResizing
325 {
326 doAnimateResizing = animateResizing;
327 }
dc5be1c Initial check-in.
uli authored
328
dd21b35 @uliwitness Make UKViewListView work with AutoLayout.
authored
329
330 #if UKVIEWLISTVIEW_USE_CONSTRAINTS
331 -(void) updateConstraints
332 {
333 if( YES )
334 {
335 [self removeConstraints: self.constraints];
336 if( !internalConstraints )
337 internalConstraints = [[NSMutableArray alloc] init];
338
339 // NSArray *myHConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"|[self]|" options: NSLayoutFormatDirectionLeadingToTrailing metrics: [NSDictionary dictionary] views: NSDictionaryOfVariableBindings(self)];
340 // [self addConstraints: myHConstraints];
341 // NSArray *myVConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"V:|[self]|" options: NSLayoutFormatDirectionLeadingToTrailing metrics: [NSDictionary dictionary] views: NSDictionaryOfVariableBindings(self)];
342 // [self addConstraints: myVConstraints];
343
344 NSView * prevView = nil;
345 NSView * lastView = nil;
346 for( NSView* currSubview in self.subviews )
347 {
348 if( currSubview.isHidden )
349 continue;
350
351 NSArray * hConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"|[currSubview]|" options: NSLayoutFormatDirectionLeadingToTrailing metrics: [NSDictionary dictionary] views: NSDictionaryOfVariableBindings(currSubview)];
352 NSArray * vConstraints = nil;
353 if( prevView )
354 {
355 vConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"V:[prevView][currSubview]" options: NSLayoutFormatDirectionLeadingToTrailing metrics: [NSDictionary dictionary] views: NSDictionaryOfVariableBindings(currSubview,prevView)];
356 }
357 else
358 {
359 vConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"V:|[currSubview]" options: NSLayoutFormatDirectionLeadingToTrailing metrics: [NSDictionary dictionary] views: NSDictionaryOfVariableBindings(currSubview)];
360 }
361 [internalConstraints addObjectsFromArray: hConstraints];
362 [internalConstraints addObjectsFromArray: vConstraints];
363 lastView = prevView = currSubview;
364 }
365
366 if( lastView )
367 {
368 NSArray * vConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"V:[lastView]|" options: NSLayoutFormatDirectionLeadingToTrailing metrics: [NSDictionary dictionary] views: NSDictionaryOfVariableBindings(lastView)];
369 [internalConstraints addObjectsFromArray: vConstraints];
370 }
371
372 [self addConstraints: internalConstraints];
373 }
374
375 [super updateConstraints];
376 }
377 #endif // UKVIEWLISTVIEW_USE_CONSTRAINTS
378
379
380 +(BOOL) requiresConstraintBasedLayout
381 {
382 return YES;
383 }
384
dc5be1c Initial check-in.
uli authored
385 @end
Something went wrong with that request. Please try again.