Bug 552909 - Builder API for MessageDialog
Summary: Builder API for MessageDialog
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.14   Edit
Hardware: PC All
: P3 normal (vote)
Target Milestone: 4.21 M3   Edit
Assignee: Marcus Höpfner CLA
QA Contact:
URL:
Whiteboard:
Keywords: noteworthy
Depends on:
Blocks: 574014
  Show dependency tree
 
Reported: 2019-11-11 10:13 EST by Lars Vogel CLA
Modified: 2021-08-19 01:38 EDT (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lars Vogel CLA 2019-11-11 10:13:07 EST
MessageDialog.open could IMHO benefit from a fluent API, like the one we created for SWT.

This API should allow to:

set the icon (optional)
set the title
set the message
set the buttons text
Comment 1 Lars Vogel CLA 2019-11-11 10:14:05 EST
Marcus, something for you as our new master of fluent API?
Comment 2 Marcus Höpfner CLA 2019-11-12 04:53:47 EST
(In reply to Lars Vogel from comment #1)
> Marcus, something for you as our new master of fluent API?

Maybe...
But I'm currently busy with other things.
Hope I can manage to look into it within the next weeks.
Comment 3 Marcus Höpfner CLA 2019-12-23 03:00:43 EST
While I started to work on a fix I recognized that there are a lot of static methods in MessageDialog to create dialogs of any kind.

So my question is, does it really add value if we add yet another possibility to create MessageDialogs?

W.r.t.to clean code it is worth to do it since the mentioned methods have a lot of parameters (four or more) and have int parameters e.g. for the message kind. A fluent api would bring benefits here.
But on the other hand it may confuse implementors to have another method?!

To make it more clear: I'm thinking for something like this:

MessageDialog.information().title("Do you really want another method?").message("Click ok if you want to have yet another method for MessageDialogs.").open(theShell);

WDYT?
Comment 4 Alexander Fedorov CLA 2019-12-23 03:05:37 EST
(In reply to Marcus Höpfner from comment #3)
> While I started to work on a fix I recognized that there are a lot of static
> methods in MessageDialog to create dialogs of any kind.
> 
> So my question is, does it really add value if we add yet another
> possibility to create MessageDialogs?
> 
> WDYT?

+1 for adding another type for MessageDialog fluent API, like "MessageDialogs"
Comment 5 Lars Vogel CLA 2019-12-23 03:59:07 EST
The static methods do not allow to specify the text of the buttons and are therefore useless for real usage. Also we want dialogs without icons, the usage of the help icon for question dialogs is wrong according to Microsoft UX guidelines.
Comment 6 Marcus Höpfner CLA 2019-12-23 04:02:15 EST
ok, thanks for clarification. So I continue.
Comment 7 Marcus Höpfner CLA 2019-12-23 04:04:46 EST
(In reply to Marcus Höpfner from comment #3)

> MessageDialog.information().title("Do you really want another
> method?").message("Click ok if you want to have yet another method for
> MessageDialogs.").open(theShell);

I'm currently facing problems in testing this.
I thought I call the above code in a unit test, do the assertions for the created controls (buttons, title, description) and close the dialog.
Any idea how I can do this? How can I recognize that the dialog has opened? I tried a ShellListener on the original shell but this was not called.
Comment 8 Paul Pazderski CLA 2019-12-23 04:42:16 EST
(In reply to Marcus Höpfner from comment #7)
> I'm currently facing problems in testing this.
> I thought I call the above code in a unit test, do the assertions for the
> created controls (buttons, title, description) and close the dialog.
> Any idea how I can do this? How can I recognize that the dialog has opened?
> I tried a ShellListener on the original shell but this was not called.

Indeed not an easy task. Will be even more difficult since the open method kind of block the main thread.

The best I came up spontaneous is the following snippet. It will open a message dialog and check if the dialog is actual opened.
-------------------------
	public void testMessageDialog() {
		Display display = Display.getDefault();
		Shell shell = new Shell(display);
		AtomicBoolean found = new AtomicBoolean(false);
		String title = "Title";
		display.asyncExec(() -> {
			for (Shell s : display.getShells()) {
				if (title.equals(s.getText())) {
					found.set(true);
				}
			}
			display.dispose();
		});
		MessageDialog.open(MessageDialog.CONFIRM, shell, title, "Message", 0);

		if (!display.isDisposed()) {
			display.readAndDispatch();
		}
		assertTrue(found.get());
	}
-------------------------
Comment 9 Eclipse Genie CLA 2019-12-26 05:43:11 EST
New Gerrit change created: https://git.eclipse.org/r/155044
Comment 10 Marcus Höpfner CLA 2020-01-17 04:02:23 EST
Regarding Lars' comment in the Gerrit commit to have a simpler builder api in order to have the possibility to just open a dialog maybe even without an image...

For this, the API of MessageDialog must also be changed. It has a bunch static methods, two huge constructors with many parameters.
Adding new API methods to satisfy the new requirements would make it worth.
I have the impression that the static methods have been introduced to overcome the constructors and to have an easier API. Now, as it is not sufficient anymore we add a factory or a builder (how ever you call it) on top of that in a separate type.
For me, this somehow feels wrong. It will result in a mixture of patterns and there is no clean API anymore. In some cases the static methods are ok, in others the Builder/Factory is needed.

My proposal is to start from scratch with a new MessageDialog with the same capabilities as the old one but with one constructor, just setter methods and an open methods. No overloaded static methods or huge constructors.
Then, as an easier to consume API have a builder/factory in a separate type to have an easier API.

But adding another public methods to MessageDialog to satisfy the Builder requirements feels wrong and makes MessageDialog worse IMHO.

WDYT?
Comment 11 Lars Vogel CLA 2020-01-17 04:45:52 EST
(In reply to Marcus Höpfner from comment #10)
> Regarding Lars' comment in the Gerrit commit to have a simpler builder api
> in order to have the possibility to just open a dialog maybe even without an
> image...
> 
> For this, the API of MessageDialog must also be changed. It has a bunch
> static methods, two huge constructors with many parameters.
> Adding new API methods to satisfy the new requirements would make it worth.
> I have the impression that the static methods have been introduced to
> overcome the constructors and to have an easier API. Now, as it is not
> sufficient anymore we add a factory or a builder (how ever you call it) on
> top of that in a separate type.
> For me, this somehow feels wrong. It will result in a mixture of patterns
> and there is no clean API anymore. In some cases the static methods are ok,
> in others the Builder/Factory is needed.
> 
> My proposal is to start from scratch with a new MessageDialog with the same
> capabilities as the old one but with one constructor, just setter methods
> and an open methods. No overloaded static methods or huge constructors.
> Then, as an easier to consume API have a builder/factory in a separate type
> to have an easier API.
> 
> But adding another public methods to MessageDialog to satisfy the Builder
> requirements feels wrong and makes MessageDialog worse IMHO.
> 
> WDYT?

+1
Comment 12 Eclipse Genie CLA 2020-01-20 03:10:51 EST
New Gerrit change created: https://git.eclipse.org/r/156156
Comment 13 Marcus Höpfner CLA 2020-01-30 08:45:03 EST
I started to change the https://git.eclipse.org/r/#/c/156156/ locally and to incorporate the feedback.

If I remove all the constants for the kind which determine the button texts and the image, what is left then?

Just a plain message dialog with a title, message, buttons and icon. But nothing is predefined, it is completely free-style. And I guess will be used like free-style, so in every UI the dialog may look different. Imagine an error dialog with error image and button "OK". Another one with error image and buttons "OK", "Cancel" (which is obviously wrong).

I would like to clarify how many guidance do we want to provide and how many free-style?
Comment 14 Alexander Fedorov CLA 2020-01-30 09:00:22 EST
(In reply to Marcus Höpfner from comment #13)
> 
> If I remove all the constants for the kind which determine the button texts
> and the image, what is left then?
> 

Several simple final dialog classes that encapsulates this information. 
Something is wrong with idea to expose internals (text, image).
What is the case when we need these kind constants?
Comment 15 Marcus Höpfner CLA 2020-01-31 03:24:28 EST
(In reply to Alexander Fedorov from comment #14)
> (In reply to Marcus Höpfner from comment #13)
> > 
> > If I remove all the constants for the kind which determine the button texts
> > and the image, what is left then?
> > 
> 
> Several simple final dialog classes that encapsulates this information. 

> Something is wrong with idea to expose internals (text, image).
What is meant by expose? Where do we expose it? It should be just setters to set these information.

> What is the case when we need these kind constants?
E.g. if you want to create an error dialog with an error image and a button "Ok".
Or a question dialog with a question mark icon and "Yes" and "No" buttons.
Comment 16 Alexander Fedorov CLA 2020-01-31 03:34:52 EST
(In reply to Marcus Höpfner from comment #15)
> (In reply to Alexander Fedorov from comment #14)
> > (In reply to Marcus Höpfner from comment #13)
> > > 
> > > If I remove all the constants for the kind which determine the button texts
> > > and the image, what is left then?
> > > 
> > 
> > Several simple final dialog classes that encapsulates this information. 
> 
> > Something is wrong with idea to expose internals (text, image).
> What is meant by expose? Where do we expose it? It should be just setters to
> set these information.

If we are talking about good OOP - getters/setters are evil, because they degrades the idea of object to a "struct of data, that everyone can change from everywhere.

> 
> > What is the case when we need these kind constants?
> E.g. if you want to create an error dialog with an error image and a button
> "Ok".

I would expect several constructors with good defaults
'new ErrorDialog(title, message)`
'new ErrorDialog(title, message, buttonLabel)'

> Or a question dialog with a question mark icon and "Yes" and "No" buttons.
'new QuestionDialog(title, question)`
'new QuestionDialog(title, question, <other arguments to configure buttons>`

If the continue our design with respect to OOP we can come up with some additional object to configure each button:

public final class Choice {
   private final String label;
   private final String tooltip;
   private final SomethingFunctional action;
}
Comment 17 Lars Vogel CLA 2020-06-02 05:21:39 EDT
Marcus and I had a short email conversation.

I think this new API should:

- Introduce a new dialog
- Allow to create a dialog without icons
- Allow to create error / question / etc dialogs via a build method for examle type(SWT.Error)
- The usage / adaption of this API should be handled via a new bug
Comment 18 Marcus Höpfner CLA 2020-06-04 09:12:24 EDT
I have uploaded a new patch set in https://git.eclipse.org/r/c/156156/.
Kindly let me know if this is the direction we wanna go.

Open issues:
- should the dialog be final?
- should it still support SWT.SHEET?
- in the builder SWT.ERROR is used but there is nor SWT.INFO neither SWT.WARNING
Comment 19 Eclipse Genie CLA 2020-10-19 10:21:21 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/170943
Comment 20 Alexander Kurtakov CLA 2021-01-07 03:07:53 EST
Mass move 4.19 M1 bugs to M3
Comment 21 Alexander Kurtakov CLA 2021-02-15 04:41:59 EST
Too late for 4.19. Remove target milestone. Please set one when you start working on it.
Comment 23 Lars Vogel CLA 2021-06-17 06:08:17 EDT
Thanks, Marcus for this contribution. Could you add this new API to the N&N?
Comment 24 Eclipse Genie CLA 2021-06-17 06:23:52 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/182104
Comment 26 Andrey Loskutov CLA 2021-06-18 04:08:08 EDT
(In reply to Eclipse Genie from comment #22)
> Gerrit change
> https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/170943 was merged
> to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/
> ?id=4ccc686b15a8190380e29cb62ef16307e9295c52

This introduces compilation error in the IDE.

Javadoc: The method of(Object[]) is undefined for the type List	PlainMessageDialog.java	/org.eclipse.jface/src/org/eclipse/jface/dialogs	line 137	Java Problem
Comment 27 Eclipse Genie CLA 2021-06-18 05:49:52 EDT
New Gerrit change created: https://git.eclipse.org/r/c/www.eclipse.org/eclipse/news/+/182163
Comment 28 Lars Vogel CLA 2021-06-18 06:05:46 EDT
(In reply to Andrey Loskutov from comment #26)
> This introduces compilation error in the IDE.
> 
> Javadoc: The method of(Object[]) is undefined for the type List
> PlainMessageDialog.java	/org.eclipse.jface/src/org/eclipse/jface/dialogs
> line 137	Java Problem

Marcus, can you have a look?
Comment 29 Eclipse Genie CLA 2021-06-18 08:16:42 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/182174
Comment 30 Marcus Höpfner CLA 2021-06-18 08:19:19 EDT
(In reply to Lars Vogel from comment #28)
> (In reply to Andrey Loskutov from comment #26)
> > This introduces compilation error in the IDE.
> > 
> > Javadoc: The method of(Object[]) is undefined for the type List
> > PlainMessageDialog.java	/org.eclipse.jface/src/org/eclipse/jface/dialogs
> > line 137	Java Problem
> 
> Marcus, can you have a look?

Ok, I fixed it in a new commit. Pls. review and merge.

I find it somehow bad that I did not get a build error for my first commit.
Isn't that something Jenkins should find and prevent the merge?
Comment 32 Lars Vogel CLA 2021-06-18 09:12:44 EDT
Thanks Marcus for fixing and Andrey for finding. Marcus, I think we could change the project settings to error for Javadoc errors, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=570430
Comment 34 Andrey Loskutov CLA 2021-08-12 08:11:41 EDT
Windows tests are failing, see 
https://download.eclipse.org/eclipse/downloads/drops4/I20210811-1800/testresults/html/org.eclipse.jface.tests_ep421I-unit-win32-java11_win32.win32.x86_64_11.html

createsDialogWithButtons	Failure	expected:<[No]> but was:<[Yes]>

org.junit.ComparisonFailure: expected:<[No]> but was:<[Yes]>
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
at org.eclipse.jface.tests.dialogs.PlainMessageDialogTest.createsDialogWithButtons(PlainMessageDialogTest.java:63)

createsDialogWithDefaultButton	Failure	expected:<[Cancel]> but was:<[No]>

org.junit.ComparisonFailure: expected:<[Cancel]> but was:<[No]>
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
at org.eclipse.jface.tests.dialogs.PlainMessageDialogTest.createsDialogWithDefaultButton(PlainMessageDialogTest.java:79)
Comment 35 Andrey Loskutov CLA 2021-08-16 03:44:40 EDT
(In reply to Andrey Loskutov from comment #34)
> Windows tests are failing

@Marcus, Lars: please investigate & provide fixes.
Comment 36 Lars Vogel CLA 2021-08-16 08:56:54 EDT
(In reply to Andrey Loskutov from comment #35)
> (In reply to Andrey Loskutov from comment #34)
> > Windows tests are failing
> 
> @Marcus, Lars: please investigate & provide fixes.

I try to look at that tomorrow morning.
Comment 37 Eclipse Genie CLA 2021-08-17 04:34:10 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/184117
Comment 39 Kalyan Prasad Tatavarthi CLA 2021-08-19 01:37:09 EDT
Verified that the tests pass in the windows build https://download.eclipse.org/eclipse/downloads/drops4/I20210818-0600/testResults.php
Comment 40 Kalyan Prasad Tatavarthi CLA 2021-08-19 01:38:39 EDT
(In reply to Andrey Loskutov from comment #34)
> Windows tests are failing, see 
> https://download.eclipse.org/eclipse/downloads/drops4/I20210811-1800/
> testresults/html/org.eclipse.jface.tests_ep421I-unit-win32-java11_win32.
> win32.x86_64_11.html
> 
> createsDialogWithButtons	Failure	expected:<[No]> but was:<[Yes]>
> 
> org.junit.ComparisonFailure: expected:<[No]> but was:<[Yes]>
> at org.junit.Assert.assertEquals(Assert.java:117)
> at org.junit.Assert.assertEquals(Assert.java:146)
> at
> org.eclipse.jface.tests.dialogs.PlainMessageDialogTest.
> createsDialogWithButtons(PlainMessageDialogTest.java:63)
> 
> createsDialogWithDefaultButton	Failure	expected:<[Cancel]> but was:<[No]>
> 
> org.junit.ComparisonFailure: expected:<[Cancel]> but was:<[No]>
> at org.junit.Assert.assertEquals(Assert.java:117)
> at org.junit.Assert.assertEquals(Assert.java:146)
> at
> org.eclipse.jface.tests.dialogs.PlainMessageDialogTest.
> createsDialogWithDefaultButton(PlainMessageDialogTest.java:79)

The tests pass in https://download.eclipse.org/eclipse/downloads/drops4/I20210818-0600/testresults/html/org.eclipse.jface.tests_ep421I-unit-win32-java11_win32.win32.x86_64_11.html