00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <Foundation/CPObject.j>
00024 @import <Foundation/CPBundle.j>
00025
00026 @import "CPDocument.j"
00027
00028
00029 var CPSharedDocumentController = nil;
00030
00036 @implementation CPDocumentController : CPObject
00037 {
00038 CPArray _documents;
00039 CPArray _documentTypes;
00040 }
00041
00047 + (id)sharedDocumentController
00048 {
00049 if (!CPSharedDocumentController)
00050 [[self alloc] init];
00051
00052 return CPSharedDocumentController;
00053 }
00054
00055
00056
00057
00058 - (id)init
00059 {
00060 self = [super init];
00061
00062 if (self)
00063 {
00064 _documents = [[CPArray alloc] init];
00065
00066 if (!CPSharedDocumentController)
00067 CPSharedDocumentController = self;
00068
00069 _documentTypes = [[[CPBundle mainBundle] infoDictionary] objectForKey:@"CPBundleDocumentTypes"];
00070 }
00071 return self;
00072 }
00073
00074
00075
00083 - (CPDocument)documentForURL:(CPURL)aURL
00084 {
00085 var index = 0,
00086 count = [_documents count];
00087
00088 for (; index < count; ++index)
00089 {
00090 var theDocument = _documents[index];
00091
00092 if ([[theDocument fileURL] isEqual:aURL])
00093 return theDocument;
00094 }
00095
00096 return nil;
00097 }
00098
00104 - (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
00105 {
00106 var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
00107
00108 if (theDocument)
00109 [self addDocument:theDocument];
00110
00111 if (shouldDisplay)
00112 {
00113 [theDocument makeWindowControllers];
00114 [theDocument showWindows];
00115 }
00116
00117 return theDocument;
00118 }
00119
00126 - (CPDocument)makeUntitledDocumentOfType:(CPString)aType error:({CPError})anError
00127 {
00128 return [[[self documentClassForType:aType] alloc] initWithType:aType error:anError];
00129 }
00130
00138 - (CPDocument)openDocumentWithContentsOfURL:(CPURL)anAbsoluteURL display:(BOOL)shouldDisplay error:(CPError)anError
00139 {
00140 var result = [self documentForURL:anAbsoluteURL];
00141
00142 if (!result)
00143 {
00144 var type = [self typeForContentsOfURL:anAbsoluteURL error:anError];
00145
00146 result = [self makeDocumentWithContentsOfURL:anAbsoluteURL ofType:type delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:[CPDictionary dictionaryWithObject:shouldDisplay forKey:@"shouldDisplay"]];
00147 }
00148 else if (shouldDisplay)
00149 [result showWindows];
00150
00151 return result;
00152 }
00153
00162 - (CPDocument)reopenDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL error:(CPError)anError
00163 {
00164 return [self makeDocumentForURL:anAbsoluteURL withContentsOfURL:absoluteContentsURL ofType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:nil];
00165 }
00166
00176 - (CPDocument)makeDocumentWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
00177 {
00178 return [[[self documentClassForType:aType] alloc] initWithContentsOfURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aSelector contextInfo:aContextInfo];
00179 }
00180
00192 - (CPDocument)makeDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
00193 {
00194 return [[[self documentClassForType:aType] alloc] initForURL:anAbsoluteURL withContentsOfURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aSelector contextInfo:aContextInfo];
00195 }
00196
00197
00198
00199
00200
00201 - (void)document:(CPDocument)aDocument didRead:(BOOL)didRead contextInfo:(id)aContextInfo
00202 {
00203 if (!didRead)
00204 return;
00205
00206 [self addDocument:aDocument];
00207 [aDocument makeWindowControllers];
00208
00209 if ([aContextInfo objectForKey:@"shouldDisplay"])
00210 [aDocument showWindows];
00211 }
00212
00217 - (CFAction)newDocument:(id)aSender
00218 {
00219 [self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
00220 }
00221
00222
00223
00228 - (CPArray)documents
00229 {
00230 return _documents;
00231 }
00232
00237 - (void)addDocument:(CPDocument)aDocument
00238 {
00239 [_documents addObject:aDocument];
00240 }
00241
00246 - (void)removeDocument:(CPDocument)aDocument
00247 {
00248 [_documents removeObjectIdenticalTo:aDocument];
00249 }
00250
00251 - (CPString)defaultType
00252 {
00253 return [_documentTypes[0] objectForKey:@"CPBundleTypeName"];
00254 }
00255
00256 - (CPString)typeForContentsOfURL:(CPURL)anAbsoluteURL error:(CPError)outError
00257 {
00258 var index = 0,
00259 count = _documentTypes.length,
00260
00261 extension = [[anAbsoluteURL pathExtension] lowercaseString];
00262
00263 for (; index < count; ++index)
00264 {
00265 var documentType = _documentTypes[index],
00266 extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
00267 extensionIndex = 0,
00268 extensionCount = extensions.length;
00269
00270 for (; extensionIndex < extensionCount; ++extensionIndex)
00271 if ([extensions[extensionIndex] lowercaseString] == extension)
00272 return [documentType objectForKey:@"CPBundleTypeName"];
00273 }
00274
00275
00276 return [self defaultType];
00277 }
00278
00279
00280
00281
00282 - (CPDictionary)_infoForType:(CPString)aType
00283 {
00284 var i = 0,
00285 count = [_documentTypes count];
00286
00287 for (;i < count; ++i)
00288 {
00289 var documentType = _documentTypes[i];
00290
00291 if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
00292 return documentType;
00293 }
00294
00295 return nil;
00296 }
00297
00303 - (Class)documentClassForType:(CPString)aType
00304 {
00305 var className = [[self _infoForType:aType] objectForKey:@"CPDocumentClass"];
00306
00307 return className ? CPClassFromString(className) : nil;
00308 }
00309
00310 @end