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