1 /*
2 * *************************************************************************************************************************************************************
3 *
4 * SteelBlue: DCI User Interfaces
5 * http://tidalwave.it/projects/steelblue
6 *
7 * Copyright (C) 2015 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8 *
9 * *************************************************************************************************************************************************************
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18 *
19 * *************************************************************************************************************************************************************
20 *
21 * git clone https://bitbucket.org/tidalwave/steelblue-src
22 * git clone https://github.com/tidalwave-it/steelblue-src
23 *
24 * *************************************************************************************************************************************************************
25 */
26 package it.tidalwave.ui.core.role;
27
28 import jakarta.annotation.Nonnull;
29 import java.util.Collection;
30 import java.util.Collections;
31 import it.tidalwave.util.As;
32 import it.tidalwave.util.NamedCallback;
33 import it.tidalwave.util.Parameters;
34 import it.tidalwave.role.SimpleComposite;
35 import it.tidalwave.ui.core.Mutable;
36 import it.tidalwave.ui.core.role.impl.DefaultPresentationModel;
37 import org.apiguardian.api.API;
38 import static it.tidalwave.util.Parameters.r;
39 import static it.tidalwave.ui.core.role.Presentable._Presentable_;
40 import static org.apiguardian.api.API.Status.EXPERIMENTAL;
41
42 /***************************************************************************************************************************************************************
43 *
44 * TODO: As the NetBeans Node, it should allow children, have event listeners for children added/removed/changed.
45 * This class so becomes the true M in MVC.
46 *
47 * @stereotype Role
48 * @since 2.0-ALPHA-1
49 * @author Fabrizio Giudici
50 *
51 **************************************************************************************************************************************************************/
52 public interface PresentationModel extends As, Mutable
53 {
54 /** Shortcut for {@link it.tidalwave.util.As}. */
55 public static final Class<PresentationModel> _PresentationModel_ = PresentationModel.class;
56
57 /** Shortcut for {@link it.tidalwave.util.As}. */
58 public static final As.Type<SimpleComposite<PresentationModel>> _SimpleCompositeOfPresentationModel_ = As.type(SimpleComposite.class);
59
60 public static final String PROPERTY_CHILDREN = "children";
61
62 /** This is an undocumented feature. If you add a {@link NamedCallback} with this name as a role in this object, it will be called back when
63 {@link #dispose()} is called. */
64 public static final String CALLBACK_DISPOSE = "dispose";
65
66 public static final String P_VERBOSE_TOSTRING = PresentationModel.class.getCanonicalName() + ".verboseToString";
67
68 public static final String PARAM_OWNER = "owner";
69 public static final String PARAM_ROLE = "role";
70
71 /***********************************************************************************************************************************************************
72 * Disposes this object.
73 **********************************************************************************************************************************************************/
74 public void dispose();
75
76 /***********************************************************************************************************************************************************
77 * {@return a new instance given an owner and no roles}.
78 * @param owner the owner
79 * @since 3.2-ALPHA-3
80 **********************************************************************************************************************************************************/
81 @Nonnull
82 public static PresentationModel of (@Nonnull final Object owner)
83 {
84 Parameters.mustNotBeArrayOrCollection(owner, PARAM_OWNER);
85 return of(owner, Collections.emptyList());
86 }
87
88 /***********************************************************************************************************************************************************
89 * {@return a new instance given an owner and a single role}.
90 * @param owner the owner
91 * @param role the role (or a {@link it.tidalwave.util.RoleFactory})
92 * @since 3.2-ALPHA-3
93 **********************************************************************************************************************************************************/
94 @Nonnull
95 public static PresentationModel of (@Nonnull final Object owner, @Nonnull final Object role)
96 {
97 Parameters.mustNotBeArrayOrCollection(owner, PARAM_OWNER);
98 Parameters.mustNotBeArrayOrCollection(role, PARAM_ROLE);
99 return of(owner, r(role));
100 }
101
102 /***********************************************************************************************************************************************************
103 * {@return a new instance given an owner and multiple roles}.
104 * @param owner the owner
105 * @param roles roles or {@link it.tidalwave.util.RoleFactory} instances
106 * @since 3.2-ALPHA-1
107 * @since 3.2-ALPHA-3 (refactored)
108 **********************************************************************************************************************************************************/
109 @Nonnull
110 public static PresentationModel of (@Nonnull final Object owner, @Nonnull final Collection<Object> roles)
111 {
112 Parameters.mustNotBeArrayOrCollection(owner, PARAM_OWNER);
113 return new DefaultPresentationModel(owner, roles);
114 }
115
116 /***********************************************************************************************************************************************************
117 * {@return an empty instance (no roles, with the exception of a dummy {@link Displayable})}.
118 * @since 3.2-ALPHA-3
119 **********************************************************************************************************************************************************/
120 @Nonnull
121 public static PresentationModel empty()
122 {
123 // TODO: cache a singleton, but don't do eager initialization (e.g. a final static), as it would deadlock
124 return of("", Displayable.of("<empty presentation model>"));
125 }
126
127 /***********************************************************************************************************************************************************
128 * {@return a new instance from an owner which might have the {@link Presentable} role}. If it is present, it is called to create the
129 * {@code PresentationModel}; otherwise a default one is created. Additional roles are added.
130 * @param owner the owner
131 * @param roles roles or {@link it.tidalwave.util.RoleFactory} instances
132 * @since 3.2-ALPHA-8
133 **********************************************************************************************************************************************************/
134 @API(status = EXPERIMENTAL) // TODO: perhaps it could be merged to of().
135 @Nonnull
136 public static PresentationModel ofMaybePresentable (@Nonnull final As owner, @Nonnull final Collection<Object> roles)
137 {
138 Parameters.mustNotBeArrayOrCollection(owner, PARAM_OWNER);
139 return owner.maybeAs(_Presentable_)
140 .map(p -> p.createPresentationModel(roles))
141 .orElseGet(() -> of(owner, roles));
142 }
143
144 /***********************************************************************************************************************************************************
145 * {@return a new instance from an owner which might have the {@link Presentable} role}. If it is present, it is called to create the
146 * {@code PresentationModel}; otherwise a default one is created.
147 * @param owner the owner
148 * @since 3.2-ALPHA-8
149 **********************************************************************************************************************************************************/
150 @API(status = EXPERIMENTAL) // TODO: perhaps it could be merged to of().
151 @Nonnull
152 public static PresentationModel ofMaybePresentable (@Nonnull final As owner)
153 {
154 return ofMaybePresentable(owner, Collections.emptyList());
155 }
156
157 /***********************************************************************************************************************************************************
158 * Sets the verbose mode for {@link java.lang.Object#toString} implementations of {@code PresentationModel}. Looking at the implementation of
159 * {@link javafx.scene.control.cell.DefaultTreeCell}, the code always calls {@code toString()} during an update, even though the text value is later
160 * overridden; hence, this method should be as fast as possible. By default, the shortened class name and system id of the owner object is returned;
161 * set verbosity to have the owner object {@code toString()} called instead.
162 * It is also possible to set system the property {@code it.tidalwave.ui.core.role.PresentationModel.verboseToString}.
163 * @param verbose the verbosity
164 * @since 2.0-ALPHA-4
165 * @see #isVerboseToString()
166 **********************************************************************************************************************************************************/
167 public static void setVerboseToString (final boolean verbose)
168 {
169 DefaultPresentationModel.setVerboseToString(verbose);
170 }
171
172 /***********************************************************************************************************************************************************
173 * {@return the verbose mode for {@link java.lang.Object#toString} implementations of {@code PresentationModel}}.
174 * @since 2.0-ALPHA-4
175 * @see #setVerboseToString(boolean)
176 **********************************************************************************************************************************************************/
177 public static boolean isVerboseToString()
178 {
179 return DefaultPresentationModel.isVerboseToString();
180 }
181 }