API 0.9.5
AppKit/CPWindowController.j
Go to the documentation of this file.
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
 All Classes Files Functions Variables Defines