mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 06:30:55 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5102 72102866-910b-0410-8b05-ffd578937521
392 lines
9.4 KiB
Objective-C
392 lines
9.4 KiB
Objective-C
/* -*-objc-*-
|
|
NSOpenPanel.m
|
|
|
|
Standard open panel for opening files
|
|
|
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
|
|
|
Author: Scott Christley <scottc@net-community.com>
|
|
Date: 1996
|
|
|
|
Author: Daniel Bðhringer <boehring@biomed.ruhr-uni-bochum.de>
|
|
Date: August 1998
|
|
|
|
Source by Daniel Bðhringer integrated into Scott Christley's preliminary
|
|
implementation by Felipe A. Rodriguez <far@ix.netcom.com>
|
|
|
|
Author: Nicola Pero <n.pero@mi.flashnet.it>
|
|
Date: October 1999 Completely Rewritten.
|
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, write to the Free Software Foundation,
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <gnustep/gui/config.h>
|
|
#include <string.h>
|
|
#include <Foundation/NSString.h>
|
|
#include <Foundation/NSArray.h>
|
|
#include <Foundation/NSException.h>
|
|
#include <AppKit/GMArchiver.h>
|
|
#include <AppKit/IMLoading.h>
|
|
#include <AppKit/NSApplication.h>
|
|
#include <AppKit/NSBrowser.h>
|
|
#include <AppKit/NSBrowserCell.h>
|
|
#include <AppKit/NSMatrix.h>
|
|
#include <AppKit/NSOpenPanel.h>
|
|
|
|
/*
|
|
* TODO: Test Everything More, debug, make sure all delegate's methods
|
|
* are used; simplify, arrange so no code is repeated between NSOpenPanel
|
|
* and NSSavePanel; check better prompts, titles, textfield stuff.
|
|
*
|
|
*/
|
|
|
|
// Pacify the compiler
|
|
@interface NSFileManager (SavePanelExtensions)
|
|
- (NSArray *) directoryContentsAtPath: (NSString *)path showHidden: (BOOL)flag;
|
|
@end
|
|
|
|
@interface NSSavePanel (PrivateMethods)
|
|
- (void) _setDirectory: (NSString *)path updateBrowser: (BOOL)flag;
|
|
@end
|
|
//
|
|
|
|
static NSOpenPanel *_gs_gui_open_panel = nil;
|
|
|
|
@interface NSOpenPanel (PrivateMethods)
|
|
- (void) _enableOKButton;
|
|
@end
|
|
|
|
@implementation NSOpenPanel (PrivateMethods)
|
|
- (void) _enableOKButton
|
|
{
|
|
[_okButton setEnabled: YES];
|
|
}
|
|
@end
|
|
|
|
@implementation NSOpenPanel
|
|
|
|
/*
|
|
* Class methods
|
|
*/
|
|
+ (void) initialize
|
|
{
|
|
if (self == [NSOpenPanel class])
|
|
{
|
|
[self setVersion: 1];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Accessing the NSOpenPanel shared instance
|
|
*/
|
|
+ (NSOpenPanel *) openPanel
|
|
{
|
|
if (!_gs_gui_open_panel)
|
|
_gs_gui_open_panel = [[NSOpenPanel alloc] init];
|
|
|
|
[_gs_gui_open_panel setDirectory: [[NSFileManager defaultManager]
|
|
currentDirectoryPath]];
|
|
[_gs_gui_open_panel setPrompt: @"Name:"];
|
|
[_gs_gui_open_panel setTitle: @"Open"];
|
|
[_gs_gui_open_panel setRequiredFileType: @""];
|
|
[_gs_gui_open_panel setTreatsFilePackagesAsDirectories: NO];
|
|
[_gs_gui_open_panel setDelegate: nil];
|
|
[_gs_gui_open_panel setAccessoryView: nil];
|
|
[_gs_gui_open_panel setCanChooseFiles: YES];
|
|
[_gs_gui_open_panel setCanChooseDirectories: YES];
|
|
[_gs_gui_open_panel setAllowsMultipleSelection: NO];
|
|
[_gs_gui_open_panel _enableOKButton];
|
|
|
|
return _gs_gui_open_panel;
|
|
}
|
|
|
|
- (id) init
|
|
{
|
|
[super init];
|
|
_canChooseDirectories = YES;
|
|
_canChooseFiles = YES;
|
|
return self;
|
|
}
|
|
|
|
/*
|
|
* Filtering Files
|
|
*/
|
|
- (void) setAllowsMultipleSelection: (BOOL)flag
|
|
{
|
|
[_browser setAllowsMultipleSelection: flag];
|
|
}
|
|
|
|
- (BOOL) allowsMultipleSelection
|
|
{
|
|
return [_browser allowsMultipleSelection];
|
|
}
|
|
|
|
- (void) setCanChooseDirectories: (BOOL)flag
|
|
{
|
|
_canChooseDirectories = flag;
|
|
[_browser setAllowsBranchSelection: flag];
|
|
}
|
|
|
|
- (BOOL) canChooseDirectories
|
|
{
|
|
return _canChooseDirectories;
|
|
}
|
|
|
|
- (void) setCanChooseFiles: (BOOL)flag
|
|
{
|
|
_canChooseFiles = flag;
|
|
}
|
|
|
|
- (BOOL) canChooseFiles
|
|
{
|
|
return _canChooseFiles;
|
|
}
|
|
|
|
- (NSString*) filename
|
|
{
|
|
NSArray *ret;
|
|
|
|
ret = [self filenames];
|
|
|
|
if ([ret count] == 1)
|
|
return [ret objectAtIndex: 0];
|
|
else
|
|
return nil;
|
|
}
|
|
|
|
/*
|
|
* Querying the Chosen Files
|
|
*/
|
|
- (NSArray *) filenames
|
|
{
|
|
if ([_browser allowsMultipleSelection])
|
|
{
|
|
NSArray *cells = [_browser selectedCells];
|
|
NSEnumerator *cellEnum = [cells objectEnumerator];
|
|
NSBrowserCell *currCell;
|
|
NSMutableArray *ret = [NSMutableArray array];
|
|
NSString *dir = [self directory];
|
|
|
|
while ((currCell = [cellEnum nextObject]))
|
|
{
|
|
[ret addObject: [NSString stringWithFormat: @"%@/%@", dir,
|
|
[currCell stringValue]]];
|
|
}
|
|
return ret;
|
|
}
|
|
else
|
|
return [NSArray arrayWithObject: [super filename]];
|
|
}
|
|
|
|
/*
|
|
* Running the NSOpenPanel
|
|
*/
|
|
- (int) runModalForTypes: (NSArray *)fileTypes
|
|
{
|
|
return [self runModalForDirectory: nil
|
|
file: nil
|
|
types: fileTypes];
|
|
}
|
|
|
|
- (int) runModalForDirectory: (NSString *)path
|
|
file: (NSString *)name
|
|
types: (NSArray *)fileTypes
|
|
{
|
|
ASSIGN (_fileTypes, fileTypes);
|
|
|
|
if (name == nil)
|
|
name = @"";
|
|
|
|
if (path == nil)
|
|
path = @"";
|
|
|
|
if (_canChooseDirectories == NO)
|
|
{
|
|
BOOL isDir;
|
|
NSString *file = [path stringByAppendingPathComponent: name];
|
|
|
|
if ((![[NSFileManager defaultManager] fileExistsAtPath: file
|
|
isDirectory: &isDir])
|
|
|| isDir)
|
|
[_okButton setEnabled: NO];
|
|
}
|
|
|
|
return [self runModalForDirectory: path file: name];
|
|
}
|
|
|
|
/*
|
|
* NSCoding protocol
|
|
*/
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
{
|
|
[super encodeWithCoder: aCoder];
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &_canChooseDirectories];
|
|
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &_canChooseFiles];
|
|
}
|
|
|
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
|
{
|
|
[super initWithCoder: aDecoder];
|
|
|
|
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_canChooseDirectories];
|
|
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_canChooseFiles];
|
|
|
|
return self;
|
|
}
|
|
@end
|
|
//
|
|
// NSOpenPanel browser delegate methods
|
|
//
|
|
@interface NSOpenPanel (BrowserDelegate)
|
|
- (void) browser: (id)sender
|
|
createRowsForColumn: (int)column
|
|
inMatrix: (NSMatrix *)matrix;
|
|
|
|
- (BOOL) browser: (NSBrowser *)sender
|
|
selectCellWithString: (NSString *)title
|
|
inColumn: (int)column;
|
|
@end
|
|
|
|
@implementation NSOpenPanel (BrowserDelegate)
|
|
- (void) browser: (id)sender
|
|
createRowsForColumn: (int)column
|
|
inMatrix: (NSMatrix *)matrix
|
|
{
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
NSString *path = [sender pathToColumn: column], *file;
|
|
NSArray *files = [fm directoryContentsAtPath: path showHidden: NO];
|
|
NSArray *extArray = [NSArray arrayWithObjects: @"app",
|
|
@"bundle", @"debug", @"profile", nil];
|
|
unsigned i, count;
|
|
BOOL exists, isDir;
|
|
NSBrowserCell *cell;
|
|
NSString *theFile;
|
|
NSString *theExtension;
|
|
unsigned int addedRows = 0;
|
|
|
|
// if array is empty, just return (nothing to display)
|
|
if ([files lastObject] == nil)
|
|
return;
|
|
|
|
|
|
// sort list of files to display
|
|
if (_delegateHasCompareFilter == YES)
|
|
{
|
|
int compare(id elem1, id elem2, void *context)
|
|
{
|
|
return (int)[_delegate panel: self
|
|
compareFilename: elem1
|
|
with: elem2
|
|
caseSensitive: YES];
|
|
}
|
|
files = [files sortedArrayUsingFunction: compare context: nil];
|
|
}
|
|
else
|
|
files = [files sortedArrayUsingSelector: @selector(compare:)];
|
|
|
|
count = [files count];
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
theFile = [files objectAtIndex: i];
|
|
theExtension = [theFile pathExtension];
|
|
|
|
file = [path stringByAppendingPathComponent: theFile];
|
|
exists = [fm fileExistsAtPath: file
|
|
isDirectory: &isDir];
|
|
|
|
if (_treatsFilePackagesAsDirectories == NO && isDir == YES)
|
|
{
|
|
if ([extArray containsObject: theExtension])
|
|
isDir = NO;
|
|
}
|
|
|
|
if (isDir)
|
|
{
|
|
[matrix insertRow: addedRows];
|
|
cell = [matrix cellAtRow: addedRows column: 0];
|
|
[cell setStringValue: theFile];
|
|
[cell setLeaf: NO];
|
|
addedRows++;
|
|
}
|
|
else
|
|
{
|
|
if (_canChooseFiles == YES)
|
|
{
|
|
if (_fileTypes)
|
|
if ([_fileTypes containsObject: theExtension] == NO)
|
|
continue;
|
|
|
|
[matrix insertRow: addedRows];
|
|
cell = [matrix cellAtRow: addedRows column: 0];
|
|
[cell setStringValue: theFile];
|
|
[cell setLeaf: YES];
|
|
addedRows++;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
- (BOOL) browser: (NSBrowser *)sender
|
|
selectCellWithString: (NSString *)title
|
|
inColumn: (int)column
|
|
{
|
|
if (([_browser allowsMultipleSelection] == NO)
|
|
|| ([[_browser selectedCells] count] == 1))
|
|
{
|
|
[self _setDirectory: [sender pathToColumn: [_browser lastColumn]]
|
|
updateBrowser: NO];
|
|
|
|
if (_canChooseDirectories)
|
|
{
|
|
if ([[sender selectedCell] isLeaf])
|
|
{
|
|
[_form setStringValue: title];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ([[sender selectedCell] isLeaf])
|
|
{
|
|
[_form setStringValue: title];
|
|
[_okButton setEnabled: YES];
|
|
}
|
|
else
|
|
{
|
|
[_form setStringValue: nil];
|
|
[_okButton setEnabled: NO];
|
|
}
|
|
}
|
|
}
|
|
else // Multiple Selection
|
|
{
|
|
// This will be useless when NSBrowser works.
|
|
// NSBrowser, when we ask not to allow to select
|
|
// branches on multiple selections, should select only leaves
|
|
// when the user is doing a multiple selection.
|
|
// For now, use the following *unsatisfactory* hack.
|
|
// (unsatisfactory because if the user selects and then
|
|
// deselects a directory, we don't re-enable the OK button).
|
|
if (_canChooseDirectories)
|
|
if ([[sender selectedCell] isLeaf] == NO)
|
|
[_okButton setEnabled: NO];
|
|
}
|
|
return YES;
|
|
}
|
|
@end
|