Bug 22621 - [Dialogs] Order of dialog buttons is wrong on MacOS X
Summary: [Dialogs] Order of dialog buttons is wrong on MacOS X
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 2.1   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P2 major (vote)
Target Milestone: 2.1 M3   Edit
Assignee: Nick Edgar CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-08-21 05:12 EDT by Andre Weinand CLA
Modified: 2002-11-12 01:49 EST (History)
2 users (show)

See Also:


Attachments
The two methods to add to JFace/Dialog (1.65 KB, patch)
2002-10-31 11:57 EST, Andre Weinand CLA
no flags Details | Diff
Revised code (1.40 KB, patch)
2002-11-01 11:37 EST, Andre Weinand CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andre Weinand CLA 2002-08-21 05:12:31 EDT
The MacOS X user interface guidelines dictate a specific order for buttons in dialogs: 
"The default button for dismissing a dialog should go in the lower-right corner. If there's a 
Cancel button, it should be to the left of the default button"
The SWT native Message dialogs adhere to these guidelines, in JFace dialogs however 
the order is backwards.
Comment 1 Tod Creasey CLA 2002-08-27 08:34:40 EDT
The issue here is if we want to change the look of Eclipse platform by 
platform. This is something that should be addressed by the Architecture team.
Comment 2 Andre Weinand CLA 2002-08-27 08:47:08 EDT
I think the issue is not only whether to change the look of the Eclipse platform.

In this case it is just dangerous to have an inconsistent order of buttons within Eclipse 
itself: the native MessageDialogs have the correct order, the "emulated" JFace dialogs 
have the wrong order. And we are using both in Eclipse.
Comment 3 Kevin Haaland CLA 2002-08-27 08:49:08 EDT
Similiar issues have come up on other platforms as well. Need to balance the 
desire to honour the platform conventions with learning (and documenting, 
training etc) a new user interface. 

Agree that this is something that needs to be addressed. 

Suggest makting this a high priority enhancement. Andre you are familiar with 
the Mac community. What do you feel the priority of his request is?
Comment 4 Andre Weinand CLA 2002-08-27 09:05:52 EDT
This request has probably the highest priority of all current MacOS X problems.
Because you can loose work by pressing the wrong button, I would consider this problem 
"major". 
Comment 5 Nick Edgar CLA 2002-10-29 09:58:12 EST
Andre, would you be willing to make and submit the changes for this?
Chris is occupied with other things at the moment.

The easiest thing to do is change how the button layout is done in Dialog to 
put the default button last, rather than making platform-specific changes to 
the order of createButton calls in many subclasses.  But this assumes that we 
can use general heuristics to make the right choice.

What is the preferred order if the Help button is included as well?
What about the multi-step wizards like the import/export dialogs, where Next or 
Finish is the default button?  Presumably the order should not change here.
Comment 6 Andre Weinand CLA 2002-10-31 11:56:27 EST
The fix for Dialog is these two methods (or the attached patch). I'm using it for two days 
now without any problems. On all non-Mac platforms it has no effect at all.

/*
 * @see Window.initializeBounds()
 */
protected void initializeBounds() {
	String platform= SWT.getPlatform();
	if ("carbon".equals(platform)) {	//$NON-NLS-1$
		// On Mac OS X the default button must be the right-most button
		Shell shell= getShell();
		if (shell != null) {
			Button defaultButton= shell.getDefaultButton();
			if (defaultButton != null && isContained(buttonBar, defaultButton)) {
				Composite container= defaultButton.getParent();
				defaultButton.moveBelow(null);
			}
		}
	}
	
	super.initializeBounds();
}

/**
 * Returns true if the given Control c is a direct or indirect child of
 * container.
 */
private boolean isContained(Control container, Control c) {
	if (container instanceof Composite) {
		Composite composite= (Composite) container;
		Control[] children= composite.getChildren();
		if (children != null) {
			for (int i= 0; i < children.length; i++) {
				Control child= children[i];
				if (child == c || isContained(child, c))
					return true;
			}
		}
	}
	return false;
}

Comment 7 Andre Weinand CLA 2002-10-31 11:57:38 EST
Created attachment 2295 [details]
The two methods to add to JFace/Dialog
Comment 8 Nick Edgar CLA 2002-11-01 09:59:42 EST
In isContained(), rather than checking all children of the container, wouldn't 
it be more efficient to look up the parent chain of c for the container?
Comment 9 Nick Edgar CLA 2002-11-01 10:00:32 EST
Also, how does this affect the new project creation page (where Next is the 
default).
Comment 10 Andre Weinand CLA 2002-11-01 11:22:24 EST
Q1: sure, good suggestion!
Q2: yes, Prev and Next are not moved and stay together because initially the 'Finish' 
button is the default button and gets moved to the right (which is definitely better than 
having the cancel button there).

New code:
/*
 * @see Window.initializeBounds()
 */
protected void initializeBounds() {
	String platform= SWT.getPlatform();
	if ("carbon".equals(platform)) {	//$NON-NLS-1$
		// On Mac OS X the default button must be the right-most button
		Shell shell= getShell();
		if (shell != null) {
			Button defaultButton= shell.getDefaultButton();
			if (defaultButton != null && isContained(buttonBar, defaultButton))
				defaultButton.moveBelow(null);
		}
	}
	super.initializeBounds();
}

/**
 * Returns true if the given Control c is a direct or indirect child of
 * container.
 */
