From f965e69721bd0227c443779d34f13e6f4c1b4195 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 17 Dec 2018 00:26:39 +0300 Subject: [PATCH] Implement basic NSSavePanel & NSOpenPanel-s directly in Cocoa The upstream Cocotron assumes that the implementation of the file panels is provided by the display, i.e. by the native toolkit. That is what we ultimately want as well, but we're far from being there yet, and we also don't want to make any toolkit a hard requirement. So in order to have our cake and eat it too, these panel implementations are designed work entirely inside Cocoa but also let the display provide a native implementation instead if one is available. --- AppKit/CMakeLists.txt | 9 +- AppKit/NSDisplay.m | 4 + .../{ => NSSavePanel.subproj}/NSOpenPanel.m | 90 +++++++++++++----- .../{ => NSSavePanel.subproj}/NSSavePanel.m | 87 +++++++++++++---- .../_NSFileSystemDataSource.h | 8 ++ .../_NSFileSystemDataSource.m | 72 ++++++++++++++ AppKit/en.lproj/NSOpenPanel.nib | Bin 0 -> 6981 bytes AppKit/en.lproj/NSSavePanel.nib | Bin 0 -> 6981 bytes AppKit/include/AppKit/NSDisplay.h | 2 + AppKit/include/AppKit/NSSavePanel.h | 11 ++- 10 files changed, 239 insertions(+), 44 deletions(-) rename AppKit/{ => NSSavePanel.subproj}/NSOpenPanel.m (66%) rename AppKit/{ => NSSavePanel.subproj}/NSSavePanel.m (73%) create mode 100644 AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.h create mode 100644 AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.m create mode 100644 AppKit/en.lproj/NSOpenPanel.nib create mode 100644 AppKit/en.lproj/NSSavePanel.nib diff --git a/AppKit/CMakeLists.txt b/AppKit/CMakeLists.txt index 6e379d40..e4e76373 100644 --- a/AppKit/CMakeLists.txt +++ b/AppKit/CMakeLists.txt @@ -340,7 +340,6 @@ set(AppKit_sources NSDrawer.subproj/NSDrawerWindow.m NSPrinter.m - NSOpenPanel.m NSTableHeaderCell.m NSColorPanel.m NSCell.m @@ -353,7 +352,10 @@ set(AppKit_sources NSSystemInfoPanel/NSSystemInfoPanel.m - NSSavePanel.m + NSSavePanel.subproj/_NSFileSystemDataSource.m + NSSavePanel.subproj/NSOpenPanel.m + NSSavePanel.subproj/NSSavePanel.m + NSDockTile.m NSGraphics.m NSColorWell.m @@ -433,6 +435,9 @@ set(AppKit_resources en.lproj/NSFontPanel.nib en.lproj/NSFontPanel.nib/keyedobjects.nib en.lproj/NSSystemInfoPanel.nib NSSystemInfoPanel/en.lproj/NSSystemInfoPanel.nib/keyedobjects.nib en.lproj/NSToolbarCustomizationPalette.nib en.lproj/NSToolbarCustomizationPalette.nib/keyedobjects.nib + + en.lproj/NSSavePanel.nib en.lproj/NSSavePanel.nib + en.lproj/NSOpenPanel.nib en.lproj/NSOpenPanel.nib ) add_framework(AppKit diff --git a/AppKit/NSDisplay.m b/AppKit/NSDisplay.m index a58eff43..e83a89c8 100644 --- a/AppKit/NSDisplay.m +++ b/AppKit/NSDisplay.m @@ -246,6 +246,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI return nil; } +- (BOOL) implementsCustomPanelForClass: (Class) panelClass { + return NO; +} + -(int)savePanel:(NSSavePanel *)savePanel runModalForDirectory:(NSString *)directory file:(NSString *)file { NSInvalidAbstractInvocation(); return 0; diff --git a/AppKit/NSOpenPanel.m b/AppKit/NSSavePanel.subproj/NSOpenPanel.m similarity index 66% rename from AppKit/NSOpenPanel.m rename to AppKit/NSSavePanel.subproj/NSOpenPanel.m index 72022a12..d0292926 100644 --- a/AppKit/NSOpenPanel.m +++ b/AppKit/NSSavePanel.subproj/NSOpenPanel.m @@ -10,26 +10,50 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #import #import -@interface NSSavePanel (Private) +@interface NSSavePanel (Private) -(void)_setFilename:(NSString*)filename; @end @implementation NSOpenPanel -+(NSOpenPanel *)openPanel { - return [[self new] autorelease]; +- (id) resetToDefaultValues { + self = [super resetToDefaultValues]; + _filenames=[NSArray new]; + [_dialogTitle release]; + _dialogTitle= [NSLocalizedStringFromTableInBundle(@"Open", nil, [NSBundle bundleForClass: [NSOpenPanel class]], @"The title of the open panel") copy]; + _allowsMultipleSelection=NO; + _canChooseDirectories=NO; + _canChooseFiles=YES; + _resolvesAliases=YES; + return self; } --init { - [super init]; - _filenames=[NSArray new]; - [_dialogTitle release]; - _dialogTitle= [NSLocalizedStringFromTableInBundle(@"Open", nil, [NSBundle bundleForClass: [NSOpenPanel class]], @"The title of the open panel") copy]; - _allowsMultipleSelection=NO; - _canChooseDirectories=NO; - _canChooseFiles=YES; - _resolvesAliases=YES; - return self; +static NSOpenPanel *_newPanel = nil; + ++ (void) set_newPanel: (NSOpenPanel *) newPanel { + _newPanel = newPanel; +} + ++ (NSSavePanel *) openPanel { + if ([[NSDisplay currentDisplay] implementsCustomPanelForClass: self]) + { + _newPanel = [[self alloc] + initWithContentRect: NSMakeRect(0, 0, 1, 1) + styleMask: NSTitledWindowMask|NSResizableWindowMask + backing: NSBackingStoreBuffered + defer: YES]; + } + else + { + [NSBundle loadNibNamed: @"NSOpenPanel" owner: self]; + } + // FIXME: release it? + return [_newPanel resetToDefaultValues]; +} + +- init { + [self release]; + return [[NSOpenPanel openPanel] retain]; } -(void)dealloc { @@ -50,29 +74,49 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI NSArray *paths=[self filenames]; NSMutableArray *result=[NSMutableArray arrayWithCapacity:[paths count]]; int i,count=[paths count]; - + for(i=0;i #import #import @@ -13,20 +14,42 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI @implementation NSSavePanel -+(NSSavePanel *)savePanel { - return [[self new] autorelease]; +- (id) resetToDefaultValues { + _dialogTitle=@"Save"; + _filename=@""; + _directory=[NSHomeDirectory() copy]; + _requiredFileType=@""; + _treatsFilePackagesAsDirectories=NO; + _accessoryView=nil; + return self; +} + +static NSSavePanel *_newPanel = nil; + ++ (void) set_newPanel: (NSSavePanel *) newPanel { + _newPanel = newPanel; +} + ++ (NSSavePanel *) savePanel { + if ([[NSDisplay currentDisplay] implementsCustomPanelForClass: self]) + { + _newPanel = [[self alloc] + initWithContentRect: NSMakeRect(0, 0, 1, 1) + styleMask: NSTitledWindowMask|NSResizableWindowMask + backing: NSBackingStoreBuffered + defer: YES]; + } + else + { + [NSBundle loadNibNamed: @"NSSavePanel" owner: self]; + } + // FIXME: release it? + return [_newPanel resetToDefaultValues]; } -init { - [super initWithContentRect:NSMakeRect(0,0,1,1) styleMask:NSTitledWindowMask|NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES]; - - _dialogTitle=@"Save"; - _filename=@""; - _directory=[NSHomeDirectory() copy]; - _requiredFileType=@""; - _treatsFilePackagesAsDirectories=NO; - _accessoryView=nil; - return self; + [self release]; + return [[NSSavePanel savePanel] retain]; } -(void)dealloc { @@ -63,14 +86,37 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI return ret; } --(int)runModalForDirectory:(NSString *)directory file:(NSString *)file { - [self _setFilename:file]; - [self setDirectory:directory]; - return [[NSDisplay currentDisplay] savePanel:self runModalForDirectory:directory file:file]; +- (IBAction) _selectFile: (id) sender { + NSURL *url = [_outlineView itemAtRow: [_outlineView selectedRow]]; + [self _setFilename: [url path]]; + + [NSApp stopModalWithCode: NSOKButton]; } --(int)runModal { - return [[NSDisplay currentDisplay] savePanel:self runModalForDirectory:[self directory] file:@""]; +- (IBAction) _cancel: (id) sender { + [NSApp stopModalWithCode: NSCancelButton]; +} + +- (NSInteger) runModalForDirectory: (NSString *) directory + file: (NSString *) file { + [self _setFilename: file]; + [self setDirectory: directory]; + + return [self runModal]; +} + +- (NSInteger) runModal { + NSInteger res; + if ([[NSDisplay currentDisplay] implementsCustomPanelForClass: [self class]]) + { + res = [[NSDisplay currentDisplay] savePanel: self + runModalForDirectory: [self directory] + file: [self filename]]; + } else { + res = [NSApp runModalForWindow: self]; + [self close]; + } + return res; } -(NSString *)directory { @@ -176,7 +222,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI } -(void)setAllowedFileTypes:(NSArray *)value { - NSUnimplementedMethod(); + [_allowedFileTypes release]; + _allowedFileTypes = [value copy]; +} + +- (NSArray *) allowedFileTypes { + return [[_allowedFileTypes copy] autorelease]; } -(void)setAllowsOtherFileTypes:(BOOL)value { diff --git a/AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.h b/AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.h new file mode 100644 index 00000000..033531d1 --- /dev/null +++ b/AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.h @@ -0,0 +1,8 @@ +#import + +@interface _NSFileSystemDataSource : NSObject { + NSMutableSet *_cachedPaths; + NSFileManager *_fileManager; +} + +@end diff --git a/AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.m b/AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.m new file mode 100644 index 00000000..4594a7a6 --- /dev/null +++ b/AppKit/NSSavePanel.subproj/_NSFileSystemDataSource.m @@ -0,0 +1,72 @@ +#import "_NSFileSystemDataSource.h" +#import + +@implementation _NSFileSystemDataSource + +- (id) init { + self = [super init]; + _cachedPaths = [[NSMutableSet alloc] init]; + _fileManager = [[NSFileManager defaultManager] retain]; + return self; +} + +- (void) dealloc { + [_cachedPaths release]; + [_fileManager release]; + [super dealloc]; +} + +- (NSInteger) outlineView: (NSOutlineView *) outlineView + numberOfChildrenOfItem: (NSURL *) url { + + if (url == nil) { + url = [NSURL URLWithString: @"/"]; + } + return [[_fileManager contentsOfDirectoryAtURL: url + includingPropertiesForKeys: nil + options: 0 + error: nil] count]; +} + +- (BOOL) outlineView: (NSOutlineView *) outlineView + isItemExpandable: (NSURL *) url { + + if (url == nil) { + return YES; + } + + BOOL isDirectory; + [_fileManager fileExistsAtPath: [url path] isDirectory: &isDirectory]; + return isDirectory; +} + +- (NSURL *) outlineView: (NSOutlineView *) outlineView + child: (NSInteger) index + ofItem: (NSURL *) url { + + if (url == nil) { + url = [NSURL URLWithString: @"/"]; + } + NSArray *items = [_fileManager contentsOfDirectoryAtURL: url + includingPropertiesForKeys: nil + options: 0 + error: nil]; + // TODO: sort + NSURL *preRes = [items objectAtIndex: index]; + NSURL *res = [_cachedPaths member: preRes]; + if (res == nil) { + [_cachedPaths addObject: preRes]; + res = preRes; + } + + return res; +} + +- (NSString *) outlineView: (NSOutlineView *) outlineView + objectValueForTableColumn: (NSTableColumn *) tableColumn + byItem: (NSURL *) url { + + return [[url pathComponents] lastObject]; +} + +@end diff --git a/AppKit/en.lproj/NSOpenPanel.nib b/AppKit/en.lproj/NSOpenPanel.nib new file mode 100644 index 0000000000000000000000000000000000000000..a6dc86e2dbda83fcfb2ab3ed032fb8045ab58b52 GIT binary patch literal 6981 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 H%9;NF#epkV literal 0 HcmV?d00001 diff --git a/AppKit/include/AppKit/NSDisplay.h b/AppKit/include/AppKit/NSDisplay.h index abac63bb..cd4885ce 100644 --- a/AppKit/include/AppKit/NSDisplay.h +++ b/AppKit/include/AppKit/NSDisplay.h @@ -59,6 +59,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI - (CGContextRef)graphicsPortForPrintOperationWithView:(NSView *)view printInfo:(NSPrintInfo *)printInfo pageRange:(NSRange)pageRange; +- (BOOL) implementsCustomPanelForClass: (Class) panelClass; + - (int)savePanel:(NSSavePanel *)savePanel runModalForDirectory:(NSString *)directory file:(NSString *)file; - (int)openPanel:(NSOpenPanel *)openPanel runModalForDirectory:(NSString *)directory file:(NSString *)file types:(NSArray *)types; diff --git a/AppKit/include/AppKit/NSSavePanel.h b/AppKit/include/AppKit/NSSavePanel.h index 61b9f084..7a859fb5 100644 --- a/AppKit/include/AppKit/NSSavePanel.h +++ b/AppKit/include/AppKit/NSSavePanel.h @@ -7,8 +7,9 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import +#import -@class NSView; +@class NSView, NSOutlineView; enum { NSFileHandlingPanelCancelButton = NSCancelButton, @@ -21,11 +22,14 @@ enum { NSString *_filename; NSString *_directory; NSString *_requiredFileType; + NSArray *_allowedFileTypes; NSString *_message; NSString *_prompt; BOOL _treatsFilePackagesAsDirectories; NSView *_accessoryView; + + IBOutlet NSOutlineView *_outlineView; } + (NSSavePanel *)savePanel; @@ -47,6 +51,8 @@ enum { - (void)setRequiredFileType:(NSString *)type; - (void)setTreatsFilePackagesAsDirectories:(BOOL)flag; +- (NSArray *) allowedFileTypes; + - (void)setAccessoryView:(NSView *)view; - (void)setCanCreateDirectories:(BOOL)value; - (void)setAllowedFileTypes:(NSArray *)value; @@ -64,4 +70,7 @@ enum { modalDelegate:(id)modalDelegate didEndSelector:(SEL)didEndSelector contextInfo:(void *)contextInfo; + +- (IBAction) _selectFile: (id) sender; +- (IBAction) _cancel: (id) sender; @end