![]() |
API 0.9.5
|
00001 /* 00002 * CPWindowController.j 00003 * AppKit 00004 * 00005 * Created by Francisco Tolmasky. 00006 * Copyright 2008, 280 North, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 00025 00040 @implementation CPWindowController : CPResponder 00041 { 00042 CPWindow _window; 00043 00044 CPArray _documents; 00045 CPDocument _document; 00046 BOOL _shouldCloseDocument; 00047 BOOL _supportsMultipleDocuments; 00048 00049 id _cibOwner; 00050 CPString _windowCibName; 00051 CPString _windowCibPath; 00052 00053 CPViewController _viewController; 00054 CPView _viewControllerContainerView; 00055 } 00056 00057 - (id)init 00058 { 00059 return [self initWithWindow:nil]; 00060 } 00061 00067 - (id)initWithWindow:(CPWindow)aWindow 00068 { 00069 self = [super init]; 00070 00071 if (self) 00072 { 00073 [self setWindow:aWindow]; 00074 [self setShouldCloseDocument:NO]; 00075 00076 [self setNextResponder:CPApp]; 00077 00078 _documents = []; 00079 } 00080 00081 return self; 00082 } 00083 00089 - (id)initWithWindowCibName:(CPString)aWindowCibName 00090 { 00091 return [self initWithWindowCibName:aWindowCibName owner:self]; 00092 } 00093 00100 - (id)initWithWindowCibName:(CPString)aWindowCibName owner:(id)anOwner 00101 { 00102 self = [self initWithWindow:nil]; 00103 00104 if (self) 00105 { 00106 _cibOwner = anOwner; 00107 _windowCibName = aWindowCibName; 00108 } 00109 00110 return self; 00111 } 00112 00113 - (id)initWithWindowCibPath:(CPString)aWindowCibPath owner:(id)anOwner 00114 { 00115 self = [self initWithWindow:nil]; 00116 00117 if (self) 00118 { 00119 _cibOwner = anOwner; 00120 _windowCibPath = aWindowCibPath; 00121 } 00122 00123 return self; 00124 } 00125 00130 - (void)loadWindow 00131 { 00132 if (_window) 00133 return; 00134 00135 [[CPBundle mainBundle] loadCibFile:[self windowCibPath] externalNameTable:[CPDictionary dictionaryWithObject:_cibOwner forKey:CPCibOwner]]; 00136 } 00137 00142 - (@action)showWindow:(id)aSender 00143 { 00144 var theWindow = [self window]; 00145 00146 if ([theWindow respondsToSelector:@selector(becomesKeyOnlyIfNeeded)] && [theWindow becomesKeyOnlyIfNeeded]) 00147 [theWindow orderFront:aSender]; 00148 else 00149 [theWindow makeKeyAndOrderFront:aSender]; 00150 } 00151 00156 - (BOOL)isWindowLoaded 00157 { 00158 return _window !== nil; 00159 } 00160 00165 - (CPWindow)window 00166 { 00167 if (!_window) 00168 { 00169 [self windowWillLoad]; 00170 [_document windowControllerWillLoadCib:self]; 00171 00172 [self loadWindow]; 00173 00174 if (_window === nil && [_cibOwner isKindOfClass:[CPDocument class]]) 00175 [self setWindow:[_cibOwner valueForKey:@"window"]]; 00176 00177 if (!_window) 00178 { 00179 var reason = [CPString stringWithFormat:@"Window for %@ could not be loaded from Cib or no window specified. \ 00180 Override loadWindow to load the window manually.", self]; 00181 00182 [CPException raise:CPInternalInconsistencyException reason:reason]; 00183 } 00184 00185 [self windowDidLoad]; 00186 [_document windowControllerDidLoadCib:self]; 00187 00188 [self synchronizeWindowTitleWithDocumentName]; 00189 } 00190 00191 return _window; 00192 } 00193 00198 - (void)setWindow:(CPWindow)aWindow 00199 { 00200 [_window setWindowController:nil]; 00201 00202 _window = aWindow; 00203 00204 [_window setWindowController:self]; 00205 [_window setNextResponder:self]; 00206 } 00207 00211 - (void)windowDidLoad 00212 { 00213 } 00214 00218 - (void)windowWillLoad 00219 { 00220 } 00221 00226 - (void)setDocument:(CPDocument)aDocument 00227 { 00228 if (_document === aDocument) 00229 return; 00230 00231 var defaultCenter = [CPNotificationCenter defaultCenter]; 00232 00233 if (_document) 00234 { 00235 if (![self supportsMultipleDocuments]) 00236 [self removeDocument:_document]; 00237 00238 [defaultCenter removeObserver:self 00239 name:CPDocumentWillSaveNotification 00240 object:_document]; 00241 00242 [defaultCenter removeObserver:self 00243 name:CPDocumentDidSaveNotification 00244 object:_document]; 00245 00246 [defaultCenter removeObserver:self 00247 name:CPDocumentDidFailToSaveNotification 00248 object:_document]; 00249 } 00250 00251 _document = aDocument; 00252 00253 if (_document) 00254 { 00255 [self addDocument:_document]; 00256 00257 [defaultCenter addObserver:self 00258 selector:@selector(_documentWillSave:) 00259 name:CPDocumentWillSaveNotification 00260 object:_document]; 00261 00262 [defaultCenter addObserver:self 00263 selector:@selector(_documentDidSave:) 00264 name:CPDocumentDidSaveNotification 00265 object:_document]; 00266 00267 [defaultCenter addObserver:self 00268 selector:@selector(_documentDidFailToSave:) 00269 name:CPDocumentDidFailToSaveNotification 00270 object:_document]; 00271 00272 [self setDocumentEdited:[_document isDocumentEdited]]; 00273 } 00274 00275 var viewController = [_document viewControllerForWindowController:self]; 00276 00277 if (viewController) 00278 [self setViewController:viewController]; 00279 00280 [self synchronizeWindowTitleWithDocumentName]; 00281 00282 // Change of document means toolbar items may no longer make sense. 00283 // FIXME: DOCUMENT ARCHITECTURE Should we setToolbar: as well? 00284 [[[self window] toolbar] validateVisibleItems]; 00285 } 00286 00287 - (void)setSupportsMultipleDocuments:(BOOL)shouldSupportMultipleDocuments 00288 { 00289 _supportsMultipleDocuments = shouldSupportMultipleDocuments; 00290 } 00291 00292 - (BOOL)supportsMultipleDocuments 00293 { 00294 return _supportsMultipleDocuments; 00295 } 00296 00297 - (void)addDocument:(CPDocument)aDocument 00298 { 00299 if (aDocument && ![_documents containsObject:aDocument]) 00300 [_documents addObject:aDocument]; 00301 } 00302 00303 - (void)removeDocument:(CPDocument)aDocument 00304 { 00305 var index = [_documents indexOfObjectIdenticalTo:aDocument]; 00306 00307 if (index === CPNotFound) 00308 return; 00309 00310 [_documents removeObjectAtIndex:index]; 00311 00312 if (_document === aDocument && [_documents count]) 00313 [self setDocument:[_documents objectAtIndex:MIN(index, [_documents count] - 1)]]; 00314 } 00315 00316 - (void)removeDocumentAndCloseIfNecessary:(CPDocument)aDocument 00317 { 00318 [self removeDocument:aDocument]; 00319 00320 if (![_documents count]) 00321 [self close]; 00322 } 00323 00324 - (CPArray)documents 00325 { 00326 return _documents; 00327 } 00328 00329 - (void)setViewControllerContainerView:(CPView)aView 00330 { 00331 _viewControllerContainerView = aView; 00332 } 00333 00334 - (void)viewControllerContainerView 00335 { 00336 return _viewControllerContainerView; 00337 } 00338 00339 - (void)setViewController:(CPViewController)aViewController 00340 { 00341 var containerView = [self viewControllerContainerView] || [[self window] contentView], 00342 view = [_viewController view], 00343 frame = view ? [view frame] : [containerView bounds]; 00344 00345 [view removeFromSuperview]; 00346 00347 _viewController = aViewController; 00348 00349 view = [_viewController view]; 00350 00351 if (view) 00352 { 00353 [view setFrame:frame]; 00354 [containerView addSubview:view]; 00355 } 00356 } 00357 00358 - (CPViewController)viewController 00359 { 00360 return _viewController; 00361 } 00362 00363 /* @ignore */ 00364 - (void)_documentWillSave:(CPNotification)aNotification 00365 { 00366 [[self window] setDocumentSaving:YES]; 00367 } 00368 00369 /* @ignore */ 00370 - (void)_documentDidSave:(CPNotification)aNotification 00371 { 00372 [[self window] setDocumentSaving:NO]; 00373 } 00374 00375 /* @ignore */ 00376 - (void)_documentDidFailToSave:(CPNotification)aNotification 00377 { 00378 [[self window] setDocumentSaving:NO]; 00379 } 00380 00384 - (CPDocument)document 00385 { 00386 return _document; 00387 } 00388 00393 - (void)setDocumentEdited:(BOOL)isEdited 00394 { 00395 [[self window] setDocumentEdited:isEdited]; 00396 } 00397 00398 - (void)close 00399 { 00400 [[self window] close]; 00401 } 00402 00403 - (void)setShouldCloseDocument:(BOOL)shouldCloseDocument 00404 { 00405 _shouldCloseDocument = shouldCloseDocument; 00406 } 00407 00408 - (BOOL)shouldCloseDocument 00409 { 00410 return _shouldCloseDocument; 00411 } 00412 00413 - (id)owner 00414 { 00415 return _cibOwner; 00416 } 00417 00418 - (CPString)windowCibName 00419 { 00420 if (_windowCibName) 00421 return _windowCibName; 00422 00423 return [[_windowCibPath lastPathComponent] stringByDeletingPathExtension]; 00424 } 00425 00426 - (CPString)windowCibPath 00427 { 00428 if (_windowCibPath) 00429 return _windowCibPath; 00430 00431 return [[CPBundle mainBundle] pathForResource:_windowCibName + @".cib"]; 00432 } 00433 00434 // Setting and Getting Window Attributes 00435 00439 - (void)synchronizeWindowTitleWithDocumentName 00440 { 00441 if (!_document || !_window) 00442 return; 00443 00444 // [_window setRepresentedFilename:]; 00445 [_window setTitle:[self windowTitleForDocumentDisplayName:[_document displayName]]]; 00446 } 00447 00452 - (CPString)windowTitleForDocumentDisplayName:(CPString)aDisplayName 00453 { 00454 return aDisplayName; 00455 } 00456 00457 @end