Bug 223703 - FileDialog.setOverwrite(boolean) does nothing on Cocoa
Summary: FileDialog.setOverwrite(boolean) does nothing on Cocoa
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.3   Edit
Hardware: Macintosh Mac OS X
: P3 normal (vote)
Target Milestone: 3.5 RC2   Edit
Assignee: Kevin Barnes CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-03-24 14:18 EDT by Carolyn MacLeod CLA
Modified: 2009-05-15 17:37 EDT (History)
5 users (show)

See Also:
carolynmacleod4: review+
steve_northover: review+


Attachments
Patch (1.57 KB, patch)
2009-05-15 08:49 EDT, Kevin Barnes CLA
no flags Details | Diff
minimal patch (1.08 KB, patch)
2009-05-15 16:45 EDT, Kevin Barnes CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Carolyn MacLeod CLA 2008-03-24 14:18:11 EDT
NSSavePanel does not have API to turn off the prompt that asks the user to confirm overwrite if the file to save already exists. This is apparently "inconsistent with Mac OS X behavior", however most other platforms let the application control whether or not to prompt before overwriting an existing file.

In order to fix bug 4727, we have added FileDialog.setOverwrite(boolean).

There does not seem to be any way to implement this new API on Cocoa except possibly to use a private method:
(BOOL)_overwriteExistingFileCheck:(NSString *)filename

Scott, do you know if this method is going to stick around a while?  :)
Comment 1 Kevin Barnes CLA 2008-03-26 09:41:04 EDT
I tried subclassing NSSavePanel and reimplementing _overwriteExistingFileCheck and found that we can prevent the prompt from appearing this way. Of course it's not API so there's no guarantee how long this will work, and we'd be breaking Apple's Human Interface Guidlines which explicitly state that users will get an application modal alert.
Comment 2 Scott Kovatch CLA 2008-03-26 12:55:04 EDT
(In reply to comment #1)
> Of course
> it's not API so there's no guarantee how long this will work, and we'd be
> breaking Apple's Human Interface Guidlines which explicitly state that users
> will get an application modal alert.

Overriding SPI is a dangerous game, but in this case I think the worst that would happen is that if the method went away it would just not work instead of crashing. You're probably okay until there's a pure-Cocoa equivalent of kNavDontConfirmReplacement, which is how this would be implemented in Carbon. I would file a bug report with Apple asking for an equivalent Cocoa API.
Comment 3 Steve Northover CLA 2008-03-26 15:17:06 EDT
Scott, go ahead and file it.  In the meantime, my vote is to subclass and override.
Comment 4 Scott Kovatch CLA 2008-09-26 16:32:08 EDT
Filed Radar 6250996 for completeness. I'm expecting it to be returned as a duplicate.
Comment 5 Kevin Barnes CLA 2009-02-06 16:16:25 EST
fixed > 20090206
Comment 6 Mike Morearty CLA 2009-05-14 18:46:30 EDT
This still reproduces for me.  I don't have an easy repro case handy, but I noticed it when attempting to verify the patch I contributed for bug 276162: My patch works on Windows and on SWT-Carbon, but does not work on SWT-Cocoa.  When I debugged it, I saw that the SWT-Cocoa version of FileDialog does have code to put in a callback if setOverwrite(true) was called, but the callback doesn't actually do anything:

int /*long*/ _overwriteExistingFileCheck(int /*long*/ id, int /*long*/ sel, int /*long*/ str) {
    return 1;
}

I suspect there is probably some code that's supposed to go in there to check for an existing file.

Another possible way to verify this, although I don't have time to try it myself, is to start with the SWT Snippet for FileDialog, add a call to dialog.setOverwrite(true) before the call to dialog.open(), and see what happens; I bet it won't ask for confirmation on SWT-Cocoa, but will on Carbon and on Windows.
Comment 7 Kevin Barnes CLA 2009-05-15 08:36:01 EDT
This works for me. The _overwriteExistingFileCheck callback will only get called if setOverwrite(true) was called before the FileDialog was opened. In open this code replaces the default method implementation with our function that always returns 1 (true).

if (overwrite) {
  callback = new Callback(this, "_overwriteExistingFileCheck", 3);
  int /*long*/ proc = callback.getAddress();
  if (proc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
  method = OS.class_getInstanceMethod(OS.class_NSSavePanel,
                                      OS.sel_overwriteExistingFileCheck);
  if (method != 0) methodImpl = OS.method_setImplementation(method, proc);
}
Comment 8 Kevin Barnes CLA 2009-05-15 08:41:03 EDT
oh... we have it backwards. 
setOverwrite(true) means prompt, not over write.
Comment 9 Kevin Barnes CLA 2009-05-15 08:49:07 EDT
Created attachment 135974 [details]
Patch
Comment 10 Kevin Barnes CLA 2009-05-15 16:45:03 EDT
Created attachment 136070 [details]
minimal patch
Comment 11 Carolyn MacLeod CLA 2009-05-15 17:22:11 EDT
The patch is good. I tested with the following snippet (in case it's useful for other reviewers...  ;)

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.events.*;

public class FileDialogOverwritePromptTest {

	public static void main(String[] args) {
		Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setLayout(new GridLayout());
		
		final Button prompt = new Button(shell, SWT.CHECK);
		prompt.setText("Overwrite Prompt");
		
		Button button = new Button(shell, SWT.PUSH);
		button.setText("Open FileDialog");
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(shell, SWT.SAVE);
				boolean p = prompt.getSelection();
				System.out.println("Setting overwrite prompt to " + p);
				dialog.setOverwrite(p);
				System.out.println(dialog.open());
				System.out.println("Overwrite prompt was " + dialog.getOverwrite());
			};
		});

		shell.pack();
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) display.sleep();
		}
	}
}
Comment 12 Kevin Barnes CLA 2009-05-15 17:37:25 EDT
fixed > 20090515