98 CPArray _windowControllers;
99 unsigned _untitledDocumentIndex;
101 BOOL _hasUndoManager;
122 _windowControllers = [];
123 _viewControllersForWindowControllers = @{};
125 _hasUndoManager = YES;
161 - (id)initWithContentsOfURL:(
CPURL)anAbsoluteURL ofType:(
CPString)aType delegate:(
id)aDelegate didReadSelector:(
SEL)aDidReadSelector contextInfo:(
id)aContextInfo
186 - (id)initForURL:(
CPURL)anAbsoluteURL withContentsOfURL:(
CPURL)absoluteContentsURL ofType:(
CPString)aType delegate:(
id)aDelegate didReadSelector:(
SEL)aDidReadSelector contextInfo:(
id)aContextInfo
212 reason:"dataOfType:error: must be overridden by the document subclass."];
227 reason:"readFromData:ofType: must be overridden by the document subclass."];
242 - (void)makeWindowControllers
247 - (void)makeViewAndWindowControllers
251 viewController = nil,
252 windowController = nil;
255 if ([viewCibName length])
259 if ([windowCibName length])
263 else if (viewController)
265 var view = [viewController view],
266 viewFrame = [view frame];
268 viewFrame.origin = CGPointMake(50, 50);
275 if (windowController && viewController)
276 [windowController setSupportsMultipleDocuments:YES];
278 if (windowController)
288 - (CPArray)windowControllers
290 return _windowControllers;
300 [_windowControllers addObject:aWindowController];
302 if ([aWindowController document] !==
self)
313 if (aWindowController)
314 [_windowControllers removeObject:aWindowController];
316 if ([aWindowController document] ===
self)
325 - (CPArray)viewControllers
327 return [_viewControllersForWindowControllers allValues];
333 [_viewControllersForWindowControllers setObject:aViewController forKey:[aWindowController
UID]];
335 if ([aWindowController document] ===
self)
341 [_viewControllersForWindowControllers removeObject:aViewController];
346 return [_viewControllersForWindowControllers objectForKey:[aWindowController
UID]];
355 [_windowControllers makeObjectsPerformSelector:@selector(setDocument:) withObject:self];
356 [_windowControllers makeObjectsPerformSelector:@selector(showWindow:) withObject:self];
365 return [_fileURL lastPathComponent];
367 if (!_untitledDocumentIndex)
370 if (_untitledDocumentIndex == 1)
373 return @"Untitled " + _untitledDocumentIndex;
414 - (void)readFromURL:(
CPURL)anAbsoluteURL ofType:(
CPString)aType delegate:(
id)aDelegate didReadSelector:(
SEL)aDidReadSelector contextInfo:(
id)aContextInfo
416 [_readConnection cancel];
421 _readConnection.session = _CPReadSessionMake(aType, aDelegate, aDidReadSelector, aContextInfo);
438 if (_fileURL === aFileURL)
443 [_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
456 - (void)saveToURL:(
CPURL)anAbsoluteURL ofType:(
CPString)aTypeName forSaveOperation:(CPSaveOperationType)aSaveOperation delegate:(
id)aDelegate didSaveSelector:(
SEL)aDidSaveSelector contextInfo:(
id)aContextInfo
459 oldChangeCount = _changeCount;
465 [_writeRequest setHTTPMethod:@"POST"];
467 [_writeRequest setHTTPMethod:@"PUT"];
469 [_writeRequest setHTTPBody:[data rawString]];
471 [_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"];
474 [_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
482 connection.session = _CPSaveSessionMake(anAbsoluteURL, aSaveOperation, oldChangeCount, aDelegate, aDidSaveSelector, aContextInfo, connection);
495 var statusCode = [aResponse statusCode];
498 if (statusCode === 200)
501 var session = aConnection.session;
503 if (aConnection == _readConnection)
507 alert(
"There was an error retrieving the document.");
509 var theDelegate = session.delegate;
511 theDelegate.isa.objj_msgSend3(theDelegate, session.didReadSelector,
self, NO, session.contextInfo);
516 if (statusCode == 409)
520 if (confirm(
"There already exists a file with that name, would you like to overwrite it?"))
522 [_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
530 _changeCount += session.changeCount;
531 [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[
self isDocumentEdited]];
536 var theDelegate = session.delegate;
538 theDelegate.isa.objj_msgSend3(theDelegate, session.didSaveSelector,
self, NO, session.contextInfo);
539 [
self _sendDocumentSavedNotification:NO];
551 var session = aConnection.session,
555 if (aConnection == _readConnection)
559 theDelegate.isa.objj_msgSend3(theDelegate, session.didReadSelector,
self, YES, session.contextInfo);
568 theDelegate.isa.objj_msgSend3(theDelegate, session.didSaveSelector,
self, YES, session.contextInfo);
569 [
self _sendDocumentSavedNotification:YES];
579 var session = aConnection.session,
582 if (_readConnection == aConnection)
583 theDelegate.isa.objj_msgSend3(theDelegate, session.didReadSelector,
self, NO, session.contextInfo);
589 _changeCount += session.changeCount;
590 [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[
self isDocumentEdited]];
595 alert(
"There was an error saving the document.");
597 theDelegate.isa.objj_msgSend3(theDelegate, session.didSaveSelector,
self, NO, session.contextInfo);
598 [
self _sendDocumentSavedNotification:NO];
608 if (_readConnection == aConnection)
609 _readConnection = nil;
616 - (BOOL)isDocumentEdited
618 return _changeCount != 0;
625 - (void)updateChangeCount:(CPDocumentChangeType)aChangeType
637 [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[
self isDocumentEdited]];
663 - (BOOL)hasUndoManager
665 return _hasUndoManager;
672 - (void)setHasUndoManager:(BOOL)aFlag
674 if (_hasUndoManager == aFlag)
677 _hasUndoManager = aFlag;
679 if (!_hasUndoManager)
686 var undoManager = [aNotification
object];
688 if ([undoManager isUndoing] || [undoManager isRedoing])
691 [
self updateChangeCount:CPChangeDone];
697 [
self updateChangeCount:CPChangeUndone];
703 [
self updateChangeCount:CPChangeDone];
717 [defaultCenter removeObserver:self
718 name:CPUndoManagerDidUndoChangeNotification
719 object:_undoManager];
721 [defaultCenter removeObserver:self
722 name:CPUndoManagerDidRedoChangeNotification
723 object:_undoManager];
725 [defaultCenter removeObserver:self
726 name:CPUndoManagerWillCloseUndoGroupNotification
727 object:_undoManager];
730 _undoManager = anUndoManager;
735 [defaultCenter addObserver:self
736 selector:@selector(_undoManagerDidUndoChange:)
737 name:CPUndoManagerDidUndoChangeNotification
738 object:_undoManager];
740 [defaultCenter addObserver:self
741 selector:@selector(_undoManagerDidRedoChange:)
742 name:CPUndoManagerDidRedoChangeNotification
743 object:_undoManager];
745 [defaultCenter addObserver:self
746 selector:@selector(_undoManagerWillCloseGroup:)
747 name:CPUndoManagerWillCloseUndoGroupNotification
748 object:_undoManager];
760 if (_hasUndoManager && !_undoManager)
782 - (void)saveDocument:(
id)aSender
787 - (void)saveDocumentWithDelegate:(
id)delegate didSaveSelector:(
SEL)didSaveSelector contextInfo:(Object)contextInfo
795 [
self saveToURL:_fileURL
ofType:[
self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
798 [
self _saveDocumentAsWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
805 - (void)saveDocumentAs:(
id)aSender
807 [
self _saveDocumentAsWithDelegate:nil didSaveSelector:nil contextInfo:nil];
810 - (void)_saveDocumentAsWithDelegate:(
id)delegate didSaveSelector:(
SEL)didSaveSelector contextInfo:(Object)contextInfo
813 response = [savePanel runModal];
818 var saveURL = [savePanel URL];
824 [
self saveToURL:saveURL ofType:[
self fileType] forSaveOperation:CPSaveAsOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
830 - (void)_sendDocumentSavedNotification:(BOOL)didSave
848 [_windowControllers makeObjectsPerformSelector:@selector(removeDocumentAndCloseIfNecessary:) withObject:self];
852 - (void)shouldCloseWindowController:(
CPWindowController)controller delegate:(
id)delegate shouldCloseSelector:(
SEL)selector contextInfo:(Object)info
854 if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !==
CPNotFound))
857 else if ([
delegate respondsToSelector:selector])
861 - (void)_document:(
CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
863 var theDelegate = context.delegate;
865 if (aDocument ===
self && shouldClose)
868 if (theDelegate != null)
869 theDelegate.isa.objj_msgSend3(theDelegate, context.selector, aDocument, shouldClose, context.context);
872 - (void)canCloseDocumentWithDelegate:(
id)aDelegate shouldCloseSelector:(
SEL)aSelector contextInfo:(Object)context
874 if (![
self isDocumentEdited])
875 return [aDelegate respondsToSelector:aSelector] && aDelegate.isa.objj_msgSend3(aDelegate, aSelector,
self, YES, context);
879 [_canCloseAlert setDelegate:self];
880 [_canCloseAlert setAlertStyle:CPWarningAlertStyle];
881 [_canCloseAlert setTitle:@"Unsaved Document"];
882 [_canCloseAlert setMessageText:@"Do you want to save the changes you've made to the document \"" + ([
self displayName] || [
self fileName]) + "\"?"];
884 [_canCloseAlert addButtonWithTitle:@"Save"];
885 [_canCloseAlert addButtonWithTitle:@"Cancel"];
886 [_canCloseAlert addButtonWithTitle:@"Don't Save"];
888 _canCloseAlert._context = {
delegate:aDelegate, selector:aSelector, context:context};
890 [_canCloseAlert runModal];
893 - (void)alertDidEnd:(
CPAlert)alert returnCode:(
int)returnCode
895 if (alert !== _canCloseAlert)
898 var
delegate = alert._context.delegate,
899 selector = alert._context.selector,
900 context = alert._context.context;
902 if (returnCode === 0)
905 delegate.isa.objj_msgSend3(
delegate, selector,
self, returnCode === 2, context);
907 _canCloseAlert = nil;
912 var _CPReadSessionMake =
function(aType, aDelegate, aDidReadSelector, aContextInfo)
914 return { fileType:aType,
delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo };
917 var _CPSaveSessionMake =
function(anAbsoluteURL, aSaveOperation, aChangeCount, aDelegate, aDidSaveSelector, aContextInfo, aConnection)
919 return { absoluteURL:anAbsoluteURL, saveOperation:aSaveOperation, changeCount:aChangeCount,
delegate:aDelegate, didSaveSelector:aDidSaveSelector, contextInfo:aContextInfo, connection:aConnection };
Used to implement exception handling (creating & raising).
var CPDocumentUntitledCount
void updateChangeCount:(CPDocumentChangeType aChangeType)
void setFileType:(CPString aType)
id sharedDocumentController()
void setUndoManager:(CPUndoManager anUndoManager)
id initWithCibName:bundle:owner:(CPString aCibNameOrNil, [bundle] CPBundle aCibBundleOrNil, [owner] id anOwner)
void saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:(CPURL anAbsoluteURL, [ofType] CPString aTypeName, [forSaveOperation] CPSaveOperationType aSaveOperation, [delegate] id aDelegate, [didSaveSelector] SEL aDidSaveSelector, [contextInfo] id aContextInfo)
void setDocument:(CPDocument aDocument)
A Cappuccino wrapper for any data type.
void postNotificationName:object:(CPString aNotificationName, [object] id anObject)
void raise:reason:(CPString aName, [reason] CPString aReason)
Provides loading of a URL request.
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
void addWindowController:(CPWindowController aWindowController)
void makeViewAndWindowControllers()
void addViewController:forWindowController:(CPViewController aViewController, [forWindowController] CPWindowController aWindowController)
id requestWithURL:(CPURL aURL)
id initWithContentRect:styleMask:(CGRect aContentRect, [styleMask] unsigned aStyleMask)
void setViewController:(CPViewController aViewController)
An immutable string (collection of characters).
id initWithWindowCibName:owner:(CPString aWindowCibName, [owner] id anOwner)
void canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:(id aDelegate, [shouldCloseSelector] SEL aSelector, [contextInfo] Object context)
CPDocumentDidFailToSaveNotification
Protocol agnostic information about a request to a specific URL.
CPDocumentDidSaveNotification
global CPApp CPSaveOperation
CPData dataWithRawString:(CPString aString)
CPData dataOfType:error:(CPString aType, [error]/*{ */CPError/*} */anError)
A notification that can be posted to a CPNotificationCenter.
void setFileURL:(CPURL aFileURL)
Used for encapsulating, presenting, and recovery from errors.
CPChangeReadOtherContents
A general mechanism for user action "undo".
CPURLConnection connectionWithRequest:delegate:(CPURLRequest aRequest, [delegate] id aDelegate)
Sends messages (CPNotification) between objects.
CPDocumentWillSaveNotification
void setNextResponder:(CPResponder aResponder)
void saveDocumentWithDelegate:didSaveSelector:contextInfo:(id delegate, [didSaveSelector] SEL didSaveSelector, [contextInfo] Object contextInfo)
Contains data obtained during a request made with CPURLConnection.
void readFromURL:ofType:delegate:didReadSelector:contextInfo:(CPURL anAbsoluteURL, [ofType] CPString aType, [delegate] id aDelegate, [didReadSelector] SEL aDidReadSelector, [contextInfo] id aContextInfo)
void readFromData:ofType:error:(CPData aData, [ofType] CPString aType, [error] CPError anError)
CPUndoManager undoManager()