From 20d14d2f8163972b040da02ea2eeef428bfef4fe Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Mon, 14 Sep 2009 00:51:43 -0700 Subject: [PATCH] Added beginnings of tabbed documents support. Reviewed by me. --- AppKit/CPDocument.j | 137 ++++++++++++++++++++++++++++++------ AppKit/CPWindow/CPWindow.j | 14 ++++ AppKit/CPWindowController.j | 77 +++++++++++++++++--- 3 files changed, 197 insertions(+), 31 deletions(-) diff --git a/AppKit/CPDocument.j b/AppKit/CPDocument.j index 32e0bd185..76838a3fa 100644 --- a/AppKit/CPDocument.j +++ b/AppKit/CPDocument.j @@ -24,6 +24,7 @@ @import @import "CPResponder.j" +@import "CPViewController.j" @import "CPWindowController.j" @@ -91,20 +92,22 @@ var CPDocumentUntitledCount = 0; */ @implementation CPDocument : CPResponder { - CPWindow _window; // For outlet purposes. + CPWindow _window; // For outlet purposes. + CPView _view; // For outlet purposes + CPDictionary _viewControllersForWindowControllers; - CPURL _fileURL; - CPString _fileType; - CPArray _windowControllers; - unsigned _untitledDocumentIndex; + CPURL _fileURL; + CPString _fileType; + CPArray _windowControllers; + unsigned _untitledDocumentIndex; - BOOL _hasUndoManager; - CPUndoManager _undoManager; - - int _changeCount; - - CPURLConnection _readConnection; - CPURLRequest _writeRequest; + BOOL _hasUndoManager; + CPUndoManager _undoManager; + + int _changeCount; + + CPURLConnection _readConnection; + CPURLRequest _writeRequest; } /*! @@ -118,10 +121,11 @@ var CPDocumentUntitledCount = 0; if (self) { _windowControllers = []; - + _viewControllersForWindowControllers = [CPDictionary dictionary]; + _hasUndoManager = YES; _changeCount = 0; - + [self setNextResponder:CPApp]; } @@ -161,10 +165,10 @@ var CPDocumentUntitledCount = 0; if (self) { - [self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo]; - [self setFileURL:anAbsoluteURL]; [self setFileType:aType]; + + [self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo]; } return self; @@ -186,10 +190,10 @@ var CPDocumentUntitledCount = 0; if (self) { - [self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo]; - [self setFileURL:anAbsoluteURL]; [self setFileType:aType]; + + [self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo]; } return self; @@ -224,16 +228,68 @@ var CPDocumentUntitledCount = 0; reason:"readFromData:ofType: must be overridden by the document subclass."]; } +- (void)viewControllerWillLoadCib:(CPViewController)aViewController +{ +} + +- (void)viewControllerDidLoadCib:(CPViewController)aViewController +{ +} + +- (CPWindowController)firstEligibleExistingWindowController +{ + return nil; +} + // Creating and managing window controllers /*! Creates the window controller for this document. */ - (void)makeWindowControllers { - var windowCibName = [self windowCibName]; + [self makeViewAndWindowControllers]; +} - if (windowCibName) - [self addWindowController:[[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self]]; +- (void)makeViewAndWindowControllers +{ + var viewCibName = [self viewCibName], + viewController = nil, + windowController = nil; + + // Create our view controller if we have a cib for it. + if ([viewCibName length]) + viewController = [[CPViewController alloc] initWithCibName:viewCibName bundle:nil owner:self]; + + // If we have a view controller, check if we have a free window for it. + if (viewController) + windowController = [self firstEligibleExistingWindowController]; + + // If not, create one. + if (!windowController) + { + var windowCibName = [self windowCibName]; + + // From a cib if we have one. + if ([windowCibName length]) + windowController = [[CPWindowController alloc] initWithWindowCibName:windowCibName owner:self]; + + // If not you get a standard window capable of displaying multiple documents and view + else if (viewController) + { + var view = [viewController view], + theWindow = [[CPWindow alloc] initWithContentRect:[view frame] styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask]; + + [theWindow setSupportsMultipleDocuments:YES]; + + windowController = [[CPWindowController alloc] initWithWindow:theWindow]; + } + } + + if (windowController) + [self addWindowController:windowController]; + + if (viewController) + [self addViewController:viewController forWindowController:windowController]; } /*! @@ -252,7 +308,7 @@ var CPDocumentUntitledCount = 0; - (void)addWindowController:(CPWindowController)aWindowController { [_windowControllers addObject:aWindowController]; - + if ([aWindowController document] !== self) { [aWindowController setNextResponder:self]; @@ -260,12 +316,42 @@ var CPDocumentUntitledCount = 0; } } +- (CPView)view +{ + return _view; +} + +- (CPArray)viewControllers +{ + return [_viewControllersForWindowControllers allObjects]; +} + +- (void)addViewController:(CPViewController)aViewController forWindowController:(CPWindowController)aWindowController +{ + // FIXME: exception if we don't own the window controller? + [_viewControllersForWindowControllers setObject:aViewController forKey:[aWindowController UID]]; + + if ([aWindowController document] === self) + [aWindowController setViewController:aViewController]; +} + +- (void)removeViewController:(CPViewController)aViewController +{ + [_viewControllersForWindowControllers removeObject:aViewController]; +} + +- (CPViewController)viewControllerForWindowController:(CPWindowController)aWindowController +{ + return [_viewControllersForWindowControllers objectForKey:[aWindowController UID]]; +} + // Managing Document Windows /*! Shows all the document's windows. */ - (void)showWindows { + [_windowControllers makeObjectsPerformSelector:@selector(setDocument:) withObject:self]; [_windowControllers makeObjectsPerformSelector:@selector(showWindow:) withObject:self]; } @@ -286,6 +372,11 @@ var CPDocumentUntitledCount = 0; return @"Untitled " + _untitledDocumentIndex; } +- (CPString)viewCibName +{ + return nil; +} + /*! Returns the document's Cib name */ @@ -343,7 +434,7 @@ var CPDocumentUntitledCount = 0; */ - (void)setFileURL:(CPURL)aFileURL { - if (_fileURL == aFileURL) + if (_fileURL === aFileURL) return; _fileURL = aFileURL; diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 00dd41a04..c8e782909 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -248,6 +248,7 @@ var CPWindowSaveImage = nil, BOOL _hasShadow; BOOL _isMovableByWindowBackground; + BOOL _supportsMultipleDocuments; BOOL _isDocumentEdited; BOOL _isDocumentSaving; @@ -441,6 +442,19 @@ CPTexturedBackgroundWindowMask return _CPBorderlessBridgeWindowView; } +- (void)setSupportsMultipleDocuments:(BOOL)shouldSupportMultipleDocuments +{ + shouldSupportMultipleDocuments = !!shouldSupportMultipleDocuments; + + // FIXME: throw exception if window controller already has multiple documents and shouldSupportMultipleDocuments === NO + _supportsMultipleDocuments = shouldSupportMultipleDocuments; +} + +- (BOOL)supportsMultipleDocuments +{ + return _supportsMultipleDocuments; +} + - (void)awakeFromCib { if (_initialFirstResponder) diff --git a/AppKit/CPWindowController.j b/AppKit/CPWindowController.j index 2bbd8bc06..f7779fcaf 100644 --- a/AppKit/CPWindowController.j +++ b/AppKit/CPWindowController.j @@ -41,14 +41,17 @@ */ @implementation CPWindowController : CPResponder { - CPWindow _window; + CPWindow _window; - CPDocument _document; - BOOL _shouldCloseDocument; + CPDocument _document; + BOOL _shouldCloseDocument; - id _cibOwner; - CPString _windowCibName; - CPString _windowCibPath; + id _cibOwner; + CPString _windowCibName; + CPString _windowCibPath; + + CPViewController _viewController; + CPView _viewControllerContainerView; } - (id)init @@ -164,8 +167,8 @@ [self loadWindow]; - if (_window === nil && _document !== nil && _cibOwner === _document) - [self setWindow:[_document valueForKey:@"window"]]; + if (_window === nil && [_cibOwner isKindOfClass:[CPDocument class]]) + [self setWindow:[_cibOwner valueForKey:@"window"]]; [self windowDidLoad]; [_document windowControllerDidLoadCib:self]; @@ -256,9 +259,67 @@ [self setDocumentEdited:[_document isDocumentEdited]]; } + var viewController = [_document viewControllerForWindowController:self]; + + if (viewController) + [self setViewController:viewController]; + [self synchronizeWindowTitleWithDocumentName]; } +- (void)setViewController:(CPViewController)aViewController +{ + var containerView = [self viewControllerContainerView] || [[self window] contentView], + view = [_viewController view], + frame = view ? [view frame] : [containerView bounds]; + + [view removeFromSuperview]; + + _viewController = aViewController; + + view = [_viewController view]; + + if (view) + { + [view setFrame:frame]; + [containerView addSubview:view]; + } +} + +- (void)setViewControllerContainerView:(CPView)aView +{ + _viewControllerContainerView = aView; +} + +- (void)viewControllerContainerView +{ + return _viewControllerContainerView; +} + +- (void)setViewController:(CPViewController)aViewController +{ + var containerView = [self viewControllerContainerView] || [[self window] contentView], + view = [_viewController view], + frame = view ? [view frame] : [containerView bounds]; + + [view removeFromSuperview]; + + _viewController = aViewController; + + view = [_viewController view]; + + if (view) + { + [view setFrame:frame]; + [containerView addSubview:view]; + } +} + +- (CPViewController)viewController +{ + return _viewController; +} + /* @ignore */ - (void)_documentWillSave:(CPNotification)aNotification {