diff --git a/ChangeLog b/ChangeLog index eaf49eca1..a3ad32a83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-10-27 Richard Frith-Macdonald + + * Source/NSOpenPanel.m: Allow users to type in an absolute path name. + Support DnD of filename into panel. + * Source/NSSavePanel.m: ditto. Also, if the name of a non-existent + directory is typed in, provide a prompt to create the directory as + in NeXTstep/OPENSTEP. + 2003-10-27 Richard Frith-Macdonald * Source/GSServicesManager.m: Tidy last patch to match use of diff --git a/Source/NSOpenPanel.m b/Source/NSOpenPanel.m index 2ee015ded..db5836f72 100644 --- a/Source/NSOpenPanel.m +++ b/Source/NSOpenPanel.m @@ -104,10 +104,10 @@ static NSOpenPanel *_gs_gui_open_panel = nil; { NSMatrix *matrix; - if(column == -1) + if (column == -1) return; - matrix = [_browser matrixInColumn:column]; + matrix = [_browser matrixInColumn: column]; if ([_browser allowsMultipleSelection]) { @@ -115,41 +115,41 @@ static NSOpenPanel *_gs_gui_open_panel = nil; selectedCells = [matrix selectedCells]; - if([selectedCells count] <= 1) + if ([selectedCells count] <= 1) { - if(_canChooseDirectories == NO || + if (_canChooseDirectories == NO || [[matrix selectedCell] isLeaf] == YES) - [super _selectTextInColumn:column]; + [super _selectTextInColumn: column]; else { - [self _selectCellName:[[_form cellAtIndex: 0] stringValue]]; - // [_form selectTextAtIndex:0]; - [_okButton setEnabled:YES]; + [self _selectCellName: [[_form cellAtIndex: 0] stringValue]]; + // [_form selectTextAtIndex: 0]; + [_okButton setEnabled: YES]; } } else { [_form abortEditing]; [[_form cellAtIndex: 0] setStringValue:@""]; - // [_form selectTextAtIndex:0]; - [_form setNeedsDisplay:YES]; - [_okButton setEnabled:YES]; + // [_form selectTextAtIndex: 0]; + [_form setNeedsDisplay: YES]; + [_okButton setEnabled: YES]; } } else { - if(_canChooseDirectories == NO || [[matrix selectedCell] isLeaf] == YES) - [super _selectTextInColumn:column]; + if (_canChooseDirectories == NO || [[matrix selectedCell] isLeaf] == YES) + [super _selectTextInColumn: column]; else { - if([[[_form cellAtIndex: 0] stringValue] length] > 0) + if ([[[_form cellAtIndex: 0] stringValue] length] > 0) { - [self _selectCellName:[[_form cellAtIndex: 0] stringValue]]; - // [_form selectTextAtIndex:0]; - [_form setNeedsDisplay:YES]; + [self _selectCellName: [[_form cellAtIndex: 0] stringValue]]; + // [_form selectTextAtIndex: 0]; + [_form setNeedsDisplay: YES]; } - [_okButton setEnabled:YES]; + [_okButton setEnabled: YES]; } } } @@ -163,14 +163,14 @@ static NSOpenPanel *_gs_gui_open_panel = nil; NSRange range; int i, titleLength, cellLength, numberOfCells; - matrix = [_browser matrixInColumn:[_browser lastColumn]]; - if([matrix selectedCell]) + matrix = [_browser matrixInColumn: [_browser lastColumn]]; + if ([matrix selectedCell]) return; titleLength = [title length]; - if(!titleLength) + if (!titleLength) { - [_okButton setEnabled:NO]; + [_okButton setEnabled: NO]; return; } @@ -180,25 +180,25 @@ static NSOpenPanel *_gs_gui_open_panel = nil; cells = [matrix cells]; numberOfCells = [cells count]; - for(i = 0; i < numberOfCells; i++) + for (i = 0; i < numberOfCells; i++) { - cellString = [[matrix cellAtRow:i column:0] stringValue]; + cellString = [[matrix cellAtRow: i column: 0] stringValue]; cellLength = [cellString length]; - if(cellLength < titleLength) + if (cellLength < titleLength) continue; - result = [self _compareFilename:[cellString substringWithRange:range] - with:title]; + result = [self _compareFilename: [cellString substringWithRange: range] + with: title]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) { - [matrix selectCellAtRow:i column:0]; - [matrix scrollCellToVisibleAtRow:i column:0]; - [_okButton setEnabled:YES]; + [matrix selectCellAtRow: i column: 0]; + [matrix scrollCellToVisibleAtRow: i column: 0]; + [_okButton setEnabled: YES]; return; } - else if(result == NSOrderedDescending) + else if (result == NSOrderedDescending) break; } } @@ -215,13 +215,13 @@ static NSOpenPanel *_gs_gui_open_panel = nil; if (filename == nil) filename = @""; - else if([filename isEqual: @""] == NO) + else if ([filename isEqual: @""] == NO) [_okButton setEnabled: YES]; if (_canChooseDirectories == NO) { - if([_browser allowsMultipleSelection] == YES) - [_browser setAllowsBranchSelection:NO]; + if ([_browser allowsMultipleSelection] == YES) + [_browser setAllowsBranchSelection: NO]; } [super _setupForDirectory: path file: filename]; @@ -430,11 +430,11 @@ static NSOpenPanel *_gs_gui_open_panel = nil; /** Displays the open panel in a modal session, with the directory path shown and file name (if any) selected. Files are filtered for the specified types. If the directory is nil, then the directory shown in - the opena panel is the last directory selected. + the open panel is the last directory selected. */ - (int) runModalForDirectory: (NSString *)path file: (NSString *)name - types: (NSArray *)fileTypes + types: (NSArray *)fileTypes { ASSIGN (_fileTypes, fileTypes); @@ -442,10 +442,10 @@ static NSOpenPanel *_gs_gui_open_panel = nil; file: name]; } -- (int)runModalForDirectory:(NSString *)path - file:(NSString *)name - types:(NSArray *)fileTypes - relativeToWindow:(NSWindow*)window +- (int) runModalForDirectory: (NSString *)path + file: (NSString *)name + types: (NSArray *)fileTypes + relativeToWindow: (NSWindow*)window { ASSIGN (_fileTypes, fileTypes); @@ -454,22 +454,22 @@ static NSOpenPanel *_gs_gui_open_panel = nil; relativeToWindow: window]; } -- (void)beginSheetForDirectory:(NSString *)path - file:(NSString *)name - types:(NSArray *)fileTypes - modalForWindow:(NSWindow *)docWindow - modalDelegate:(id)delegate - didEndSelector:(SEL)didEndSelector - contextInfo:(void *)contextInfo +- (void) beginSheetForDirectory: (NSString *)path + file: (NSString *)name + types: (NSArray *)fileTypes + modalForWindow: (NSWindow *)docWindow + modalDelegate: (id)delegate + didEndSelector: (SEL)didEndSelector + contextInfo: (void *)contextInfo { ASSIGN (_fileTypes, fileTypes); [self beginSheetForDirectory: path - file: name - modalForWindow: docWindow - modalDelegate: delegate - didEndSelector: didEndSelector - contextInfo: contextInfo]; + file: name + modalForWindow: docWindow + modalDelegate: delegate + didEndSelector: didEndSelector + contextInfo: contextInfo]; } - (void) ok: (id)sender @@ -478,6 +478,7 @@ static NSOpenPanel *_gs_gui_open_panel = nil; NSBrowserCell *selectedCell = nil; NSArray *selectedCells = nil; int selectedColumn, lastColumn; + NSString *tmp; selectedColumn = [_browser selectedColumn]; lastColumn = [_browser lastColumn]; @@ -489,8 +490,7 @@ static NSOpenPanel *_gs_gui_open_panel = nil; { selectedCells = [matrix selectedCells]; - if (selectedColumn == lastColumn && - [selectedCells count] == 1) + if (selectedColumn == lastColumn && [selectedCells count] == 1) selectedCell = [selectedCells objectAtIndex: 0]; } else @@ -518,21 +518,29 @@ static NSOpenPanel *_gs_gui_open_panel = nil; } } else if (_canChooseDirectories == NO - && (![_browser allowsMultipleSelection] || !selectedCells - || selectedColumn != lastColumn || ![selectedCells count])) + && (![_browser allowsMultipleSelection] || !selectedCells + || selectedColumn != lastColumn || ![selectedCells count])) { [_form selectTextAtIndex: 0]; [_form setNeedsDisplay: YES]; return; } - ASSIGN (_directory, [_browser pathToColumn:[_browser lastColumn]]); + ASSIGN (_directory, [_browser pathToColumn: [_browser lastColumn]]); + if (selectedCell) - ASSIGN (_fullFileName, [_directory stringByAppendingPathComponent: - [selectedCell stringValue]]); + tmp = [selectedCell stringValue]; else - ASSIGN (_fullFileName, [_directory stringByAppendingPathComponent: - [[_form cellAtIndex: 0] stringValue]]); + tmp = [[_form cellAtIndex: 0] stringValue]; + + if ([tmp isAbsolutePath] == YES) + { + ASSIGN (_fullFileName, tmp); + } + else + { + ASSIGN (_fullFileName, [_directory stringByAppendingPathComponent: tmp]); + } if (_delegateHasValidNameFilter) { @@ -550,6 +558,7 @@ static NSOpenPanel *_gs_gui_open_panel = nil; _OKButtonPressed = YES; [NSApp stopModal]; + [self close]; } @@ -604,17 +613,26 @@ static NSOpenPanel *_gs_gui_open_panel = nil; NSComparisonResult result; NSRange range; - matrix = [_browser matrixInColumn: [_browser lastColumn]]; s = [[[aNotification userInfo] objectForKey: @"NSFieldEditor"] string]; + /* + * If the user typed in an absolute path, display it. + */ + if ([s isAbsolutePath] == YES) + { + [self setDirectory: s]; + } + sLength = [s length]; range.location = 0; range.length = sLength; - if(sLength == 0) + matrix = [_browser matrixInColumn: [_browser lastColumn]]; + + if (sLength == 0) { [matrix deselectAllCells]; - if(_canChooseDirectories == NO) + if (_canChooseDirectories == NO) [_okButton setEnabled: NO]; return; } @@ -624,20 +642,20 @@ static NSOpenPanel *_gs_gui_open_panel = nil; selectedRow = [matrix selectedRow]; cells = [matrix cells]; - if(selectedString) + if (selectedString) { cellLength = [selectedString length]; - if(cellLength < sLength) + if (cellLength < sLength) range.length = cellLength; result = [selectedString compare: s options: 0 range: range]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) return; - else if(result == NSOrderedAscending) + else if (result == NSOrderedAscending) result = NSOrderedDescending; - else if(result == NSOrderedDescending) + else if (result == NSOrderedDescending) result = NSOrderedAscending; range.length = sLength; @@ -645,21 +663,21 @@ static NSOpenPanel *_gs_gui_open_panel = nil; else result = NSOrderedDescending; - if(result == NSOrderedDescending) + if (result == NSOrderedDescending) { int numberOfCells = [cells count]; - for(i = selectedRow+1; i < numberOfCells; i++) + for (i = selectedRow+1; i < numberOfCells; i++) { selectedString = [[matrix cellAtRow: i column: 0] stringValue]; cellLength = [selectedString length]; - if(cellLength < sLength) + if (cellLength < sLength) continue; result = [selectedString compare: s options: 0 range: range]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) { [matrix deselectAllCells]; [matrix selectCellAtRow: i column: 0]; @@ -671,17 +689,17 @@ static NSOpenPanel *_gs_gui_open_panel = nil; } else { - for(i = selectedRow; i >= 0; --i) + for (i = selectedRow; i >= 0; --i) { selectedString = [[matrix cellAtRow: i column: 0] stringValue]; cellLength = [selectedString length]; - if(cellLength < sLength) + if (cellLength < sLength) continue; result = [selectedString compare: s options: 0 range: range]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) { [matrix deselectAllCells]; [matrix selectCellAtRow: i column: 0]; diff --git a/Source/NSSavePanel.m b/Source/NSSavePanel.m index 37fa4a824..3f9c9292e 100644 --- a/Source/NSSavePanel.m +++ b/Source/NSSavePanel.m @@ -48,6 +48,8 @@ #include "AppKit/NSImage.h" #include "AppKit/NSImageView.h" #include "AppKit/NSMatrix.h" +#include "AppKit/NSPasteboard.h" +#include "AppKit/NSDragging.h" #include "AppKit/NSSavePanel.h" #include "AppKit/NSTextField.h" #include "AppKit/NSWorkspace.h" @@ -90,6 +92,64 @@ static BOOL _gs_display_reading_progress = NO; - (NSComparisonResult) _compareFilename: (NSString *)n1 with: (NSString *)n2; @end /* NSSavePanel (PrivateMethods) */ +@interface PanelView : NSView +{ + NSSavePanel *owner; +} +- (id) initWithFrame: (NSRect)r owner: (NSSavePanel*)p; +- (BOOL) performDragOperation: (id)sender; +- (BOOL) prepareForDragOperation: (id)sender; +@end + +@implementation PanelView + +- (unsigned int) draggingEntered: (id )sender +{ + NSPasteboard *pb; + + pb = [sender draggingPasteboard]; + if ([[pb types] indexOfObject: NSFilenamesPboardType] == NSNotFound) + { + return NSDragOperationNone; + } + return NSDragOperationAll; +} + +- (id) initWithFrame: (NSRect)r owner: (NSSavePanel*)p +{ + if ((self = [super initWithFrame: r]) != nil) + { + owner = p; + [self registerForDraggedTypes: [NSArray arrayWithObjects: + NSFilenamesPboardType, nil]]; + } + return self; +} + +- (BOOL) performDragOperation: (id)sender +{ + NSArray *types; + NSPasteboard *dragPb; + + dragPb = [sender draggingPasteboard]; + types = [dragPb types]; + if ([types containsObject: NSFilenamesPboardType] == YES) + { + NSArray *names = [dragPb propertyListForType: NSFilenamesPboardType]; + NSString *file = [names lastObject]; + + [owner setDirectory: file]; + return YES; + } + return NO; +} + +- (BOOL) prepareForDragOperation: (id)sender +{ + return YES; +} +@end + @implementation NSSavePanel (_PrivateMethods) -(id) _initWithoutGModel { @@ -98,6 +158,7 @@ static BOOL _gs_display_reading_progress = NO; NSImage *image; NSRect r; id lastKeyView; + id panelView; // Track window resizing so we can change number of browser columns. [[NSNotificationCenter defaultCenter] addObserver: self @@ -114,10 +175,15 @@ static BOOL _gs_display_reading_progress = NO; styleMask: (NSTitledWindowMask | NSResizableWindowMask) backing: 2 defer: YES]; [self setMinSize: [self frame].size]; - [[self contentView] setBounds: NSMakeRect (0, 0, 308, 317)]; + + r = NSMakeRect (0, 0, 308, 317); + panelView = [[PanelView alloc] initWithFrame: r owner: self]; + [self setContentView: panelView]; + RELEASE(panelView); + [[self contentView] setBounds: r]; r = NSMakeRect (0, 64, 308, 245); - _topView = [[NSView alloc] initWithFrame: r]; + _topView = [[PanelView alloc] initWithFrame: r owner: self]; [_topView setBounds: r]; [_topView setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [_topView setAutoresizesSubviews: YES]; @@ -125,7 +191,7 @@ static BOOL _gs_display_reading_progress = NO; [_topView release]; r = NSMakeRect (0, 0, 308, 64); - _bottomView = [[NSView alloc] initWithFrame: r]; + _bottomView = [[PanelView alloc] initWithFrame: r owner: self]; [_bottomView setBounds: r]; [_bottomView setAutoresizingMask: NSViewWidthSizable|NSViewMaxYMargin]; [_bottomView setAutoresizesSubviews: YES]; @@ -333,7 +399,7 @@ static BOOL _gs_display_reading_progress = NO; NSBrowserCell *selectedCell; BOOL isLeaf; - if(column == -1) + if (column == -1) return; matrix = [_browser matrixInColumn:column]; @@ -349,7 +415,7 @@ static BOOL _gs_display_reading_progress = NO; } else { - if([[[_form cellAtIndex: 0] stringValue] length] > 0) + if ([[[_form cellAtIndex: 0] stringValue] length] > 0) { [_okButton setEnabled:YES]; [self _selectCellName:[[_form cellAtIndex: 0] stringValue]]; @@ -375,34 +441,34 @@ static BOOL _gs_display_reading_progress = NO; int i, titleLength, cellLength, numberOfCells; matrix = [_browser matrixInColumn:[_browser lastColumn]]; - if([matrix selectedCell]) + if ([matrix selectedCell]) return; titleLength = [title length]; - if(!titleLength) + if (!titleLength) return; cells = [matrix cells]; numberOfCells = [cells count]; - for(i = 0; i < numberOfCells; i++) + for (i = 0; i < numberOfCells; i++) { cellString = [[matrix cellAtRow:i column:0] stringValue]; cellLength = [cellString length]; - if(cellLength != titleLength) + if (cellLength != titleLength) continue; result = [self _compareFilename:cellString with:title]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) { [matrix selectCellAtRow:i column:0]; [matrix scrollCellToVisibleAtRow:i column:0]; [_okButton setEnabled:YES]; return; } - else if(result == NSOrderedDescending) + else if (result == NSOrderedDescending) break; } } @@ -939,6 +1005,7 @@ selectCellWithString: (NSString*)title NSMatrix *matrix; NSBrowserCell *selectedCell; NSString *filename; + BOOL isDir = NO; matrix = [_browser matrixInColumn: [_browser lastColumn]]; selectedCell = [matrix selectedCell]; @@ -976,9 +1043,50 @@ selectCellWithString: (NSString*)title } ASSIGN (_directory, [_browser pathToColumn:[_browser lastColumn]]); - ASSIGN (_fullFileName, [_directory stringByAppendingPathComponent: - [[_form cellAtIndex: 0] stringValue]]); + filename = [[_form cellAtIndex: 0] stringValue]; + if ([filename isAbsolutePath] == YES) + { + ASSIGN (_fullFileName, filename); + } + else + { + ASSIGN (_fullFileName, [_directory stringByAppendingPathComponent: + filename]); + } + filename = [_fullFileName stringByDeletingLastPathComponent]; + if ([_fm fileExistsAtPath: filename isDirectory: &isDir] == NO) + { + int result; + + result = NSRunAlertPanel(_(@"Save"), + _(@"The directory '%@' does not exist, do you want to create it?"), + _(@"Yes"), _(@"No"), nil, + filename + ); + + if (result == NSAlertDefaultReturn) + { + if ([_fm createDirectoryAtPath: filename attributes: nil] == NO) + { + NSRunAlertPanel(_(@"Save"), + _(@"The directory '%@' could not be created."), + _(@"Dismiss"), nil, nil, + filename + ); + return; + } + } + } + else if (isDir == NO) + { + NSRunAlertPanel(_(@"Save"), + _(@"The path '%@' is not a directory."), + _(@"Dismiss"), nil, nil, + filename + ); + return; + } if ([_fm fileExistsAtPath: [self filename] isDirectory: NULL]) { int result; @@ -1433,14 +1541,22 @@ createRowsForColumn: (int)column NSComparisonResult result; NSRange range; - matrix = [_browser matrixInColumn:[_browser lastColumn]]; s = [[[aNotification userInfo] objectForKey:@"NSFieldEditor"] string]; + /* + * If the user typed in an absolute path, display it. + */ + if ([s isAbsolutePath] == YES) + { + [self setDirectory: s]; + } + sLength = [s length]; range.location = 0; range.length = sLength; - if(sLength == 0) + matrix = [_browser matrixInColumn:[_browser lastColumn]]; + if (sLength == 0) { [matrix deselectAllCells]; [_okButton setEnabled:NO]; @@ -1452,31 +1568,31 @@ createRowsForColumn: (int)column selectedRow = [matrix selectedRow]; cells = [matrix cells]; - if(selectedString) + if (selectedString) { result = [s compare:selectedString options:0 range:range]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) return; } else result = NSOrderedDescending; - if(result == NSOrderedDescending) + if (result == NSOrderedDescending) { int numberOfCells = [cells count]; - for(i = selectedRow+1; i < numberOfCells; i++) + for (i = selectedRow+1; i < numberOfCells; i++) { selectedString = [[matrix cellAtRow:i column:0] stringValue]; cellLength = [selectedString length]; - if(cellLength != sLength) + if (cellLength != sLength) continue; result = [selectedString compare:s options:0 range:range]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) { [matrix deselectAllCells]; [matrix selectCellAtRow:i column:0]; @@ -1488,17 +1604,17 @@ createRowsForColumn: (int)column } else { - for(i = selectedRow; i >= 0; --i) + for (i = selectedRow; i >= 0; --i) { selectedString = [[matrix cellAtRow:i column:0] stringValue]; cellLength = [selectedString length]; - if(cellLength != sLength) + if (cellLength != sLength) continue; result = [selectedString compare:s options:0 range:range]; - if(result == NSOrderedSame) + if (result == NSOrderedSame) { [matrix deselectAllCells]; [matrix selectCellAtRow:i column:0];