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