From c182fc33e409021950cdeba60bede1fe492a6348 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 7 Dec 2021 16:51:44 +0100 Subject: [PATCH 1/8] Make MockServices independent of JUnit API --- harness/nbjunit/src/org/netbeans/junit/MockServices.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/harness/nbjunit/src/org/netbeans/junit/MockServices.java b/harness/nbjunit/src/org/netbeans/junit/MockServices.java index c450ae552032..08f9cf053d92 100644 --- a/harness/nbjunit/src/org/netbeans/junit/MockServices.java +++ b/harness/nbjunit/src/org/netbeans/junit/MockServices.java @@ -37,8 +37,6 @@ import java.util.NoSuchElementException; import java.util.logging.Level; import java.util.logging.Logger; -import junit.framework.Assert; -import junit.framework.AssertionFailedError; /** * Lets you register mock implementations of global services. @@ -161,7 +159,10 @@ public ServiceClassLoader(Class[] services, ClassLoader l, boolean test) { for (Class c : services) { try { if (test) { - Assert.assertEquals(c, getParent().loadClass(c.getName())); + final Class real = getParent().loadClass(c.getName()); + if (!c.equals(real)) { + throw new AssertionError("Service " + c + " isn't " + real); + } } int mods = c.getModifiers(); if (!Modifier.isPublic(mods) || Modifier.isAbstract(mods)) { @@ -173,7 +174,7 @@ public ServiceClassLoader(Class[] services, ClassLoader l, boolean test) { } catch (NoSuchMethodException x) { throw (IllegalArgumentException) new IllegalArgumentException("Class " + c.getName() + " has no public no-arg constructor").initCause(x); } catch (Exception x) { - throw (AssertionFailedError) new AssertionFailedError(x.toString()).initCause(x); + throw new AssertionError(x.toString(), x); } } this.services = services; From 5eecb86464fcb3a0ef6124afe43c51bc1e22912f Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 7 Dec 2021 16:56:54 +0100 Subject: [PATCH 2/8] Splitting the API and implementation of HTML/Java UI module --- platform/api.htmlui/manifest.mf | 3 +- platform/api.htmlui/nbproject/project.xml | 29 +- .../org/netbeans/api/htmlui/HTMLDialog.java | 101 ++++--- .../org/netbeans/modules/htmlui/Buttons.java | 144 +++++++--- .../modules/htmlui/ContextAccessor.java | 56 ++++ .../modules/htmlui/HTMLDialogBase.java | 113 ++++++++ .../modules/htmlui/HTMLDialogImpl.java | 152 ---------- .../modules/htmlui/HTMLDialogProcessor.java | 92 ++++-- .../org/netbeans/modules/htmlui/HtmlPair.java | 74 +++++ .../org/netbeans/modules/htmlui/Pages.java | 46 +-- .../netbeans/spi/htmlui/HTMLViewerSpi.java | 272 ++++++++++++++++++ .../org/netbeans/modules/htmlui/ATech.java | 2 +- .../modules/htmlui/DialogOnSubmitTest.java | 71 +++++ .../modules/htmlui/MockHtmlViewer.java | 120 ++++++++ .../htmlui/OpenHTMLRegistrationTest.java | 2 +- platform/htmlui/build.xml | 5 + platform/htmlui/manifest.mf | 6 + platform/htmlui/nbproject/project.properties | 3 + platform/htmlui/nbproject/project.xml | 102 +++++++ .../modules/htmlui/impl/Bundle.properties | 5 + .../htmlui/impl/DefaultHtmlToolkit.java | 85 ++++++ .../modules/htmlui/impl}/HtmlComponent.java | 71 ++--- .../modules/htmlui/impl}/HtmlToolkit.java | 24 +- .../modules/htmlui/impl/SwingFXViewer.java | 223 ++++++++++++++ .../modules/htmlui/jfx/JavaFxHtmlToolkit.java | 18 +- .../modules/htmlui/jfx/NbBrowsers.java | 0 .../modules/htmlui/jfx/NbFxPanel.java | 0 .../netbeans/modules/htmlui/DialogsTest.java | 82 ++++-- .../netbeans/modules/htmlui/impl/ATech.java | 40 +++ .../modules/htmlui/impl}/ComponentsTest.java | 6 +- .../htmlui/impl}/EnsureJavaFXPresent.java | 8 +- .../htmlui/impl}/HtmlComponentTest.java | 31 +- .../modules/htmlui/impl}/NbResloc.java | 2 +- .../htmlui/impl}/ShowDialogFromEDTTest.java | 2 +- .../impl}/ShowDialogFromFXThreadTest.java | 2 +- .../netbeans/modules/htmlui/impl/empty.html | 31 ++ .../netbeans/modules/htmlui/impl/simple.html | 30 ++ 37 files changed, 1647 insertions(+), 406 deletions(-) create mode 100644 platform/api.htmlui/src/org/netbeans/modules/htmlui/ContextAccessor.java create mode 100644 platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogBase.java delete mode 100644 platform/api.htmlui/src/org/netbeans/modules/htmlui/HTMLDialogImpl.java create mode 100644 platform/api.htmlui/src/org/netbeans/modules/htmlui/HtmlPair.java create mode 100644 platform/api.htmlui/src/org/netbeans/spi/htmlui/HTMLViewerSpi.java create mode 100644 platform/api.htmlui/test/unit/src/org/netbeans/modules/htmlui/DialogOnSubmitTest.java create mode 100644 platform/api.htmlui/test/unit/src/org/netbeans/modules/htmlui/MockHtmlViewer.java create mode 100644 platform/htmlui/build.xml create mode 100644 platform/htmlui/manifest.mf create mode 100644 platform/htmlui/nbproject/project.properties create mode 100644 platform/htmlui/nbproject/project.xml create mode 100644 platform/htmlui/src/org/netbeans/modules/htmlui/impl/Bundle.properties create mode 100644 platform/htmlui/src/org/netbeans/modules/htmlui/impl/DefaultHtmlToolkit.java rename platform/{api.htmlui/src/org/netbeans/modules/htmlui => htmlui/src/org/netbeans/modules/htmlui/impl}/HtmlComponent.java (77%) rename platform/{api.htmlui/src/org/netbeans/modules/htmlui => htmlui/src/org/netbeans/modules/htmlui/impl}/HtmlToolkit.java (62%) create mode 100644 platform/htmlui/src/org/netbeans/modules/htmlui/impl/SwingFXViewer.java rename platform/{api.htmlui => htmlui}/src/org/netbeans/modules/htmlui/jfx/JavaFxHtmlToolkit.java (92%) rename platform/{api.htmlui => htmlui}/src/org/netbeans/modules/htmlui/jfx/NbBrowsers.java (100%) rename platform/{api.htmlui => htmlui}/src/org/netbeans/modules/htmlui/jfx/NbFxPanel.java (100%) rename platform/{api.htmlui => htmlui}/test/unit/src/org/netbeans/modules/htmlui/DialogsTest.java (78%) create mode 100644 platform/htmlui/test/unit/src/org/netbeans/modules/htmlui/impl/ATech.java rename platform/{api.htmlui/test/unit/src/org/netbeans/modules/htmlui => htmlui/test/unit/src/org/netbeans/modules/htmlui/impl}/ComponentsTest.java (93%) rename platform/{api.htmlui/test/unit/src/org/netbeans/modules/htmlui => htmlui/test/unit/src/org/netbeans/modules/htmlui/impl}/EnsureJavaFXPresent.java (90%) rename platform/{api.htmlui/test/unit/src/org/netbeans/modules/htmlui => htmlui/test/unit/src/org/netbeans/modules/htmlui/impl}/HtmlComponentTest.java (95%) rename platform/{api.htmlui/test/unit/src/org/netbeans/modules/htmlui => htmlui/test/unit/src/org/netbeans/modules/htmlui/impl}/NbResloc.java (96%) rename platform/{api.htmlui/test/unit/src/org/netbeans/modules/htmlui => htmlui/test/unit/src/org/netbeans/modules/htmlui/impl}/ShowDialogFromEDTTest.java (97%) rename platform/{api.htmlui/test/unit/src/org/netbeans/modules/htmlui => htmlui/test/unit/src/org/netbeans/modules/htmlui/impl}/ShowDialogFromFXThreadTest.java (98%) create mode 100644 platform/htmlui/test/unit/src/org/netbeans/modules/htmlui/impl/empty.html create mode 100644 platform/htmlui/test/unit/src/org/netbeans/modules/htmlui/impl/simple.html diff --git a/platform/api.htmlui/manifest.mf b/platform/api.htmlui/manifest.mf index 1efee18ceff7..6e5cfe9a5774 100644 --- a/platform/api.htmlui/manifest.mf +++ b/platform/api.htmlui/manifest.mf @@ -1,5 +1,4 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.htmlui OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/htmlui/Bundle.properties -OpenIDE-Module-Specification-Version: 1.22 - +OpenIDE-Module-Specification-Version: 1.23 diff --git a/platform/api.htmlui/nbproject/project.xml b/platform/api.htmlui/nbproject/project.xml index 276307bdc18d..97b476725509 100644 --- a/platform/api.htmlui/nbproject/project.xml +++ b/platform/api.htmlui/nbproject/project.xml @@ -37,12 +37,6 @@ - - net.java.html.boot.fx - - - - net.java.html.json @@ -57,14 +51,6 @@ org.netbeans.html.xhr4j - - org.netbeans.libs.javafx - - - - 2.4 - - org.netbeans.libs.asm @@ -94,7 +80,7 @@ - org.openide.util.ui + org.openide.util @@ -102,19 +88,19 @@ - org.openide.util + org.openide.util.lookup - 9.3 + 8.25 - org.openide.util.lookup + org.openide.util.ui - 8.25 + 9.3 @@ -142,10 +128,15 @@ org.netbeans.libs.testng + + org.netbeans.modules.nbjunit + + org.netbeans.api.htmlui + org.netbeans.spi.htmlui diff --git a/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java b/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java index ebc1fd1749ca..432ec670bfc0 100644 --- a/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java +++ b/platform/api.htmlui/src/org/netbeans/api/htmlui/HTMLDialog.java @@ -24,12 +24,15 @@ import java.lang.annotation.Target; import java.util.Locale; import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import net.java.html.json.Model; import net.java.html.json.Property; import org.netbeans.html.context.spi.Contexts.Id; -import org.netbeans.modules.htmlui.HTMLDialogImpl; +import org.netbeans.modules.htmlui.HTMLDialogBase; -/** Generates method that opens an HTML based modal dialog. Sample of a typical +/** Generates method that opens an HTML based modal dialog. Sample of a typical * usage follows. * HTML Page dialog.html *
@@ -60,9 +63,9 @@
 
     {@link Override @Override} public void actionPerformed({@link ActionEvent} e) {
         // shows dialog with a question, checkbox is checked by default
-        // {@link #className() Pages} is automatically generated class 
+        // {@link #className() Pages} is automatically generated class
         String ret = Pages.showHelloWorld(true);
-        
+
         System.out.println("User selected: " + ret);
     }
 }
@@ -71,13 +74,13 @@
  * The method is generated into Pages class in the same package
  * (unless one changes the name via {@link #className()}) and has the same name,
  * and parameters as the method annotated by this annotation. When the method
- * is invoked, it opens a dialog, loads an HTML page into it. When the page is 
+ * is invoked, it opens a dialog, loads an HTML page into it. When the page is
  * loaded, it calls back the method annotated by this annotation and passes it
- * its own arguments. The method is supposed to make the page live, preferrably 
- * by using {@link net.java.html.json.Model} generated class and calling 
+ * its own arguments. The method is supposed to make the page live, preferrably
+ * by using {@link net.java.html.json.Model} generated class and calling
  * applyBindings() on it.
  * 

- * The HTML page may contain hidden <button> elements. If it does so, + * The HTML page may contain hidden <button> elements. If it does so, * those buttons are copied to the dialog frame and displayed underneath the page. * Their enabled/disabled state reflects the state of the buttons in the page. * When one of the buttons is selected, the dialog closes and the generated @@ -88,7 +91,7 @@ * <button> elements, two buttons are added. One representing * the OK choice (with id="OK") and one representing * the cancel choice (with null id). Both buttons are always - * enabled. One can check the + * enabled. One can check the * return value from the dialog showing method * to be "OK" to know whether the * user approved the dialog. @@ -102,17 +105,17 @@ * Will be resolved by the annotation processor and converted into * nbresloc protocol - as such the HTML page can be L10Ned * later by adding classical L10N suffixes. E.g. index_cs.html - * will take preceedence over index.html if the user is + * will take preceedence over index.html if the user is * running in Czech {@link Locale}. - * + * * @return relative path the HTML page */ String url(); - + /** Name of the file to generate the method that opens the dialog * into. Class of such name will be generated into the same - * package. - * + * package. + * * @return name of class to generate */ String className() default "Pages"; @@ -120,30 +123,47 @@ /** Selects some of provided technologies. The HTML/Java API @ version 1.1 * supports {@link Id technology ids}. One can specify the preferred ones * to use in this NetBeans component by using this attribute. - * + * * @return list of preferred technology ids * @since 1.3 */ String[] techIds() default {}; - - /** Rather than using this class directly, consider - * {@link HTMLDialog}. The {@link HTMLDialog} annotation + + /** + * + * @since 1.23 + */ + @FunctionalInterface + public interface OnSubmit { + /** Callback when a button is pressed. + * + * @param button the ID of the pressed button or {@code null} on cancel + * @return {@code true} to close the dialog, {@code false} to ignore + * the button press and leave the dialog open + * @since 1.23 + */ + boolean onSubmit(String button); + } + + /** Rather than using this class directly, consider + * {@link HTMLDialog}. The {@link HTMLDialog} annotation * generates boilderplate code for you * and can do some compile times checks helping you to warnings * as soon as possible. */ public static final class Builder { - private final HTMLDialogImpl impl; - + private final String url; + private List techIds = new ArrayList<>(); + private Runnable onPageLoad; + private Builder(String u) { - impl = new HTMLDialogImpl(); - impl.setUrl(u); + this.url = u; } /** Starts creation of a new HTML dialog. The page * can contain hidden buttons as described at * {@link HTMLDialog}. - * + * * @param url URL (usually using nbresloc protocol) * of the page to display in the dialog. * @return instance of the builder @@ -151,51 +171,64 @@ private Builder(String u) { public static Builder newDialog(String url) { return new Builder(url); } - + /** Registers a runnable to be executed when the page * becomes ready. - * + * * @param run runnable to run * @return this builder */ public Builder loadFinished(Runnable run) { - impl.setOnPageLoad(run); + this.onPageLoad = run; return this; } - + /** Requests some of provided technologies. The HTML/Java API @ version 1.1 * supports {@link Id technology ids}. One can specify the preferred ones * to use in this NetBeans component by using calling this method. - * + * * @param ids list of preferred technology ids to add to the builder * @return instance of the builder * @since 1.3 */ public Builder addTechIds(String... ids) { - impl.addTechIds(ids); + techIds.addAll(Arrays.asList(ids)); return this; } - /** Displays the dialog. This method blocks waiting for the - * dialog to be shown and closed by the user. - * + /** Displays the dialog and waits. This method blocks waiting for the + * dialog to be shown and closed by the user. + * * @return 'id' of a selected button element or null * if the dialog was closed without selecting a button */ public String showAndWait() { + HTMLDialogBase impl = HTMLDialogBase.create(url, onPageLoad, null, techIds.toArray(new String[0]), null); return impl.showAndWait(); } - + + /** Displays the dialog and returns immediately. + * + * @param s callback to call when a button is clicked and dialog + * is about to be closed + * @since 1.23 + */ + public void show(OnSubmit s) { + HTMLDialogBase impl = HTMLDialogBase.create(url, onPageLoad, s, techIds.toArray(new String[0]), null); + impl.show(s); + } + /** Obtains the component from the builder. The parameter * can either be {@link javafx.embed.swing.JFXPanel}.class or * {@link javafx.scene.web.WebView}.class. After calling this * method the builder becomes useless. - * + * * @param requested component type * @param type either {@link javafx.embed.swing.JFXPanel} or {@link javafx.scene.web.WebView} class * @return instance of the requested component */ public C component(Class type) { + HTMLDialogBase impl = HTMLDialogBase.create(url, onPageLoad, null, techIds.toArray(new String[0]), type); return impl.component(type); } } diff --git a/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java b/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java index 21c86bb8233a..50a7408ba2c4 100644 --- a/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java +++ b/platform/api.htmlui/src/org/netbeans/modules/htmlui/Buttons.java @@ -18,21 +18,41 @@ */ package org.netbeans.modules.htmlui; -import java.awt.EventQueue; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import javax.swing.JButton; +import java.util.Objects; import net.java.html.js.JavaScriptBody; +import org.netbeans.api.htmlui.HTMLDialog; +import org.netbeans.spi.htmlui.HTMLViewerSpi; import org.openide.util.NbBundle; /** * * @author Jaroslav Tulach */ -final class Buttons { - private final List arr = new ArrayList<>(); - - @JavaScriptBody(args = {}, javacall = true, body = +class Buttons { + private static final String PREFIX = "dialog-buttons-"; + + private final HTMLDialog.OnSubmit onSubmit; + private final HTMLViewerSpi viewer; + private final View view; + + private final List