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
00034 @implementation CPDocumentController : CPObject
00035 {
00036 CPArray _documents;
00037 CPArray _documentTypes;
00038 }
00039
00045 + (id)sharedDocumentController
00046 {
00047 if (!CPSharedDocumentController)
00048 [[self alloc] init];
00049
00050 return CPSharedDocumentController;
00051 }
00052
00053
00054
00055
00056 - (id)init
00057 {
00058 self = [super init];
00059
00060 if (self)
00061 {
00062 _documents = [[CPArray alloc] init];
00063
00064 if (!CPSharedDocumentController)
00065 CPSharedDocumentController = self;
00066
00067 _documentTypes = [[[CPBundle mainBundle] infoDictionary] objectForKey:@"CPBundleDocumentTypes"];
00068 }
00069 return self;
00070 }
00071
00072
00073
00081 - (CPDocument)documentForURL:(CPURL)aURL
00082 {
00083 var index = 0,
00084 count = [_documents count];
00085
00086 for (; index < count; ++index)
00087 {
00088 var theDocument = _documents[index];
00089
00090 if ([[theDocument fileURL] isEqual:aURL])
00091 return theDocument;
00092 }
00093
00094 return nil;
00095 }
00096
00102 - (void)openUntitledDocumentOfType:(CPString)aType display:(BOOL)shouldDisplay
00103 {
00104 var theDocument = [self makeUntitledDocumentOfType:aType error:nil];
00105
00106 if (theDocument)
00107 [self addDocument:theDocument];
00108
00109 if (shouldDisplay)
00110 {
00111 [theDocument makeWindowControllers];
00112 [theDocument showWindows];
00113 }
00114
00115 return theDocument;
00116 }
00117
00124 - (CPDocument)makeUntitledDocumentOfType:(CPString)aType error:({CPError})anError
00125 {
00126 return [[[self documentClassForType:aType] alloc] initWithType:aType error:anError];
00127 }
00128
00136 - (CPDocument)openDocumentWithContentsOfURL:(CPURL)anAbsoluteURL display:(BOOL)shouldDisplay error:(CPError)anError
00137 {
00138 var result = [self documentForURL:anAbsoluteURL];
00139
00140 if (!result)
00141 {
00142 var type = [self typeForContentsOfURL:anAbsoluteURL error:anError];
00143
00144 result = [self makeDocumentWithContentsOfURL:anAbsoluteURL ofType:type delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:[CPDictionary dictionaryWithObject:shouldDisplay forKey:@"shouldDisplay"]];
00145 }
00146 else if (shouldDisplay)
00147 [result showWindows];
00148
00149 return result;
00150 }
00151
00160 - (CPDocument)reopenDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL error:(CPError)anError
00161 {
00162 return [self makeDocumentForURL:anAbsoluteURL withContentsOfURL:absoluteContentsURL ofType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] delegate:self didReadSelector:@selector(document:didRead:contextInfo:) contextInfo:nil];
00163 }
00164
00174 - (CPDocument)makeDocumentWithContentsOfURL:(CPURL)anAbsoluteURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
00175 {
00176 return [[[self documentClassForType:aType] alloc] initWithContentsOfURL:anAbsoluteURL ofType:aType delegate:aDelegate didReadSelector:aSelector contextInfo:aContextInfo];
00177 }
00178
00190 - (CPDocument)makeDocumentForURL:(CPURL)anAbsoluteURL withContentsOfURL:(CPURL)absoluteContentsURL ofType:(CPString)aType delegate:(id)aDelegate didReadSelector:(SEL)aSelector contextInfo:(id)aContextInfo
00191 {
00192 return [[[self documentClassForType:aType] alloc] initForURL:anAbsoluteURL withContentsOfURL:absoluteContentsURL ofType:aType delegate:aDelegate didReadSelector:aSelector contextInfo:aContextInfo];
00193 }
00194
00195
00196
00197
00198
00199 - (void)document:(CPDocument)aDocument didRead:(BOOL)didRead contextInfo:(id)aContextInfo
00200 {
00201 if (!didRead)
00202 return;
00203
00204 [self addDocument:aDocument];
00205 [aDocument makeWindowControllers];
00206
00207 if ([aContextInfo objectForKey:@"shouldDisplay"])
00208 [aDocument showWindows];
00209 }
00210
00215 - (CFAction)newDocument:(id)aSender
00216 {
00217 [self openUntitledDocumentOfType:[[_documentTypes objectAtIndex:0] objectForKey:@"CPBundleTypeName"] display:YES];
00218 }
00219
00220
00221
00226 - (CPArray)documents
00227 {
00228 return _documents;
00229 }
00230
00235 - (void)addDocument:(CPDocument)aDocument
00236 {
00237 [_documents addObject:aDocument];
00238 }
00239
00244 - (void)removeDocument:(CPDocument)aDocument
00245 {
00246 [_documents removeObjectIdenticalTo:aDocument];
00247 }
00248
00249 - (CPString)defaultType
00250 {
00251 return [_documentTypes[0] objectForKey:@"CPBundleTypeName"];
00252 }
00253
00254 - (CPString)typeForContentsOfURL:(CPURL)anAbsoluteURL error:(CPError)outError
00255 {
00256 var index = 0,
00257 count = _documentTypes.length,
00258
00259 extension = [[anAbsoluteURL pathExtension] lowercaseString];
00260
00261 for (; index < count; ++index)
00262 {
00263 var documentType = _documentTypes[index],
00264 extensions = [documentType objectForKey:@"CFBundleTypeExtensions"],
00265 extensionIndex = 0,
00266 extensionCount = extensions.length;
00267
00268 for (; extensionIndex < extensionCount; ++extensionIndex)
00269 if ([extensions[extensionIndex] lowercaseString] == extension)
00270 return [documentType objectForKey:@"CPBundleTypeName"];
00271 }
00272
00273
00274 return [self defaultType];
00275 }
00276
00277
00278
00279
00280 - (CPDictionary)_infoForType:(CPString)aType
00281 {
00282 var i = 0,
00283 count = [_documentTypes count];
00284
00285 for (;i < count; ++i)
00286 {
00287 var documentType = _documentTypes[i];
00288
00289 if ([documentType objectForKey:@"CPBundleTypeName"] == aType)
00290 return documentType;
00291 }
00292
00293 return nil;
00294 }
00295
00301 - (Class)documentClassForType:(CPString)aType
00302 {
00303 var className = [[self _infoForType:aType] objectForKey:@"CPDocumentClass"];
00304
00305 return className ? CPClassFromString(className) : nil;
00306 }
00307
00308 @end