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