39 CPSaveAsOperation = 1;
44 CPSaveToOperation = 2;
49 CPAutosaveOperation = 3;
70 CPChangeReadOtherContents = 3;
75 CPChangeAutosaved = 4;
77 CPDocumentWillSaveNotification =
@"CPDocumentWillSaveNotification";
78 CPDocumentDidSaveNotification =
@"CPDocumentDidSaveNotification";
79 CPDocumentDidFailToSaveNotification =
@"CPDocumentDidFailToSaveNotification";
81 var CPDocumentUntitledCount = 0;
100 CPArray _windowControllers;
101 unsigned _untitledDocumentIndex;
103 BOOL _hasUndoManager;
124 _windowControllers = [];
125 _viewControllersForWindowControllers = @{};
127 _hasUndoManager = YES;
130 [
self setNextResponder:CPApp];
147 [
self setFileType:aType];
163 - (id)initWithContentsOfURL:(
CPURL)anAbsoluteURL ofType:(
CPString)aType delegate:(
id)aDelegate didReadSelector:(
SEL)aDidReadSelector contextInfo:(
id)aContextInfo
169 [
self setFileURL:anAbsoluteURL];
170 [
self setFileType:aType];
172 [
self readFromURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
188 - (id)initForURL:(
CPURL)anAbsoluteURL withContentsOfURL:(
CPURL)absoluteContentsURL ofType:(
CPString)aType delegate:(
id)aDelegate didReadSelector:(
SEL)aDidReadSelector contextInfo:(
id)aContextInfo
194 [
self setFileURL:anAbsoluteURL];
195 [
self setFileType:aType];
197 [
self readFromURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aDidReadSelector contextInfo:aContextInfo];
214 reason:"dataOfType:error: must be overridden by the document subclass."];
229 reason:"readFromData:ofType: must be overridden by the document subclass."];
244 - (void)makeWindowControllers
246 [
self makeViewAndWindowControllers];
249 - (void)makeViewAndWindowControllers
251 var viewCibName = [
self viewCibName],
252 windowCibName = [
self windowCibName],
253 viewController = nil,
254 windowController = nil;
257 if ([viewCibName length])
258 viewController = [[
CPViewController alloc] initWithCibName:viewCibName bundle:nil owner:self];
261 if ([windowCibName length])
262 windowController = [[
CPWindowController alloc] initWithWindowCibName:windowCibName owner:self];
265 else if (viewController)
267 var view = [viewController view],
268 viewFrame = [view frame];
270 viewFrame.origin = CGPointMake(50, 50);
272 var theWindow = [[
CPWindow alloc] initWithContentRect:viewFrame styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask | CPResizableWindowMask];
277 if (windowController && viewController)
278 [windowController setSupportsMultipleDocuments:YES];
280 if (windowController)
281 [
self addWindowController:windowController];
284 [
self addViewController:viewController forWindowController:windowController];
290 - (CPArray)windowControllers
292 return _windowControllers;
302 [_windowControllers addObject:aWindowController];
304 if ([aWindowController document] !==
self)
305 [aWindowController setDocument:self];
315 if (aWindowController)
316 [_windowControllers removeObject:aWindowController];
318 if ([aWindowController document] ===
self)
319 [aWindowController setDocument:nil];
327 - (CPArray)viewControllers
329 return [_viewControllersForWindowControllers allValues];
335 [_viewControllersForWindowControllers setObject:aViewController forKey:[aWindowController UID]];
337 if ([aWindowController document] ===
self)
338 [aWindowController setViewController:aViewController];
343 [_viewControllersForWindowControllers removeObject:aViewController];
348 return [_viewControllersForWindowControllers objectForKey:[aWindowController UID]];
357 [_windowControllers makeObjectsPerformSelector:@selector(setDocument:) withObject:self];
358 [_windowControllers makeObjectsPerformSelector:@selector(showWindow:) withObject:self];
367 return [_fileURL lastPathComponent];
369 if (!_untitledDocumentIndex)
370 _untitledDocumentIndex = ++CPDocumentUntitledCount;
372 if (_untitledDocumentIndex == 1)
375 return @"Untitled " + _untitledDocumentIndex;
416 - (void)readFromURL:(
CPURL)anAbsoluteURL ofType:(
CPString)aType delegate:(
id)aDelegate didReadSelector:(
SEL)aDidReadSelector contextInfo:(
id)aContextInfo
418 [_readConnection cancel];
423 _readConnection.session = _CPReadSessionMake(aType, aDelegate, aDidReadSelector, aContextInfo);
438 - (void)setFileURL:(
CPURL)aFileURL
440 if (_fileURL === aFileURL)
445 [_windowControllers makeObjectsPerformSelector:@selector(synchronizeWindowTitleWithDocumentName)];
458 - (void)saveToURL:(
CPURL)anAbsoluteURL ofType:(
CPString)aTypeName forSaveOperation:(CPSaveOperationType)aSaveOperation delegate:(
id)aDelegate didSaveSelector:(
SEL)aDidSaveSelector contextInfo:(
id)aContextInfo
460 var data = [
self dataOfType:[
self fileType] error:nil],
461 oldChangeCount = _changeCount;
467 [_writeRequest setHTTPMethod:@"POST"];
469 [_writeRequest setHTTPMethod:@"PUT"];
471 [_writeRequest setHTTPBody:[data rawString]];
473 [_writeRequest setValue:@"close" forHTTPHeaderField:@"Connection"];
475 if (aSaveOperation === CPSaveOperation)
476 [_writeRequest setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];
478 if (aSaveOperation !== CPSaveToOperation)
479 [
self updateChangeCount:CPChangeCleared];
484 connection.session = _CPSaveSessionMake(anAbsoluteURL, aSaveOperation, oldChangeCount, aDelegate, aDidSaveSelector, aContextInfo, connection);
497 var statusCode = [aResponse statusCode];
500 if (statusCode === 200)
503 var session = aConnection.session;
505 if (aConnection == _readConnection)
509 alert(
"There was an error retrieving the document.");
511 objj_msgSend(session.delegate, 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"];
528 if (session.saveOperation != CPSaveToOperation)
530 _changeCount += session.changeCount;
531 [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[
self isDocumentEdited]];
536 objj_msgSend(session.delegate, session.didSaveSelector,
self, NO, session.contextInfo);
537 [
self _sendDocumentSavedNotification:NO];
549 var session = aConnection.session;
552 if (aConnection == _readConnection)
556 objj_msgSend(session.delegate, session.didReadSelector,
self, YES, session.contextInfo);
560 if (session.saveOperation != CPSaveToOperation)
561 [
self setFileURL:session.absoluteURL];
565 objj_msgSend(session.delegate, session.didSaveSelector,
self, YES, session.contextInfo);
566 [
self _sendDocumentSavedNotification:YES];
576 var session = aConnection.session;
578 if (_readConnection == aConnection)
579 objj_msgSend(session.delegate, session.didReadSelector,
self, NO, session.contextInfo);
583 if (session.saveOperation != CPSaveToOperation)
585 _changeCount += session.changeCount;
586 [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[
self isDocumentEdited]];
591 alert(
"There was an error saving the document.");
593 objj_msgSend(session.delegate, session.didSaveSelector,
self, NO, session.contextInfo);
594 [
self _sendDocumentSavedNotification:NO];
604 if (_readConnection == aConnection)
605 _readConnection = nil;
612 - (BOOL)isDocumentEdited
614 return _changeCount != 0;
621 - (void)updateChangeCount:(CPDocumentChangeType)aChangeType
623 if (aChangeType == CPChangeDone)
625 else if (aChangeType == CPChangeUndone)
627 else if (aChangeType == CPChangeCleared)
633 [_windowControllers makeObjectsPerformSelector:@selector(setDocumentEdited:) withObject:[
self isDocumentEdited]];
659 - (BOOL)hasUndoManager
661 return _hasUndoManager;
668 - (void)setHasUndoManager:(BOOL)aFlag
670 if (_hasUndoManager == aFlag)
673 _hasUndoManager = aFlag;
675 if (!_hasUndoManager)
676 [
self setUndoManager:nil];
682 var undoManager = [aNotification
object];
684 if ([undoManager isUndoing] || [undoManager isRedoing])
687 [
self updateChangeCount:CPChangeDone];
693 [
self updateChangeCount:CPChangeUndone];
699 [
self updateChangeCount:CPChangeDone];
713 [defaultCenter removeObserver:self
714 name:CPUndoManagerDidUndoChangeNotification
715 object:_undoManager];
717 [defaultCenter removeObserver:self
718 name:CPUndoManagerDidRedoChangeNotification
719 object:_undoManager];
721 [defaultCenter removeObserver:self
722 name:CPUndoManagerWillCloseUndoGroupNotification
723 object:_undoManager];
726 _undoManager = anUndoManager;
731 [defaultCenter addObserver:self
732 selector:@selector(_undoManagerDidUndoChange:)
733 name:CPUndoManagerDidUndoChangeNotification
734 object:_undoManager];
736 [defaultCenter addObserver:self
737 selector:@selector(_undoManagerDidRedoChange:)
738 name:CPUndoManagerDidRedoChangeNotification
739 object:_undoManager];
741 [defaultCenter addObserver:self
742 selector:@selector(_undoManagerWillCloseGroup:)
743 name:CPUndoManagerWillCloseUndoGroupNotification
744 object:_undoManager];
756 if (_hasUndoManager && !_undoManager)
768 return [
self undoManager];
778 - (void)saveDocument:(
id)aSender
780 [
self saveDocumentWithDelegate:nil didSaveSelector:nil contextInfo:nil];
783 - (void)saveDocumentWithDelegate:(
id)delegate didSaveSelector:(
SEL)didSaveSelector contextInfo:(Object)contextInfo
791 [
self saveToURL:_fileURL ofType:[
self fileType] forSaveOperation:CPSaveOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
794 [
self _saveDocumentAsWithDelegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
801 - (void)saveDocumentAs:(
id)aSender
803 [
self _saveDocumentAsWithDelegate:nil didSaveSelector:nil contextInfo:nil];
806 - (void)_saveDocumentAsWithDelegate:(
id)delegate didSaveSelector:(
SEL)didSaveSelector contextInfo:(Object)contextInfo
809 response = [savePanel runModal];
814 var saveURL = [savePanel URL];
820 [
self saveToURL:saveURL ofType:[
self fileType] forSaveOperation:CPSaveAsOperation delegate:delegate didSaveSelector:didSaveSelector contextInfo:contextInfo];
826 - (void)_sendDocumentSavedNotification:(BOOL)didSave
840 @implementation CPDocument (ClosingDocuments)
844 [_windowControllers makeObjectsPerformSelector:@selector(removeDocumentAndCloseIfNecessary:) withObject:self];
848 - (void)shouldCloseWindowController:(
CPWindowController)controller delegate:(
id)delegate shouldCloseSelector:(
SEL)selector contextInfo:(Object)info
850 if ([controller shouldCloseDocument] || ([_windowControllers count] < 2 && [_windowControllers indexOfObject:controller] !==
CPNotFound))
851 [
self canCloseDocumentWithDelegate:self shouldCloseSelector:@selector(_document:shouldClose:context:) contextInfo:{delegate:delegate, selector:selector, context:info}];
853 else if ([delegate respondsToSelector:selector])
854 objj_msgSend(delegate, selector,
self, YES, info);
857 - (void)_document:(
CPDocument)aDocument shouldClose:(BOOL)shouldClose context:(Object)context
859 if (aDocument ===
self && shouldClose)
862 objj_msgSend(context.delegate, context.selector, aDocument, shouldClose, context.context);
865 - (void)canCloseDocumentWithDelegate:(
id)aDelegate shouldCloseSelector:(
SEL)aSelector contextInfo:(Object)context
867 if (![
self isDocumentEdited])
868 return [aDelegate respondsToSelector:aSelector] && objj_msgSend(aDelegate, aSelector,
self, YES, context);
870 _canCloseAlert = [[
CPAlert alloc] init];
872 [_canCloseAlert setDelegate:self];
873 [_canCloseAlert setAlertStyle:CPWarningAlertStyle];
874 [_canCloseAlert setTitle:@"Unsaved Document"];
875 [_canCloseAlert setMessageText:@"Do you want to save the changes you've made to the document \"" + ([
self displayName] || [
self fileName]) + "\"?"];
877 [_canCloseAlert addButtonWithTitle:@"Save"];
878 [_canCloseAlert addButtonWithTitle:@"Cancel"];
879 [_canCloseAlert addButtonWithTitle:@"Don't Save"];
881 _canCloseAlert._context = {delegate:aDelegate, selector:aSelector, context:context};
883 [_canCloseAlert runModal];
886 - (void)alertDidEnd:(
CPAlert)alert returnCode:(
int)returnCode
888 if (alert !== _canCloseAlert)
891 var delegate = alert._context.delegate,
892 selector = alert._context.selector,
893 context = alert._context.context;
895 if (returnCode === 0)
896 [
self saveDocumentWithDelegate:delegate didSaveSelector:selector contextInfo:context];
898 objj_msgSend(delegate, selector,
self, returnCode === 2, context);
900 _canCloseAlert = nil;
905 var _CPReadSessionMake =
function(aType, aDelegate, aDidReadSelector, aContextInfo)
907 return { fileType:aType, delegate:aDelegate, didReadSelector:aDidReadSelector, contextInfo:aContextInfo };
910 var _CPSaveSessionMake =
function(anAbsoluteURL, aSaveOperation, aChangeCount, aDelegate, aDidSaveSelector, aContextInfo, aConnection)
912 return { absoluteURL:anAbsoluteURL, saveOperation:aSaveOperation, changeCount:aChangeCount, delegate:aDelegate, didSaveSelector:aDidSaveSelector, contextInfo:aContextInfo, connection:aConnection };