mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-06-02 06:10:59 +00:00
Clean up and completion of NSDocumentController.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27415 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
4a710daca9
commit
6cfee381c1
4 changed files with 572 additions and 314 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
2008-12-25 Fred Kiefer <FredKiefer@gmx.de>
|
||||||
|
|
||||||
|
* Headers/AppKit/NSMenuItem.h: Declare to implement interface
|
||||||
|
NSValidatedUserInterfaceItem.
|
||||||
|
* Headers/AppKit/NSDocumentController.h: Change to use NSUInteger and
|
||||||
|
NSInteger.
|
||||||
|
* Source/NSDocumentController.m: Implement all Cocoa methods of this
|
||||||
|
class and clean up the rest of the implementation.
|
||||||
|
Partly using code by Nikolaus Schaller <hns@computer.org>.
|
||||||
|
|
||||||
2008-12-21 Adam Fedor <fedor@gnu.org>
|
2008-12-21 Adam Fedor <fedor@gnu.org>
|
||||||
|
|
||||||
* Version 0.16.0
|
* Version 0.16.0
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
@class NSOpenPanel;
|
@class NSOpenPanel;
|
||||||
@class NSWindow;
|
@class NSWindow;
|
||||||
|
|
||||||
@interface NSDocumentController : NSObject
|
@interface NSDocumentController : NSObject <NSCoding>
|
||||||
{
|
{
|
||||||
@private
|
@private
|
||||||
NSMutableArray *_documents;
|
NSMutableArray *_documents;
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
- (IBAction)newDocument:(id)sender;
|
- (IBAction)newDocument:(id)sender;
|
||||||
- (IBAction)clearRecentDocuments:(id)sender;
|
- (IBAction)clearRecentDocuments:(id)sender;
|
||||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
|
||||||
- (unsigned int) maximumRecentDocumentCount;
|
- (NSUInteger) maximumRecentDocumentCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*" Recent Documents "*/
|
/*" Recent Documents "*/
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
/*" Open panel "*/
|
/*" Open panel "*/
|
||||||
- (NSArray *)URLsFromRunningOpenPanel;
|
- (NSArray *)URLsFromRunningOpenPanel;
|
||||||
- (NSArray *)fileNamesFromRunningOpenPanel;
|
- (NSArray *)fileNamesFromRunningOpenPanel;
|
||||||
- (int)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)openableFileExtensions;
|
- (NSInteger)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)openableFileExtensions;
|
||||||
|
|
||||||
/*" Document management "*/
|
/*" Document management "*/
|
||||||
- (void)addDocument:(NSDocument *)document;
|
- (void)addDocument:(NSDocument *)document;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#import <GNUstepBase/GSVersionMacros.h>
|
#import <GNUstepBase/GSVersionMacros.h>
|
||||||
|
|
||||||
#include <Foundation/NSObject.h>
|
#include <Foundation/NSObject.h>
|
||||||
|
#include <AppKit/NSUserInterfaceValidation.h>
|
||||||
|
|
||||||
@class NSAttributedString;
|
@class NSAttributedString;
|
||||||
@class NSString;
|
@class NSString;
|
||||||
|
@ -367,7 +368,7 @@
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface NSMenuItem : NSObject <NSMenuItem>
|
@interface NSMenuItem : NSObject <NSMenuItem, NSValidatedUserInterfaceItem>
|
||||||
{
|
{
|
||||||
NSMenu *_menu;
|
NSMenu *_menu;
|
||||||
NSString *_title;
|
NSString *_title;
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "AppKit/NSDocumentController.h"
|
#include "AppKit/NSDocumentController.h"
|
||||||
#include "AppKit/NSOpenPanel.h"
|
#include "AppKit/NSOpenPanel.h"
|
||||||
#include "AppKit/NSApplication.h"
|
#include "AppKit/NSApplication.h"
|
||||||
|
#include "AppKit/NSMenu.h"
|
||||||
#include "AppKit/NSMenuItem.h"
|
#include "AppKit/NSMenuItem.h"
|
||||||
#include "AppKit/NSWorkspace.h"
|
#include "AppKit/NSWorkspace.h"
|
||||||
#include "NSDocumentFrameworkPrivate.h"
|
#include "NSDocumentFrameworkPrivate.h"
|
||||||
|
@ -61,8 +62,14 @@ static NSString *CFBundleTypeExtensions = @"CFBundleTypeExtensions";
|
||||||
static NSString *CFBundleTypeName = @"CFBundleTypeName";
|
static NSString *CFBundleTypeName = @"CFBundleTypeName";
|
||||||
static NSString *CFBundleTypeRole = @"CFBundleTypeRole";
|
static NSString *CFBundleTypeRole = @"CFBundleTypeRole";
|
||||||
|
|
||||||
|
// FIXME: Looks like this was changed to @"NSRecentDocumentRecords"
|
||||||
static NSString *NSRecentDocuments = @"NSRecentDocuments";
|
static NSString *NSRecentDocuments = @"NSRecentDocuments";
|
||||||
|
|
||||||
|
static NSString *NSEditorRole = @"Editor";
|
||||||
|
static NSString *NSViewerRole = @"Viewer";
|
||||||
|
//static NSString *NSNoRole = @"None";
|
||||||
|
//static NSString *NSShellRole = @"Shell";
|
||||||
|
|
||||||
static NSDocumentController *sharedController = nil;
|
static NSDocumentController *sharedController = nil;
|
||||||
|
|
||||||
#define TYPE_INFO(name) TypeInfoForName(_types, name)
|
#define TYPE_INFO(name) TypeInfoForName(_types, name)
|
||||||
|
@ -108,6 +115,14 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@interface NSDocumentController (RecentsMenu)
|
||||||
|
- (NSMenu *) _recentMenu;
|
||||||
|
- (void) _updateOpenRecentMenu;
|
||||||
|
- (IBAction) _openRecentDocument: (id)sender;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
/** <p>
|
/** <p>
|
||||||
NSDocumentController is a class that controls a set of NSDocuments
|
NSDocumentController is a class that controls a set of NSDocuments
|
||||||
for an application. As an application delegate, it responds to the
|
for an application. As an application delegate, it responds to the
|
||||||
|
@ -159,7 +174,8 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
{
|
{
|
||||||
if (sharedController == nil)
|
if (sharedController == nil)
|
||||||
{
|
{
|
||||||
sharedController = [[self alloc] init];
|
// -init sets sharedController
|
||||||
|
[[self alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
return sharedController;
|
return sharedController;
|
||||||
|
@ -256,12 +272,13 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
IMP meth2;
|
IMP meth2;
|
||||||
|
|
||||||
meth1 = [self methodForSelector: sel];
|
meth1 = [self methodForSelector: sel];
|
||||||
meth2 = [[NSDocument class] instanceMethodForSelector: sel];
|
meth2 = [[NSDocumentController class] instanceMethodForSelector: sel];
|
||||||
|
|
||||||
return (meth1 != meth2);
|
return (meth1 != meth2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OVERRIDDEN(sel) [self _hasOverridden: @selector(sel)]
|
//#define OVERRIDDEN(sel) [self _hasOverridden: @selector(sel)]
|
||||||
|
#define OVERRIDDEN(sel) ([self methodForSelector: @selector(sel)] != [[NSDocumentController class] instanceMethodForSelector: @selector(sel)])
|
||||||
|
|
||||||
- (BOOL) shouldCreateUI
|
- (BOOL) shouldCreateUI
|
||||||
{
|
{
|
||||||
|
@ -331,6 +348,13 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
error: (NSError **)err
|
error: (NSError **)err
|
||||||
{
|
{
|
||||||
Class documentClass = [self documentClassForType: type];
|
Class documentClass = [self documentClassForType: type];
|
||||||
|
|
||||||
|
if (documentClass == nil)
|
||||||
|
{
|
||||||
|
// FIXME: Set err
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
return AUTORELEASE([[documentClass alloc] initForURL: url
|
return AUTORELEASE([[documentClass alloc] initForURL: url
|
||||||
withContentsOfURL: contents
|
withContentsOfURL: contents
|
||||||
ofType: type
|
ofType: type
|
||||||
|
@ -340,20 +364,40 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
- (id) makeDocumentWithContentsOfURL: (NSURL *)url
|
- (id) makeDocumentWithContentsOfURL: (NSURL *)url
|
||||||
ofType: (NSString *)type
|
ofType: (NSString *)type
|
||||||
error: (NSError **)err
|
error: (NSError **)err
|
||||||
|
{
|
||||||
|
if (OVERRIDDEN(makeDocumentWithContentsOfFile:ofType:) && [url isFileURL])
|
||||||
|
{
|
||||||
|
return [self makeDocumentWithContentsOfFile: [url path] ofType: type];
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Class documentClass = [self documentClassForType: type];
|
Class documentClass = [self documentClassForType: type];
|
||||||
|
|
||||||
|
if (documentClass == nil)
|
||||||
|
{
|
||||||
|
// FIXME: Set err
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
return AUTORELEASE([[documentClass alloc] initWithContentsOfURL: url
|
return AUTORELEASE([[documentClass alloc] initWithContentsOfURL: url
|
||||||
ofType: type
|
ofType: type
|
||||||
error: err]);
|
error: err]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (id) makeUntitledDocumentOfType: (NSString *)type
|
- (id) makeUntitledDocumentOfType: (NSString *)type
|
||||||
error: (NSError **)err
|
error: (NSError **)err
|
||||||
|
{
|
||||||
|
if (OVERRIDDEN(makeUntitledDocumentOfType:))
|
||||||
|
{
|
||||||
|
return [self makeUntitledDocumentOfType: type];
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Class documentClass = [self documentClassForType: type];
|
Class documentClass = [self documentClassForType: type];
|
||||||
return AUTORELEASE([[documentClass alloc] initWithType: type
|
return AUTORELEASE([[documentClass alloc] initWithType: type
|
||||||
error: err]);
|
error: err]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL) presentError: (NSError *)error
|
- (BOOL) presentError: (NSError *)error
|
||||||
{
|
{
|
||||||
|
@ -383,19 +427,32 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
- (NSString*) defaultType
|
- (NSString*) defaultType
|
||||||
{
|
{
|
||||||
NSString *defaultName = nil;
|
NSString *defaultName = nil;
|
||||||
if ([_types count] == 0)
|
int i, count = [_types count];
|
||||||
{
|
|
||||||
return nil; // raise exception?
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultName = [(NSDictionary*)[_types objectAtIndex: 0] objectForKey: NSNameKey];
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
NSDictionary *typeInfo = (NSDictionary*)[_types objectAtIndex: i];
|
||||||
|
NSString *role;
|
||||||
|
|
||||||
|
role = [typeInfo objectForKey: NSRoleKey];
|
||||||
|
if (role == nil)
|
||||||
|
role = [typeInfo objectForKey: CFBundleTypeRole];
|
||||||
|
|
||||||
|
if ([role isEqual: NSEditorRole])
|
||||||
|
{
|
||||||
|
defaultName = [typeInfo objectForKey: NSNameKey];
|
||||||
if (defaultName == nil)
|
if (defaultName == nil)
|
||||||
{
|
{
|
||||||
defaultName = [(NSDictionary*)[_types objectAtIndex: 0] objectForKey: CFBundleTypeName];
|
defaultName = [typeInfo objectForKey: CFBundleTypeName];
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultName;
|
return defaultName;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// none found
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) addDocument: (NSDocument *)document
|
- (void) addDocument: (NSDocument *)document
|
||||||
{
|
{
|
||||||
|
@ -477,9 +534,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
|
|
||||||
if (document == nil)
|
if (document == nil)
|
||||||
{
|
{
|
||||||
// Should we only do this if [url isFileURL] is YES?
|
NSString *type = [self typeForContentsOfURL: url error: NULL];
|
||||||
NSString *type = [self typeFromFileExtension:
|
|
||||||
[[url path] pathExtension]];
|
|
||||||
|
|
||||||
document = [self makeDocumentWithContentsOfURL: url ofType: type];
|
document = [self makeDocumentWithContentsOfURL: url ofType: type];
|
||||||
|
|
||||||
|
@ -543,12 +598,10 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
display: (BOOL)display
|
display: (BOOL)display
|
||||||
error: (NSError **)err
|
error: (NSError **)err
|
||||||
{
|
{
|
||||||
if (OVERRIDDEN(openDocumentWithContentsOfFile:display:))
|
if (OVERRIDDEN(openDocumentWithContentsOfFile:display:) && [url isFileURL])
|
||||||
{
|
{
|
||||||
NSString *fileName;
|
return [self openDocumentWithContentsOfFile: [url path]
|
||||||
|
display: display];
|
||||||
fileName = [url path];
|
|
||||||
return [self openDocumentWithContentsOfFile: fileName display: display];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -556,11 +609,16 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
|
|
||||||
if (document == nil)
|
if (document == nil)
|
||||||
{
|
{
|
||||||
// Should we only do this if [url isFileURL] is YES?
|
NSString *type = [self typeForContentsOfURL: url error: err];
|
||||||
NSString *type = [self typeFromFileExtension:
|
|
||||||
[[url path] pathExtension]];
|
|
||||||
|
|
||||||
document = [self makeDocumentWithContentsOfURL: url ofType: type error: err];
|
if (type == nil)
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
document = [self makeDocumentWithContentsOfURL: url
|
||||||
|
ofType: type
|
||||||
|
error: err];
|
||||||
|
|
||||||
if (document == nil)
|
if (document == nil)
|
||||||
{
|
{
|
||||||
|
@ -591,12 +649,15 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
withContentsOfURL: (NSURL *)contents
|
withContentsOfURL: (NSURL *)contents
|
||||||
error: (NSError **)err
|
error: (NSError **)err
|
||||||
{
|
{
|
||||||
if ([contents isFileURL])
|
NSString *type = [self typeForContentsOfURL: contents error: err];
|
||||||
|
id document;
|
||||||
|
|
||||||
|
if (type == nil)
|
||||||
{
|
{
|
||||||
NSString *type =
|
return NO;
|
||||||
[self typeFromFileExtension: [[contents path] pathExtension]];
|
}
|
||||||
id document =
|
|
||||||
[self makeDocumentForURL: url
|
document = [self makeDocumentForURL: url
|
||||||
withContentsOfURL: contents
|
withContentsOfURL: contents
|
||||||
ofType: type
|
ofType: type
|
||||||
error: err];
|
error: err];
|
||||||
|
@ -610,12 +671,6 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// FIXME: set error
|
|
||||||
*err = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
@ -623,6 +678,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
- (NSOpenPanel *) _setupOpenPanel
|
- (NSOpenPanel *) _setupOpenPanel
|
||||||
{
|
{
|
||||||
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
||||||
|
|
||||||
[openPanel setDirectory: [self currentDirectory]];
|
[openPanel setDirectory: [self currentDirectory]];
|
||||||
[openPanel setAllowsMultipleSelection: YES];
|
[openPanel setAllowsMultipleSelection: YES];
|
||||||
return openPanel;
|
return openPanel;
|
||||||
|
@ -631,7 +687,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
/** Invokes [NSOpenPanel-runModalForTypes:] with the NSOpenPanel
|
/** Invokes [NSOpenPanel-runModalForTypes:] with the NSOpenPanel
|
||||||
object openPanel, and passes the openableFileExtensions file types
|
object openPanel, and passes the openableFileExtensions file types
|
||||||
*/
|
*/
|
||||||
- (int) runModalOpenPanel: (NSOpenPanel *)openPanel
|
- (NSInteger) runModalOpenPanel: (NSOpenPanel *)openPanel
|
||||||
forTypes: (NSArray *)openableFileExtensions
|
forTypes: (NSArray *)openableFileExtensions
|
||||||
{
|
{
|
||||||
return [openPanel runModalForTypes: openableFileExtensions];
|
return [openPanel runModalForTypes: openableFileExtensions];
|
||||||
|
@ -645,6 +701,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
NSDictionary *typeInfo = [_types objectAtIndex: i];
|
NSDictionary *typeInfo = [_types objectAtIndex: i];
|
||||||
|
|
||||||
[array addObjectsFromArray: [typeInfo objectForKey: NSUnixExtensionsKey]];
|
[array addObjectsFromArray: [typeInfo objectForKey: NSUnixExtensionsKey]];
|
||||||
[array addObjectsFromArray: [typeInfo objectForKey: NSDOSExtensionsKey]];
|
[array addObjectsFromArray: [typeInfo objectForKey: NSDOSExtensionsKey]];
|
||||||
[array addObjectsFromArray: [typeInfo objectForKey: CFBundleTypeExtensions]];
|
[array addObjectsFromArray: [typeInfo objectForKey: CFBundleTypeExtensions]];
|
||||||
|
@ -687,7 +744,6 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (IBAction) saveAllDocuments: (id)sender
|
- (IBAction) saveAllDocuments: (id)sender
|
||||||
{
|
{
|
||||||
NSDocument *document;
|
NSDocument *document;
|
||||||
|
@ -702,23 +758,30 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (IBAction) openDocument: (id)sender
|
- (IBAction) openDocument: (id)sender
|
||||||
{
|
{
|
||||||
NSEnumerator *fileEnum;
|
NSError *err = nil;
|
||||||
NSString *filename;
|
NSEnumerator *urlEnum;
|
||||||
|
NSURL *url;
|
||||||
|
|
||||||
fileEnum = [[self fileNamesFromRunningOpenPanel] objectEnumerator];
|
urlEnum = [[self URLsFromRunningOpenPanel] objectEnumerator];
|
||||||
|
while ((url = [urlEnum nextObject]))
|
||||||
while ((filename = [fileEnum nextObject]))
|
|
||||||
{
|
{
|
||||||
[self openDocumentWithContentsOfFile: filename display: YES];
|
[self openDocumentWithContentsOfURL: url display: YES error: &err];
|
||||||
|
if (err && ![self presentError: err])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction) newDocument: (id)sender
|
- (IBAction) newDocument: (id)sender
|
||||||
{
|
{
|
||||||
[self openUntitledDocumentOfType: [self defaultType] display: YES];
|
NSError *err = nil;
|
||||||
|
|
||||||
|
[self openUntitledDocumentAndDisplay: YES error: &err];
|
||||||
|
if (err)
|
||||||
|
[self presentError: err];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -748,11 +811,59 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
static BOOL _shouldClose = YES;
|
||||||
|
|
||||||
|
- (void) _document: (NSDocument *)doc
|
||||||
|
shouldClose: (BOOL)shouldClose
|
||||||
|
contextInfo: (void *)contextInfo
|
||||||
|
{
|
||||||
|
_shouldClose = shouldClose;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)closeAllDocumentsWithDelegate:(id)delegate
|
- (void)closeAllDocumentsWithDelegate:(id)delegate
|
||||||
didCloseAllSelector:(SEL)didAllCloseSelector
|
didCloseAllSelector:(SEL)didAllCloseSelector
|
||||||
contextInfo:(void *)contextInfo
|
contextInfo:(void *)contextInfo
|
||||||
{
|
{
|
||||||
//FIXME
|
int count;
|
||||||
|
BOOL closeAll = YES;
|
||||||
|
|
||||||
|
count = [_documents count];
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
NSDocument *array[count];
|
||||||
|
|
||||||
|
[_documents getObjects: array];
|
||||||
|
while (count-- > 0)
|
||||||
|
{
|
||||||
|
NSDocument *document = array[count];
|
||||||
|
|
||||||
|
// Initialize to known state
|
||||||
|
_shouldClose = YES;
|
||||||
|
[document canCloseDocumentWithDelegate: self
|
||||||
|
shouldCloseSelector:
|
||||||
|
@selector(_document:shouldClose:contextInfo:)
|
||||||
|
contextInfo: contextInfo];
|
||||||
|
if (_shouldClose)
|
||||||
|
{
|
||||||
|
[document close];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
closeAll = NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delegate != nil && didAllCloseSelector != NULL)
|
||||||
|
{
|
||||||
|
void (*meth)(id, SEL, id, BOOL, void*);
|
||||||
|
meth = (void (*)(id, SEL, id, BOOL, void*))[delegate methodForSelector:
|
||||||
|
didAllCloseSelector];
|
||||||
|
if (meth)
|
||||||
|
meth(delegate, didAllCloseSelector, self, closeAll, contextInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If there are any unsaved documents, this method displays an alert
|
/** If there are any unsaved documents, this method displays an alert
|
||||||
|
@ -800,7 +911,34 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
didReviewAllSelector: (SEL)didReviewAllSelector
|
didReviewAllSelector: (SEL)didReviewAllSelector
|
||||||
contextInfo: (void *)contextInfo
|
contextInfo: (void *)contextInfo
|
||||||
{
|
{
|
||||||
|
NSString *cancelString = (cancellable)? ((NSString *)_(@"Cancel")) : ((NSString *)nil);
|
||||||
|
int result = YES;
|
||||||
|
|
||||||
|
if (![self hasEditedDocuments])
|
||||||
|
{
|
||||||
|
if (delegate != nil && didReviewAllSelector != NULL)
|
||||||
|
{
|
||||||
|
void (*meth)(id, SEL, id, BOOL, void*);
|
||||||
|
meth = (void (*)(id, SEL, id, BOOL, void*))[delegate methodForSelector:
|
||||||
|
didReviewAllSelector];
|
||||||
|
if (meth)
|
||||||
|
meth(delegate, didReviewAllSelector, self, result, contextInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
|
NSBeginAlertSheet(title,
|
||||||
|
_(@"Review Unsaved"),
|
||||||
|
cancelString,
|
||||||
|
_(@"Quit Anyway"),
|
||||||
|
nil,
|
||||||
|
delegate,
|
||||||
|
didReviewAllSelector,
|
||||||
|
contextInfo,
|
||||||
|
_(@"You have unsaved documents"),
|
||||||
|
nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -845,7 +983,6 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
[self reviewUnsavedDocumentsWithAlertTitle: _(@"Power Off") cancellable: NO];
|
[self reviewUnsavedDocumentsWithAlertTitle: _(@"Power Off") cancellable: NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Returns an array of all open documents */
|
/** Returns an array of all open documents */
|
||||||
- (NSArray *) documents
|
- (NSArray *) documents
|
||||||
{
|
{
|
||||||
|
@ -958,12 +1095,9 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
|
|
||||||
- (id) documentForURL: (NSURL *)url
|
- (id) documentForURL: (NSURL *)url
|
||||||
{
|
{
|
||||||
if (OVERRIDDEN(documentForFileName:))
|
if (OVERRIDDEN(documentForFileName:) && [url isFileURL])
|
||||||
{
|
{
|
||||||
NSString *fileName;
|
return [self documentForFileName: [url path]];
|
||||||
|
|
||||||
fileName = [url path];
|
|
||||||
return [self documentForFileName: fileName];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -985,23 +1119,30 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
|
|
||||||
- (BOOL) validateMenuItem: (NSMenuItem *)anItem
|
- (BOOL) validateMenuItem: (NSMenuItem *)anItem
|
||||||
{
|
{
|
||||||
if ([anItem action] == @selector(saveAllDocuments:))
|
return [self validateUserInterfaceItem: anItem];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) validateUserInterfaceItem: (id <NSValidatedUserInterfaceItem>)anItem
|
||||||
|
{
|
||||||
|
if (sel_eq([anItem action], @selector(saveAllDocuments:)))
|
||||||
{
|
{
|
||||||
return [self hasEditedDocuments];
|
return [self hasEditedDocuments];
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem
|
|
||||||
{
|
|
||||||
// FIXME
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) displayNameForType: (NSString *)type
|
- (NSString *) displayNameForType: (NSString *)type
|
||||||
{
|
{
|
||||||
|
// FIXME: Is this needed?
|
||||||
NSString *name = [TYPE_INFO(type) objectForKey: NSHumanReadableNameKey];
|
NSString *name = [TYPE_INFO(type) objectForKey: NSHumanReadableNameKey];
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
name = [[NSBundle mainBundle] localizedStringForKey: type
|
||||||
|
value: type
|
||||||
|
table: @"InfoPlist"];
|
||||||
|
}
|
||||||
|
|
||||||
return name ? name : type;
|
return name ? name : type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,6 +1162,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
containsObject: fileExtension])
|
containsObject: fileExtension])
|
||||||
{
|
{
|
||||||
NSString *type = [typeInfo objectForKey: NSNameKey];
|
NSString *type = [typeInfo objectForKey: NSNameKey];
|
||||||
|
|
||||||
if(type == nil)
|
if(type == nil)
|
||||||
{
|
{
|
||||||
type = [typeInfo objectForKey: CFBundleTypeName];
|
type = [typeInfo objectForKey: CFBundleTypeName];
|
||||||
|
@ -1034,26 +1176,21 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
|
|
||||||
- (NSString *) typeForContentsOfURL: (NSURL *)url error: (NSError **)err
|
- (NSString *) typeForContentsOfURL: (NSURL *)url error: (NSError **)err
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME: open connection and get response to determine mine/type
|
||||||
NSString *extension;
|
// Should we only do this if [url isFileURL] is YES?
|
||||||
|
return [self typeFromFileExtension: [[url path] pathExtension]];
|
||||||
extension = [[url path] pathExtension];
|
|
||||||
return [self typeFromFileExtension: extension];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) fileExtensionsFromType: (NSString *)type
|
- (NSArray *) fileExtensionsFromType: (NSString *)type
|
||||||
{
|
{
|
||||||
NSDictionary *typeInfo = TYPE_INFO(type);
|
NSDictionary *typeInfo = TYPE_INFO(type);
|
||||||
NSArray *unixExtensions = [typeInfo objectForKey: NSUnixExtensionsKey];
|
NSMutableArray *array = [NSMutableArray arrayWithCapacity: 3];
|
||||||
NSArray *dosExtensions = [typeInfo objectForKey: NSDOSExtensionsKey];
|
|
||||||
NSArray *cfFileExtensions = [typeInfo objectForKey: CFBundleTypeExtensions];
|
|
||||||
|
|
||||||
if (!dosExtensions && !unixExtensions) return cfFileExtensions;
|
[array addObjectsFromArray: [typeInfo objectForKey: NSUnixExtensionsKey]];
|
||||||
if (!dosExtensions) return unixExtensions;
|
[array addObjectsFromArray: [typeInfo objectForKey: NSDOSExtensionsKey]];
|
||||||
if (!unixExtensions) return dosExtensions;
|
[array addObjectsFromArray: [typeInfo objectForKey: CFBundleTypeExtensions]];
|
||||||
|
|
||||||
return [[unixExtensions arrayByAddingObjectsFromArray: dosExtensions]
|
return array;
|
||||||
arrayByAddingObjectsFromArray: cfFileExtensions];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Class) documentClassForType: (NSString *)type
|
- (Class) documentClassForType: (NSString *)type
|
||||||
|
@ -1095,18 +1232,19 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
[_recent_documents removeAllObjects];
|
[_recent_documents removeAllObjects];
|
||||||
[[NSUserDefaults standardUserDefaults]
|
[[NSUserDefaults standardUserDefaults]
|
||||||
setObject: _recent_documents forKey: NSRecentDocuments];
|
setObject: _recent_documents forKey: NSRecentDocuments];
|
||||||
|
[self _updateOpenRecentMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
// The number of remembered recent documents
|
// The number of remembered recent documents
|
||||||
- (unsigned int) maximumRecentDocumentCount
|
- (NSUInteger) maximumRecentDocumentCount
|
||||||
{
|
{
|
||||||
|
// FIXME: Should come from user defaults
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) noteNewRecentDocument: (NSDocument *)aDocument
|
- (void) noteNewRecentDocument: (NSDocument *)aDocument
|
||||||
{
|
{
|
||||||
NSString *fileName = [aDocument fileName];
|
NSURL *anURL = [aDocument fileURL];
|
||||||
NSURL *anURL = [NSURL fileURLWithPath: fileName];
|
|
||||||
|
|
||||||
if (anURL != nil)
|
if (anURL != nil)
|
||||||
[self noteNewRecentDocumentURL: anURL];
|
[self noteNewRecentDocumentURL: anURL];
|
||||||
|
@ -1129,6 +1267,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
|
|
||||||
[_recent_documents addObject: anURL];
|
[_recent_documents addObject: anURL];
|
||||||
|
|
||||||
|
// Save the changed list
|
||||||
a = [_recent_documents mutableCopy];
|
a = [_recent_documents mutableCopy];
|
||||||
index = [a count];
|
index = [a count];
|
||||||
while (index-- > 0)
|
while (index-- > 0)
|
||||||
|
@ -1139,6 +1278,7 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
[[NSUserDefaults standardUserDefaults]
|
[[NSUserDefaults standardUserDefaults]
|
||||||
setObject: a forKey: NSRecentDocuments];
|
setObject: a forKey: NSRecentDocuments];
|
||||||
RELEASE(a);
|
RELEASE(a);
|
||||||
|
[self _updateOpenRecentMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) recentDocumentURLs
|
- (NSArray *) recentDocumentURLs
|
||||||
|
@ -1146,12 +1286,23 @@ static NSDictionary *TypeInfoForHumanReadableName (NSArray *types, NSString *typ
|
||||||
return _recent_documents;
|
return _recent_documents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NSCoding protocol
|
||||||
|
//
|
||||||
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation NSDocumentController (Private)
|
@implementation NSDocumentController (Private)
|
||||||
static NSString *NSEditorRole = @"Editor";
|
|
||||||
static NSString *NSViewerRole = @"Viewer";
|
|
||||||
//static NSString *NSNoRole = @"None";
|
|
||||||
|
|
||||||
- (NSArray *) _editorAndViewerTypesForClass: (Class)documentClass
|
- (NSArray *) _editorAndViewerTypesForClass: (Class)documentClass
|
||||||
{
|
{
|
||||||
|
@ -1177,6 +1328,7 @@ static NSString *NSViewerRole = @"Viewer";
|
||||||
|| [role isEqual: NSViewerRole]))
|
|| [role isEqual: NSViewerRole]))
|
||||||
{
|
{
|
||||||
NSString *name = [typeInfo objectForKey: NSNameKey];
|
NSString *name = [typeInfo objectForKey: NSNameKey];
|
||||||
|
|
||||||
if(name == nil)
|
if(name == nil)
|
||||||
{
|
{
|
||||||
name = [typeInfo objectForKey: CFBundleTypeName];
|
name = [typeInfo objectForKey: CFBundleTypeName];
|
||||||
|
@ -1200,10 +1352,17 @@ static NSString *NSViewerRole = @"Viewer";
|
||||||
NSString *className = [typeInfo objectForKey: NSDocumentClassKey];
|
NSString *className = [typeInfo objectForKey: NSDocumentClassKey];
|
||||||
NSString *role = [typeInfo objectForKey: NSRoleKey];
|
NSString *role = [typeInfo objectForKey: NSRoleKey];
|
||||||
|
|
||||||
|
// if the standard one isn't filled... check the CF key.
|
||||||
|
if (role == nil)
|
||||||
|
{
|
||||||
|
role = [typeInfo objectForKey: CFBundleTypeRole];
|
||||||
|
}
|
||||||
|
|
||||||
if ([docClassName isEqualToString: className] &&
|
if ([docClassName isEqualToString: className] &&
|
||||||
(role == nil || [role isEqual: NSEditorRole]))
|
(role == nil || [role isEqual: NSEditorRole]))
|
||||||
{
|
{
|
||||||
NSString *name = [typeInfo objectForKey: NSNameKey];
|
NSString *name = [typeInfo objectForKey: NSNameKey];
|
||||||
|
|
||||||
if(name == nil)
|
if(name == nil)
|
||||||
{
|
{
|
||||||
name = [typeInfo objectForKey: CFBundleTypeName];
|
name = [typeInfo objectForKey: CFBundleTypeName];
|
||||||
|
@ -1393,3 +1552,91 @@ static NSString *processName;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation NSDocumentController (RecentsMenu)
|
||||||
|
|
||||||
|
- (NSMenu *) _recentMenu
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be handled by making us the delegate of the recent's menu
|
||||||
|
- (void) _updateOpenRecentMenu
|
||||||
|
{
|
||||||
|
NSMenu *recentMenu;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
recentMenu = [self _recentMenu];
|
||||||
|
if (!recentMenu)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't update (to keep Clear List status consistent)
|
||||||
|
[recentMenu setAutoenablesItems: NO];
|
||||||
|
[recentMenu setMenuChangedMessagesEnabled: NO];
|
||||||
|
|
||||||
|
while ([recentMenu numberOfItems] > 0)
|
||||||
|
[recentMenu removeItemAtIndex: 0]; // remove them all
|
||||||
|
|
||||||
|
for (i = [_recent_documents count]; i >= -2; i--)
|
||||||
|
{
|
||||||
|
// add all items incl. a Clear List item if needed
|
||||||
|
NSMenuItem *item;
|
||||||
|
|
||||||
|
if (i == -1)
|
||||||
|
{
|
||||||
|
if ([_recent_documents count] == 0)
|
||||||
|
continue; // skip if menu is empty
|
||||||
|
item = (NSMenuItem *) [NSMenuItem separatorItem];
|
||||||
|
// will release...
|
||||||
|
RETAIN(item);
|
||||||
|
}
|
||||||
|
else if (i == -2)
|
||||||
|
{
|
||||||
|
item = [[NSMenuItem alloc] initWithTitle: _(@"Clear List")
|
||||||
|
action: @selector(clearRecentDocuments:)
|
||||||
|
keyEquivalent: nil];
|
||||||
|
// disable for empty list
|
||||||
|
[item setEnabled: [_recent_documents count] > 0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// standard item
|
||||||
|
NSURL *u = [_recent_documents objectAtIndex: i]; // get URL
|
||||||
|
if ([u isFileURL])
|
||||||
|
item = [[NSMenuItem alloc] initWithTitle: [[u path] lastPathComponent]
|
||||||
|
action: @selector(_openRecentDocument:)
|
||||||
|
keyEquivalent:nil];
|
||||||
|
else
|
||||||
|
item = [[NSMenuItem alloc] initWithTitle: [u relativeString]
|
||||||
|
action: @selector(_openRecentDocument:)
|
||||||
|
keyEquivalent:nil];
|
||||||
|
[item setTag: i];
|
||||||
|
}
|
||||||
|
[item setTarget: self];
|
||||||
|
[recentMenu addItem: item];
|
||||||
|
RELEASE(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
[recentMenu setMenuChangedMessagesEnabled: YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) _openRecentDocument: (id)sender
|
||||||
|
{
|
||||||
|
// action to open recent document by tag index
|
||||||
|
NSURL *url;
|
||||||
|
int idx = [sender tag];
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= [_recent_documents count])
|
||||||
|
{
|
||||||
|
// something went wrong, ignore
|
||||||
|
[self _updateOpenRecentMenu];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
url = (NSURL *)[_recent_documents objectAtIndex: idx];
|
||||||
|
[self openDocumentWithContentsOfURL: url display: YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue