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 }