API  0.9.7
 All Classes Files Functions Variables Macros Groups Pages
CPViewController.j
Go to the documentation of this file.
1 /*
2  * CPViewController.j
3  * AppKit
4  *
5  * Created by Nicholas Small and Francisco Tolmasky.
6  * Copyright 2009, 280 North, Inc.
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 @class CPDocument
26 
27 @global CPApp
28 
29 
30 var CPViewControllerCachedCibs;
31 
65 @implementation CPViewController : CPResponder
66 {
67  CPView _view;
68  BOOL _isLoading;
69  BOOL _isLazy;
70  BOOL _isViewLoaded;
71 
72  id _representedObject;
73  CPString _title;
74 
75  CPString _cibName;
76  CPBundle _cibBundle;
77  CPDictionary _cibExternalNameTable;
78 }
79 
80 + (void)initialize
81 {
82  if (self !== [CPViewController class])
83  return;
84 
85  CPViewControllerCachedCibs = @{};
86 }
87 
91 - (id)init
92 {
93  return [self initWithCibName:nil bundle:nil];
94 }
95 
96 - (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil
97 {
98  return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:nil];
99 }
100 
101 - (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil owner:(id)anOwner
102 {
103  return [self initWithCibName:aCibNameOrNil bundle:aCibBundleOrNil externalNameTable:@{ CPCibOwner: anOwner }];
104 }
105 
119 - (id)initWithCibName:(CPString)aCibNameOrNil bundle:(CPBundle)aCibBundleOrNil externalNameTable:(CPDictionary)anExternalNameTable
120 {
121  self = [super init];
122 
123  if (self)
124  {
125  // Don't load the cib until someone actually requests the view. The user may just be intending to use setView:.
126  _cibName = aCibNameOrNil;
127  _cibBundle = aCibBundleOrNil || [CPBundle mainBundle];
128  _cibExternalNameTable = anExternalNameTable || @{ CPCibOwner: self };
129 
130  _isLoading = NO;
131  _isLazy = NO;
132  }
133 
134  return self;
135 }
136 
153 - (void)loadView
154 {
155  if (_view)
156  return;
157 
158  if (_cibName)
159  {
160  // check if a cib is already cached for the current _cibName
161  var cib = [CPViewControllerCachedCibs objectForKey:_cibName];
162 
163  if (!cib)
164  {
165  // if the cib isn't cached yet : fetch it and cache it
166  cib = [[CPCib alloc] initWithCibNamed:_cibName bundle:_cibBundle];
167  [CPViewControllerCachedCibs setObject:cib forKey:_cibName];
168  }
169 
170  [cib instantiateCibWithExternalNameTable:_cibExternalNameTable];
171  }
172  else
173  _view = [CPView new];
174 }
175 
183 - (CPView)view
184 {
185  if (!_view)
186  {
187  _isLoading = YES;
188 
189  var cibOwner = [_cibExternalNameTable objectForKey:CPCibOwner];
190 
191  if ([cibOwner respondsToSelector:@selector(viewControllerWillLoadCib:)])
192  [cibOwner viewControllerWillLoadCib:self];
193 
194  [self loadView];
195 
196  if (_view === nil && [cibOwner isKindOfClass:[CPDocument class]])
197  [self setView:[cibOwner valueForKey:@"view"]];
198 
199  if (!_view)
200  {
201  var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. Override loadView to load the view manually.", self];
202 
203  [CPException raise:CPInternalInconsistencyException reason:reason];
204  }
205 
206  if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)])
207  [cibOwner viewControllerDidLoadCib:self];
208 
209  _isLoading = NO;
210  [self _viewDidLoad];
211  }
212  else if (_isLazy)
213  {
214  _isLazy = NO;
215  [self _viewDidLoad];
216  }
217 
218  return _view;
219 }
220 
221 - (void)_viewDidLoad
222 {
223  [self willChangeValueForKey:"isViewLoaded"];
224  [self viewDidLoad];
225  _isViewLoaded = YES;
226  [self didChangeValueForKey:"isViewLoaded"];
227 }
228 
237 - (void)viewDidLoad
238 {
239 
240 }
241 
242 
251 - (void)setView:(CPView)aView
252 {
253  var willChangeIsViewLoaded = (_isViewLoaded == NO && aView != nil) || (_isViewLoaded == YES && aView == nil);
254 
255  if (willChangeIsViewLoaded)
256  [self willChangeValueForKey:"isViewLoaded"];
257 
258  _view = aView;
259  _isViewLoaded = aView !== nil;
260 
261  if (willChangeIsViewLoaded)
262  [self didChangeValueForKey:"isViewLoaded"];
263 }
264 
265 - (BOOL)automaticallyNotifiesObserversOfIsViewLoaded
266 {
267  return NO;
268 }
269 
270 @end
271 
272 
273 var CPViewControllerViewKey = @"CPViewControllerViewKey",
274  CPViewControllerTitleKey = @"CPViewControllerTitleKey",
275  CPViewControllerCibNameKey = @"CPViewControllerCibNameKey",
276  CPViewControllerBundleKey = @"CPViewControllerBundleKey";
277 
278 @implementation CPViewController (CPCoding)
279 
285 - (id)initWithCoder:(CPCoder)aCoder
286 {
287  self = [super initWithCoder:aCoder];
288 
289  if (self)
290  {
291  _view = [aCoder decodeObjectForKey:CPViewControllerViewKey];
292  _title = [aCoder decodeObjectForKey:CPViewControllerTitleKey];
293  _cibName = [aCoder decodeObjectForKey:CPViewControllerCibNameKey];
294 
295  var bundlePath = [aCoder decodeObjectForKey:CPViewControllerBundleKey];
296  _cibBundle = bundlePath ? [CPBundle bundleWithPath:bundlePath] : [CPBundle mainBundle];
297 
298  _cibExternalNameTable = @{ CPCibOwner: self };
299  _isLazy = YES;
300  }
301 
302  return self;
303 }
304 
309 - (void)encodeWithCoder:(CPCoder)aCoder
310 {
311  [super encodeWithCoder:aCoder];
312 
313  [aCoder encodeObject:_view forKey:CPViewControllerViewKey];
314  [aCoder encodeObject:_title forKey:CPViewControllerTitleKey];
315  [aCoder encodeObject:_cibName forKey:CPViewControllerCibNameKey];
316  [aCoder encodeObject:[_cibBundle bundlePath] forKey:CPViewControllerBundleKey];
317 }
318 
319 @end
320 
321 @implementation CPViewController (CPSynthesizedAccessors)
322 
326 - (CPView)view
327 {
328  return _view;
329 }
330 
334 - (void)setView:(CPView)aValue
335 {
336  _view = aValue;
337 }
338 
342 - (BOOL)isViewLoaded
343 {
344  return _isViewLoaded;
345 }
346 
350 - (id)representedObject
351 {
352  return _representedObject;
353 }
354 
358 - (void)setRepresentedObject:(id)aValue
359 {
360  _representedObject = aValue;
361 }
362 
366 - (CPString)title
367 {
368  return _title;
369 }
370 
374 - (void)setTitle:(CPString)aValue
375 {
376  _title = aValue;
377 }
378 
382 - (CPString)cibName
383 {
384  return _cibName;
385 }
386 
390 - (CPBundle)cibBundle
391 {
392  return _cibBundle;
393 }
394 
398 - (CPDictionary)cibExternalNameTable
399 {
400  return _cibExternalNameTable;
401 }
402 
403 @end