Community
Participate
Working Groups
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.
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.
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.
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?
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".
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.
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; }
Created attachment 2295 [details] The two methods to add to JFace/Dialog
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?
Also, how does this affect the new project creation page (where Next is the default).
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; }
Please ignore above bogus code, real patch is coming....
Created attachment 2299 [details] Revised code
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.
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.
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.
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?
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)
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.
Andre was wondering if we can get the correct platform-specific icons to show in the dialog from SWT (e.g. Info / Warning / Error).
Enter this request as a separate DCR. It probably is not available on all platforms.
Filed bug 25703 for the icons.
Closing.