private boolean isContained(Control container, Control c) {
	Composite parent;
	while ((parent= c.getParent()) != null)
		if (parent == container)
			return true;
	return false;
}

Comment 11 Andre Weinand CLA 2002-11-01 11:28:50 EST
Please ignore above bogus code, real patch is coming....
Comment 12 Andre Weinand CLA 2002-11-01 11:37:46 EST
Created attachment 2299 [details]
Revised code
Comment 13 Nick Edgar CLA 2002-11-01 16:41:21 EST
Andre, why does this have to be done in initializeBounds?  Is it just because 
it's called after createContents in create?  I'm concerned because the spec for 
initializeBounds says that it can be reimplemented, without necessarily calling 
super.  In fact, our editors dialog does so (Window / Switch to Editor).
Perhaps it would be better to move the code to createButtonBar, however this 
says it can be overridden as well.  Several places do, although all call super.
Comment 14 Nick Edgar CLA 2002-11-01 17:03:49 EST
Tried it on Windows by uncommenting the platform check.
Doesn't seem to be working for:
- File / Save As... (Cancel is on right, but OK is default).
- New Project / New > Other (Cancel is on right, but Finish is the default when 
Next isn't)
- likewise for Import / Export

Released the change anyway (with the carbon check) since it's still an 
improvement.
Comment 15 Andre Weinand CLA 2002-11-01 20:39:15 EST
Yes, the code is in initializeBounds because it is called after create(). I tried all the other 
createXxx hooks, but they are more often reimplemented as initializeBounds.
A better solution would be a hook introduced in window and reimplemented in Dialog as 
final. However, that would be a breaking change.

The best solution would be to move this code to SWT because it must match the layout, 
L&F, button order of the native MessageBox and other dialogs. I don't think that JFace 
must handle that. Its more a custom widget like StyledText. For example on the Mac the 
icons are completely wrong because they are Windows icons.

On Mac OS X 'File / Save As... ' and 'New Project / New > Other' are both correct.
Import/Export is the only dialog that has Cancel on the right.

BTW: my latest patch implements your suggestion with getparent()! However, the code 
checked in is the old code.

Comment 16 Nick Edgar CLA 2002-11-01 23:17:21 EST
Sorry, I released the wrong patch.  I'll fix it up.

Veronika and McQ, do you have any thoughts on how to handle platform-specific 
differences in dialog look and feel at the SWT level?
Comment 17 Mike Wilson CLA 2002-11-04 09:56:47 EST
I suspect this is a case where platform L&F guidelines should not be applied. My 
reasoning goes like this...

First, I believe that, Eclipse should switch its dialogs to use the Mac model which is the 
more reasonable one. That is, the default button should be accept and it should be on 
the right. This allows the user to either hit return, or use position memory to get to the 
"make it so" button. Mac applications typically support Undo'ing operations that were 
invoked by dialogs, so it's fairly safe to do this.

The problem is that, in Eclipse, accepting a dialog can be a dangerous operation in that 
we often can not undo the operation easily (and so do not provide an Undo). Thus in 
Eclipse as of today, the default button ought to be cancel and it should be on the right, 
ensuring that the user has to consciously make a UI action if he *really* wants to make 
the positive choice.

Unfortunately, we are currently inconsistant: The default is typically accept, the rightmost 
button is typically cancel. This is the problem which should be fixed. I don't actually care 
whether the default button is accept or cancel, but in any case it should be on the right.

(Note: I haven't checked through all the dialogs, I'm thinking predominantly of Prev/Next/
Finish/Cancel in wizard pages)


Comment 18 Nick Edgar CLA 2002-11-04 12:54:22 EST
Fixed up the patch.

To address McQ's comments, I think that adopting the Mac convention on Windows 
and other platforms would be too great a departure from platform conventions.  
Almost every other app on Windows uses the order: OK, Cancel, Apply (with OK 
being the default).  Perhaps they are following the reading order convention
(default button is first one in top-down, left-to-right order), at least for 
Western languages.
Surprisingly, the Windows User Experience doesn't have anything to say on the 
matter of placement of the default button.  It seems to be more of a defacto 
standard.  However, I think that for the same reasons Mac users found it 
annoying to have the Windows convention for button order foisted on them, 
Windows users would find it annoying to have the Mac convention (even if we 
believe that it's a better order for motor memory).

I agree that we should not make it easy to do irreversable or destructive 
actions.  Here the WUE does say "Avoid making a command button the default 
button if its action is irreversible or destructive." (although they don't hold 
to that for Delete in Explorer).  However I think that makes sense regardless 
of where you place the default button.
We need to do a better job of undo for destructive actions like delete (the 
local history protects us somewhat, but it would be good to have recycle bin 
support too).
In other cases like creation wizards, it's not a big deal since it's easy to 
delete the new resource(s) after the fact.

Comment 19 Nick Edgar CLA 2002-11-04 12:59:13 EST
Andre was wondering if we can get the correct platform-specific icons to show 
in the dialog from SWT (e.g. Info / Warning / Error).
Comment 20 Veronika Irvine CLA 2002-11-04 13:55:08 EST
Enter this request as a separate DCR.  It probably is not available on all 
platforms.
Comment 21 Nick Edgar CLA 2002-11-04 16:51:08 EST
Filed bug 25703 for the icons.

 
Comment 22 Nick Edgar CLA 2002-11-12 01:49:49 EST
Closing.