View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * SteelBlue: DCI User Interfaces
5    * http://tidalwave.it/projects/steelblue
6    *
7    * Copyright (C) 2015 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8    *
9    * *************************************************************************************************************************************************************
10   *
11   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17   * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
18   *
19   * *************************************************************************************************************************************************************
20   *
21   * git clone https://bitbucket.org/tidalwave/steelblue-src
22   * git clone https://github.com/tidalwave-it/steelblue-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.ui.javafx;
27  
28  import jakarta.annotation.Nonnull;
29  import java.util.Collection;
30  import java.util.Optional;
31  import java.util.function.Function;
32  import java.nio.file.Path;
33  import javafx.beans.property.BooleanProperty;
34  import javafx.beans.property.DoubleProperty;
35  import javafx.beans.property.IntegerProperty;
36  import javafx.beans.property.LongProperty;
37  import javafx.beans.property.Property;
38  import javafx.scene.Node;
39  import javafx.scene.control.ButtonBase;
40  import javafx.scene.control.ComboBox;
41  import javafx.scene.control.ListView;
42  import javafx.scene.control.MenuItem;
43  import javafx.scene.control.TableView;
44  import javafx.scene.control.TextField;
45  import javafx.scene.control.ToggleButton;
46  import javafx.scene.control.TreeTableView;
47  import javafx.scene.control.TreeView;
48  import javafx.scene.layout.GridPane;
49  import javafx.scene.layout.Pane;
50  import it.tidalwave.ui.core.BoundProperty;
51  import it.tidalwave.ui.core.UserNotification;
52  import it.tidalwave.ui.core.UserNotificationWithFeedback;
53  import it.tidalwave.ui.core.role.PresentationModel;
54  import it.tidalwave.ui.core.role.UserAction;
55  import it.tidalwave.ui.core.role.Visibility;
56  import it.tidalwave.ui.javafx.role.CustomGraphicProvider;
57  
58  /***************************************************************************************************************************************************************
59   *
60   * @author  Fabrizio Giudici
61   *
62   **************************************************************************************************************************************************************/
63  public interface JavaFXBinder
64    {
65      /***********************************************************************************************************************************************************
66       * Binds a button to a {@link UserAction}. The following roles o the action are used:
67       * <ul>
68       * <li>Displayable: to set the label of the button</li>
69       * </ul>
70       * The action is used as a callback when the button is pressed; invoked in a thread provided by the binder executor. The {@code enabled} property of the
71       * {@code UserAction} is bound, negated, to the {@code disabled} property of the button.
72       * @param   button      the button
73       * @param   action      the action
74       **********************************************************************************************************************************************************/
75      public void bind (@Nonnull ButtonBase button, @Nonnull UserAction action);
76  
77      /***********************************************************************************************************************************************************
78       * Binds a menu item to a {@link UserAction}. The following roles o the action are used:
79       * <ul>
80       * <li>Displayable: to set the label of the menu item</li>
81       * </ul>
82       * The action is used as a callback when the button is pressed; invoked in a thread provided by the binder executor. The {@code enabled} property of the
83       * {@code UserAction} is bound, negated, to the {@code disabled} property of the menu item.
84       * @param   menuItem    the menu item
85       * @param   action      the action
86       **********************************************************************************************************************************************************/
87      public void bind (@Nonnull MenuItem menuItem, @Nonnull UserAction action);
88  
89      /***********************************************************************************************************************************************************
90       * Binds a {@link TableView} to a {@link PresentationModel} and an optional callback. The {@code PresentationModel} is used to populate the table. The
91       * following roles are used:
92       * <ul>
93       * <li>A {@link it.tidalwave.role.SimpleComposite} provides children {@code PresentationModel}s for each row.</li>
94       * <li>In each row, an {@link it.tidalwave.role.Aggregate<PresentationModel>} is used to provide the {@code PresentationModel}s for
95       *     each column.</li>
96       * <li>A {@link it.tidalwave.ui.core.role.Displayable} (optional) is used to provide the text to render for each item.</li>
97       * <li>A {@link CustomGraphicProvider} (optional) is used to provide the graphics to render for each item.</li>
98       * <li>A {@link it.tidalwave.ui.core.role.Styleable} (optional) is used to provide the rendering style for each item.</li>
99       * <li>A {@link it.tidalwave.ui.core.role.UserActionProvider} (optional) is used to provide the actions for creating a context menu;
100      *     the default action is also bound to the double click or SPACE gesture.</li>
101      * </ul>
102      * The process of populating data is performed in background threads, so this method quickly returns also in case of large amount of data. The
103      * initialization callback is called in the JavaFX thread when data population has been completed.
104      * @param   tableView       the {@code TablewView}
105      * @param   pm              the {@code PresentationModel}
106      * @param   initCallback    the callback
107      * @since   1.0-ALPHA-13
108      **********************************************************************************************************************************************************/
109     public void bind (@Nonnull TableView<PresentationModel> tableView, @Nonnull PresentationModel pm, @Nonnull Optional<Runnable> initCallback);
110 
111     /***********************************************************************************************************************************************************
112      * Binds a {@link TableView} to a {@link PresentationModel} and a callback. See {@link #bind(javafx.scene.control.TableView,
113      * it.tidalwave.ui.core.role.PresentationModel, java.util.Optional)}. The process of populating data is performed in background threads, so this method
114      * quickly returns also in case of large amount of data. The initialization callback is called in the JavaFX thread when data population has been completed.
115      * @param   tableView       the {@code TablewView}
116      * @param   pm              the {@code PresentationModel}
117      * @param   initCallback    the callback
118      **********************************************************************************************************************************************************/
119     public default void bind (@Nonnull final TableView<PresentationModel> tableView, @Nonnull final PresentationModel pm, @Nonnull final Runnable initCallback)
120       {
121         bind(tableView, pm, Optional.of(initCallback));
122       }
123 
124     /***********************************************************************************************************************************************************
125      * Binds a {@link TableView} to a {@link PresentationModel}. See {@link #bind(javafx.scene.control.TableView, it.tidalwave.ui.core.role.PresentationModel,
126      * java.util.Optional)}.
127      * @param   tableView       the {@code TablewView}
128      * @param   pm              the {@code PresentationModel}
129      * @since   1.0-ALPHA-13
130      **********************************************************************************************************************************************************/
131     public default void bind (@Nonnull final TableView<PresentationModel> tableView, @Nonnull final PresentationModel pm)
132       {
133         bind(tableView, pm, Optional.empty());
134       }
135 
136     /***********************************************************************************************************************************************************
137      * Binds a {@link TreeView} to a {@link PresentationModel} and a callback. The {@code PresentationModel} is used to populate the table. The following roles
138      * are used:
139      * <ul>
140      * <li>A {@link it.tidalwave.role.SimpleComposite} provides children {@code PresentationModel}s for each row.</li>
141      * <li>In each row, an {@link it.tidalwave.role.Aggregate<PresentationModel>} is used to provide the {@code PresentationModel}s for
142      *     each column.</li>
143      * <li>A {@link it.tidalwave.ui.core.role.Displayable} (optional) is used to provide the text to render for each item.</li>
144      * <li>A {@link CustomGraphicProvider} (optional) is used to provide the graphics to render for each item.</li>
145      * <li>A {@link it.tidalwave.ui.core.role.Styleable} (optional) is used to provide the rendering style for each item.</li>
146      * <li>A {@link it.tidalwave.ui.core.role.UserActionProvider} (optional) is used to provide the actions for creating a context menu;
147      *     the default action is also bound to the double click or SPACE gesture.</li>
148      * <li>A {@link Visibility} (optional) is used to decide whether the root node should be visible or not.</li>
149      * </ul>
150      * The process of populating data is performed in background threads, so this method quickly returns also in case  of large amount of data. The
151      * initialization callback is called in the JavaFX thread when data population has been completed.
152      * @param   treeView        the {@code TreeView}
153      * @param   pm              the {@code PresentationModel}
154      * @param   initCallback    the callback
155      **********************************************************************************************************************************************************/
156     public void bind (@Nonnull TreeView<PresentationModel> treeView, @Nonnull PresentationModel pm, @Nonnull Optional<Runnable> initCallback);
157 
158     /***********************************************************************************************************************************************************
159      * Binds a {@link TableView} to a {@link PresentationModel} and a callback. See {@link #bind(javafx.scene.control.TreeView,
160      * it.tidalwave.ui.core.role.PresentationModel, java.util.Optional)}.
161      * @param   treeView        the {@code TreeView}
162      * @param   pm              the {@code PresentationModel}
163      * @param   initCallback    the callback
164      * @since   1.0-ALPHA-13
165      **********************************************************************************************************************************************************/
166     public default void bind (@Nonnull final TreeView<PresentationModel> treeView, @Nonnull final PresentationModel pm, @Nonnull final Runnable initCallback)
167       {
168         bind(treeView, pm, Optional.of(initCallback));
169       }
170 
171     /***********************************************************************************************************************************************************
172      * Binds a {@link TableView} to a {@link PresentationModel}. See {@link #bind(javafx.scene.control.TableView, it.tidalwave.ui.core.role.PresentationModel,
173      * java.util.Optional)}
174      * @param   treeView        the {@code TreeView}
175      * @param   pm              the {@code PresentationModel}
176      * @since   1.0-ALPHA-13
177      **********************************************************************************************************************************************************/
178     public default void bind (@Nonnull final TreeView<PresentationModel> treeView, @Nonnull final PresentationModel pm)
179       {
180         bind(treeView, pm, Optional.empty());
181       }
182 
183     /***********************************************************************************************************************************************************
184      * Binds a {@link TreeTableView} to a {@link PresentationModel} and a callback. The {@code PresentationModel} is used to populate the table. The following
185      * roles are used:
186      * <ul>
187      * <li>A {@link it.tidalwave.role.SimpleComposite} provides children {@code PresentationModel}s for each row.</li>
188      * <li>In each row, an {@link it.tidalwave.role.Aggregate<PresentationModel>} is used to provide the {@code PresentationModel}s for
189      *     each column.</li>
190      * <li>A {@link it.tidalwave.ui.core.role.Displayable} (optional) is used to provide the text to render for each item.</li>
191      * <li>A {@link CustomGraphicProvider} (optional) is used to provide the graphics to render for each item.</li>
192      * <li>A {@link it.tidalwave.ui.core.role.Styleable} (optional) is used to provide the rendering style for each item.</li>
193      * <li>A {@link it.tidalwave.ui.core.role.UserActionProvider} (optional) is used to provide the actions for creating a context menu;
194      *     the default action is also bound to the double click or SPACE gesture.</li>
195      * <li>A {@link Visibility} (optional) is used to decide whether the root node should be visible or not.</li>
196      * </ul>
197      * The process of populating data is performed in background threads, so this method quickly returns also in case of large amount of data. The
198      * initialization callback is called in the JavaFX thread when data population has been completed.
199      * @param   treeTableView   the {@code TreeTableView}
200      * @param   pm              the {@code PresentationModel}
201      * @param   initCallback    the callback
202      **********************************************************************************************************************************************************/
203     public void bind (@Nonnull TreeTableView<PresentationModel> treeTableView, @Nonnull PresentationModel pm, @Nonnull Optional<Runnable> initCallback);
204 
205     /***********************************************************************************************************************************************************
206      * Binds a {@link TreeTableView} to a {@link PresentationModel} and a callback. See {@link #bind(javafx.scene.control.TreeTableView,
207      * it.tidalwave.ui.core.role.PresentationModel, java.util.Optional)}.
208      * @param   treeTableView   the {@code TreeTableView}
209      * @param   pm              the {@code PresentationModel}
210      * @param   initCallback    the callback
211      * @since   1.0-ALPHA-13
212      **********************************************************************************************************************************************************/
213     public default void bind (@Nonnull final TreeTableView<PresentationModel> treeTableView,
214                               @Nonnull final PresentationModel pm,
215                               @Nonnull final Runnable initCallback)
216       {
217         bind(treeTableView, pm, Optional.of(initCallback));
218       }
219 
220     /***********************************************************************************************************************************************************
221      * Binds a {@link TreeTableView} to a {@link PresentationModel}. See {@link #bind(javafx.scene.control.TreeTableView,
222      * it.tidalwave.ui.core.role.PresentationModel, java.util.Optional)}.
223      * @param   treeTableView   the {@code TreeTableView}
224      * @param   pm              the {@code PresentationModel}
225      * @since   1.0-ALPHA-13
226      **********************************************************************************************************************************************************/
227     public default void bind (@Nonnull final TreeTableView<PresentationModel> treeTableView, @Nonnull final PresentationModel pm)
228       {
229         bind(treeTableView, pm, Optional.empty());
230       }
231 
232     /***********************************************************************************************************************************************************
233      * Binds a {@link ListView} to a {@link PresentationModel} and an optional callback. The {@code PresentationModel} is used to populate the table. The
234      * following roles are used:
235      * <ul>
236      * <li>A {@link it.tidalwave.role.SimpleComposite} provides children {@code PresentationModel}s for each row.</li>
237      * <li>In each row, an {@link it.tidalwave.role.Aggregate<PresentationModel>} is used to provide the {@code PresentationModel}s for
238      *     each column.</li>
239      * <li>A {@link it.tidalwave.ui.core.role.Displayable} (optional) is used to provide the text to render for each item.</li>
240      * <li>A {@link CustomGraphicProvider} (optional) is used to provide the graphics to render for each item.</li>
241      * <li>A {@link it.tidalwave.ui.core.role.Styleable} (optional) is used to provide the rendering style for each item.</li>
242      * <li>A {@link it.tidalwave.ui.core.role.UserActionProvider} (optional) is used to provide the actions for creating a context menu;
243      *     the default action is also bound to the double click or SPACE gesture.</li>
244      * </ul>
245      * The process of populating data is performed in background threads, so this method quickly returns also in case of large amount of data. The
246      * initialization callback is called in the JavaFX thread when data population has been completed.
247      * @param   listView        the {@code ListView}
248      * @param   pm              the {@code PresentationModel}
249      * @param   initCallback    the callback
250      **********************************************************************************************************************************************************/
251     public void bind (@Nonnull ListView<PresentationModel> listView, @Nonnull PresentationModel pm, @Nonnull Optional<Runnable> initCallback);
252 
253     /***********************************************************************************************************************************************************
254      * Binds a {@link ListView} to a {@link PresentationModel} and a callback. See {@link #bind(javafx.scene.control.ListView,
255      * it.tidalwave.ui.core.role.PresentationModel, java.util.Optional)}.
256      * @param   listView        the {@code ListView}
257      * @param   pm              the {@code PresentationModel}
258      * @param   initCallback    the callback
259      * @since   1.0-ALPHA-13
260      **********************************************************************************************************************************************************/
261     public default void bind (@Nonnull final ListView<PresentationModel> listView, @Nonnull final PresentationModel pm, @Nonnull final Runnable initCallback)
262       {
263         bind(listView, pm, Optional.of(initCallback));
264       }
265 
266     /***********************************************************************************************************************************************************
267      * Binds a {@link ComboBox} to a {@link PresentationModel}. See {@link #bind(javafx.scene.control.ListView, it.tidalwave.ui.core.role.PresentationModel,
268      * java.util.Optional)}.
269      * @param   listView        the {@code ListView}
270      * @param   pm              the {@code PresentationModel}
271      * @since   1.0-ALPHA-13
272      **********************************************************************************************************************************************************/
273     public default void bind (@Nonnull final ListView<PresentationModel> listView, @Nonnull final PresentationModel pm)
274       {
275         bind(listView, pm, Optional.empty());
276       }
277 
278     /***********************************************************************************************************************************************************
279      * Binds a {@link ComboBox} to a {@link PresentationModel} and an optional callback. The {@code PresentationModel} is used to populate the table. The
280      * following roles are used:
281      * <ul>
282      * <li>A {@link it.tidalwave.role.SimpleComposite} provides children {@code PresentationModel}s for each row.</li>
283      * <li>In each row, an {@link it.tidalwave.role.Aggregate<PresentationModel>} is used to provide the {@code PresentationModel}s for
284      *     each column.</li>
285      * <li>A {@link it.tidalwave.ui.core.role.Displayable} (optional) is used to provide the text to render for each item.</li>
286      * <li>A {@link CustomGraphicProvider} (optional) is used to provide the graphics to render for each item.</li>
287      * <li>A {@link it.tidalwave.ui.core.role.Styleable} (optional) is used to provide the rendering style for each item.</li>
288      * <li>A {@link it.tidalwave.ui.core.role.UserActionProvider} (optional) is used to provide the actions for creating a context menu;
289      *     the default action is also bound to the double click or SPACE gesture.</li>
290      * </ul>
291      * The process of populating data is performed in background threads, so this method quickly returns also in case of large amount of data. The
292      * initialization callback is called in the JavaFX thread when data population has been completed.
293      * @param   comboBox        the {@code ComboBox}
294      * @param   pm              the {@code PresentationModel}
295      * @param   initCallback    the callback
296      **********************************************************************************************************************************************************/
297     public void bind (@Nonnull ComboBox<PresentationModel> comboBox, @Nonnull PresentationModel pm, @Nonnull Optional<Runnable> initCallback);
298 
299     /***********************************************************************************************************************************************************
300      * Binds a {@link ComboBox} to a {@link PresentationModel} and a callback. See {@link #bind(javafx.scene.control.ComboBox,
301      * it.tidalwave.ui.core.role.PresentationModel, java.util.Optional)}.
302      * @param   comboBox        the {@code ComboBox}
303      * @param   pm              the {@code PresentationModel}
304      * @param   initCallback    the callback
305      * @since   1.0-ALPHA-13
306      **********************************************************************************************************************************************************/
307     public default void bind (@Nonnull final ComboBox<PresentationModel> comboBox, @Nonnull final PresentationModel pm, @Nonnull final Runnable initCallback)
308       {
309         bind(comboBox, pm, Optional.of(initCallback));
310       }
311 
312     /***********************************************************************************************************************************************************
313      * Binds a {@link ComboBox} to a {@link PresentationModel}. See {@link #bind(javafx.scene.control.ComboBox, it.tidalwave.ui.core.role.PresentationModel,
314      * java.util.Optional)}.
315      * @param   comboBox        the {@code ComboBox}
316      * @param   pm              the {@code PresentationModel}
317      * @since   1.0-ALPHA-13
318      **********************************************************************************************************************************************************/
319     public default void bind (@Nonnull final ComboBox<PresentationModel> comboBox, @Nonnull final PresentationModel pm)
320       {
321         bind(comboBox, pm, Optional.empty());
322       }
323 
324     /***********************************************************************************************************************************************************
325      * Given a {@link PresentationModel} that contains a {@link it.tidalwave.role.Composite}, populate the pane with {@link ToggleButton}s associated to the
326      * elements of the {@link it.tidalwave.role.Composite}. Each element is searched for the following roles:
327      * <ul>
328      * <li>{@link it.tidalwave.ui.core.role.UserActionProvider} (mandatory) to provide a callback for the button</li>
329      * <li>{@link it.tidalwave.ui.core.role.Displayable} to provide a text for the button</li>
330      * <li>{@link it.tidalwave.ui.core.role.Styleable} to provide a CSS style for the button</li>
331      * </ul>
332      * The pane must be pre-populated with at least one button, which will be queried for the CSS style.
333      * @param   pane        the {@code Pane}
334      * @param   pm          the {@code PresentationModel}
335      **********************************************************************************************************************************************************/
336     public void bindToggleButtons (@Nonnull Pane pane, @Nonnull PresentationModel pm);
337 
338     /***********************************************************************************************************************************************************
339      * Deprecated. Merge to bindToggleButtons, passing some arguments for choosing toggle or normal buttons.
340      * @deprecated
341      **********************************************************************************************************************************************************/
342     @Deprecated
343     public void bindButtonsInPane (@Nonnull GridPane gridPane, @Nonnull Collection<UserAction> actions);
344 
345     /***********************************************************************************************************************************************************
346      * Binds two properties of different types.
347      * @param   <T>             the target property type
348      * @param   <S>             the source property type
349      * @param   target          the target property
350      * @param   source          the source property
351      * @param   adapter         an adapter from one source to the target
352      * @since   2.0-ALPHA-1
353      **********************************************************************************************************************************************************/
354     public <T, S> void bind (@Nonnull final BoundProperty<? super T> target, @Nonnull final Property<? extends S> source, @Nonnull final Function<S, T> adapter);
355 
356     /***********************************************************************************************************************************************************
357      * Binds two properties of the same type.
358      * @param   <T>             the property type
359      * @param   target          the target property
360      * @param   source          the source property
361      * @since   2.0-ALPHA-1
362      **********************************************************************************************************************************************************/
363     public default <T> void bind (@Nonnull final BoundProperty<? super T> target, @Nonnull final Property<T> source)
364       {
365         bind(target, source, Function.identity());
366       }
367 
368     /***********************************************************************************************************************************************************
369      * Bidirectionally binds two properties of different types.
370      * @param   <T>             the former property type
371      * @param   <S>             the latter property type
372      * @param   property1       the former property
373      * @param   property2       the latter property
374      * @param   adapter         an adapter from one type to the other
375      * @param   reverseAdapter  the reverse adapter
376      * @since   2.0-ALPHA-1
377      **********************************************************************************************************************************************************/
378     public <T, S> void bindBidirectionally (@Nonnull final BoundProperty<? super T> property1,
379                                             @Nonnull final Property<S> property2,
380                                             @Nonnull final Function<? super S, T> adapter,
381                                             @Nonnull final Function<? super T, ? extends S> reverseAdapter);
382 
383     /***********************************************************************************************************************************************************
384      * {@inheritDoc}
385      **********************************************************************************************************************************************************/
386     public default <T> void bindBidirectionally (@Nonnull final BoundProperty<? super T> property1, @Nonnull final Property<T> property2)
387       {
388         bindBidirectionally(property1, property2, Function.identity(), Function.identity());
389       }
390 
391     /***********************************************************************************************************************************************************
392      * Bidirectionally binds two properties.
393      * @param   property1   the former property
394      * @param   property2   the latter property
395      **********************************************************************************************************************************************************/
396     public default void bindBidirectionally (@Nonnull final BoundProperty<? super Boolean> property1, @Nonnull final BooleanProperty property2)
397       {
398         bindBidirectionally(property1, property2, a -> a, a -> a);
399       }
400 
401     /***********************************************************************************************************************************************************
402      * Bidirectionally binds two properties.
403      * @param   property1   the former property
404      * @param   property2   the latter property
405      **********************************************************************************************************************************************************/
406     public default void bindBidirectionally (@Nonnull final BoundProperty<? super Integer> property1, @Nonnull final IntegerProperty property2)
407       {
408         bindBidirectionally(property1, property2, Number::intValue, a -> a);
409       }
410 
411     /***********************************************************************************************************************************************************
412      * Bidirectionally binds two properties.
413      * @param   property1   the former property
414      * @param   property2   the latter property
415      **********************************************************************************************************************************************************/
416     public default void bindBidirectionally (@Nonnull final BoundProperty<? super Long> property1, @Nonnull final LongProperty property2)
417       {
418         bindBidirectionally(property1, property2, Number::longValue, a -> a);
419       }
420 
421     /***********************************************************************************************************************************************************
422      * Bidirectionally binds two properties.
423      * @param   property1   the former property
424      * @param   property2   the latter property
425      **********************************************************************************************************************************************************/
426     public default void bindBidirectionally (@Nonnull final BoundProperty<? super Double> property1, @Nonnull final DoubleProperty property2)
427       {
428         bindBidirectionally(property1, property2, Number::doubleValue, a -> a);
429       }
430 
431     /***********************************************************************************************************************************************************
432      *
433      **********************************************************************************************************************************************************/
434     public void bindBidirectionally (@Nonnull TextField textField, @Nonnull BoundProperty<String> textProperty,  @Nonnull BoundProperty<Boolean> validProperty);
435 
436     /***********************************************************************************************************************************************************
437      * Shows a modal dialog with the given content and provides feedback by means of the given notification.
438      * @param   notification  the object notifying whether the operation is confirmed or cancelled
439      * @since   1.1-ALPHA-6
440      **********************************************************************************************************************************************************/
441     public default void showInModalDialog (@Nonnull final UserNotification notification)
442       {
443         showInModalDialog(UserNotificationWithFeedback.notificationWithFeedback()
444                                                       .withCaption(notification.getCaption())
445                                                       .withText(notification.getText()));
446       }
447 
448     /***********************************************************************************************************************************************************
449      * Shows a modal dialog with the given content and provides feedback by means of the given notification.
450      * @param  node          the dialog content
451      * @param  notification  the object notifying whether the operation is confirmed or cancelled
452      **********************************************************************************************************************************************************/
453     public void showInModalDialog (@Nonnull UserNotificationWithFeedback notification, @Nonnull Optional<Node> node);
454 
455     // FIXME: use a Builder, merge with the above
456     public default void showInModalDialog (@Nonnull final Node node,
457                                            @Nonnull final UserNotificationWithFeedback notification,
458                                            @Nonnull final BoundProperty<Boolean> valid)
459       {
460         showInModalDialog(notification, Optional.of(node));
461       }
462 
463     @Deprecated
464     public default void showInModalDialog (@Nonnull final Node node, @Nonnull final UserNotificationWithFeedback notification)
465       {
466         showInModalDialog(notification, Optional.of(node));
467       }
468 
469     public default void showInModalDialog (@Nonnull final UserNotificationWithFeedback notification)
470       {
471         showInModalDialog(notification, Optional.empty());
472       }
473 
474     /***********************************************************************************************************************************************************
475      * Opens the FileChooser for selecting a file. The outcome of the operation (confirmed or cancelled) will be notified to the given notification object. The
476      * selected file will be set to the given bound property, which can be also used to set the default value rendered on the FileChooser.
477      * @param  notification  the object notifying whether the operation is confirmed or cancelled
478      * @param  selectedFile  the property containing the selected file
479      **********************************************************************************************************************************************************/
480     public void openFileChooserFor (@Nonnull UserNotificationWithFeedback notification, @Nonnull BoundProperty<Path> selectedFile);
481 
482     /***********************************************************************************************************************************************************
483      * Opens the FileChooser for selecting a folder. The outcome of the operation (confirmed or cancelled) will be notified to the given notification object.
484      * The selected folder will be set to the given bound property, which can be also used to set the default value rendered on the FileChooser.
485      * @param  notification    the object notifying whether the operation is confirmed or cancelled
486      * @param  selectedFolder  the property containing the selected folder
487      **********************************************************************************************************************************************************/
488     public void openDirectoryChooserFor (@Nonnull UserNotificationWithFeedback notification, @Nonnull BoundProperty<Path> selectedFolder);
489   }