Skip to content

Method: lambda$pmFor$3(SimpleEntity)

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.example.presentation.impl;
27:
28: import javax.annotation.Nonnull;
29: import javax.annotation.PostConstruct;
30: import java.nio.file.Path;
31: import java.nio.file.Paths;
32: import org.springframework.stereotype.Component;
33: import it.tidalwave.util.annotation.VisibleForTesting;
34: import it.tidalwave.role.Aggregate;
35: import it.tidalwave.role.ui.BoundProperty;
36: import it.tidalwave.role.ui.Displayable;
37: import it.tidalwave.role.ui.PresentationModel;
38: import it.tidalwave.role.ui.PresentationModelAggregate;
39: import it.tidalwave.role.ui.Selectable;
40: import it.tidalwave.role.ui.UserAction;
41: import it.tidalwave.role.ui.UserActionProvider;
42: import it.tidalwave.role.ui.Visible;
43: import it.tidalwave.role.ui.example.model.Dao;
44: import it.tidalwave.role.ui.example.model.SimpleDciEntity;
45: import it.tidalwave.role.ui.example.model.SimpleEntity;
46: import it.tidalwave.role.ui.example.presentation.MainPanelPresentation;
47: import it.tidalwave.role.ui.example.presentation.MainPanelPresentation.Bindings;
48: import it.tidalwave.role.ui.example.presentation.MainPanelPresentationControl;
49: import lombok.Getter;
50: import lombok.RequiredArgsConstructor;
51: import static it.tidalwave.util.Parameters.r;
52: import static it.tidalwave.util.ui.UserNotificationWithFeedback.*;
53: import static it.tidalwave.role.ui.Presentable._Presentable_;
54: import static it.tidalwave.role.ui.spi.PresentationModelCollectors.toCompositePresentationModel;
55:
56: /***************************************************************************************************************************************************************
57: *
58: * @stereotype Control
59: *
60: * @author Fabrizio Giudici
61: *
62: **************************************************************************************************************************************************************/
63: @Component @RequiredArgsConstructor
64: public class DefaultMainPanelPresentationControl implements MainPanelPresentationControl
65: {
66: private static final Path USER_HOME = Paths.get(System.getProperty("user.home"));
67:
68: // START SNIPPET: injections
69: @Nonnull
70: private final Dao dao;
71:
72: @Nonnull
73: private final MainPanelPresentation presentation;
74: // END SNIPPET: injections
75:
76: // For each button on the presentation that can do something, a UserAction is provided.
77: // START SNIPPET: userActions
78: @Getter
79: private final UserAction actionButton = UserAction.of(this::onButtonPressed,
80: Displayable.of("Press me"));
81:
82: @Getter
83: private final UserAction actionDialogOk = UserAction.of(this::onButtonDialogOkPressed,
84: Displayable.of("Dialog with ok"));
85:
86: @Getter
87: private final UserAction actionDialogCancelOk = UserAction.of(this::onButtonDialogOkCancelPressed,
88: Displayable.of("Dialog with ok/cancel"));
89:
90: @Getter
91: private final UserAction actionPickFile = UserAction.of(this::onButtonPickFilePressed,
92: Displayable.of("Pick file"));
93:
94: @Getter
95: private final UserAction actionPickDirectory = UserAction.of(this::onButtonPickDirectoryPressed,
96: Displayable.of("Pick directory"));
97: // END SNIPPET: userActions
98: // START SNIPPET: bindings
99: private final Bindings bindings = Bindings.builder()
100: .actionButton(actionButton)
101: .actionDialogOk(actionDialogOk)
102: .actionDialogCancelOk(actionDialogCancelOk)
103: .actionPickFile(actionPickFile)
104: .actionPickDirectory(actionPickDirectory)
105: .build();
106: // END SNIPPET: bindings
107:
108: // Then there can be a set of variables that represent the internal state of the control.
109: @VisibleForTesting int status = 1;
110:
111: /***********************************************************************************************************************************************************
112: * At {@link PostConstruct} time the control just performs the binding to the presentation.
113: **********************************************************************************************************************************************************/
114: // START SNIPPET: initialization
115: @PostConstruct
116: @VisibleForTesting void initialize()
117: {
118: presentation.bind(bindings);
119: }
120: // END SNIPPET: initialization
121:
122: /***********************************************************************************************************************************************************
123: * {@inheritDoc}
124: *
125: * This method demonstrates the typical idiom for populating model:
126: *
127: * 1. A dao is called to provide raw model - let's say in form of collections;
128: * 2. Objects in the collection are transformed into PresentationModels.
129: * 3. The PresentationModels are then passed to the presentation.
130: **********************************************************************************************************************************************************/
131: // START SNIPPET: populate
132: @Override
133: public void populate ()
134: {
135: final var entities1 = dao.getSimpleEntities();
136: final var entities2 = dao.getDciEntities();
137: final var files = dao.getFiles();
138: final var pm1 = entities1.stream().map(this::pmFor).collect(toCompositePresentationModel());
139: final var pm2 = entities2.stream().map(this::pmFor).collect(toCompositePresentationModel());
140: final var pm3 = files.stream()
141: .map(item -> item.as(_Presentable_).createPresentationModel())
142: .collect(toCompositePresentationModel(r(Visible.INVISIBLE)));
143: presentation.populate(pm1, pm2, pm3);
144: }
145: // END SNIPPET: populate
146:
147: /***********************************************************************************************************************************************************
148: * Factory method for the PresentationModel of SimpleEntity instances.
149: *
150: * It aggregates a few extra roles into the PresentationModel that are used by the control, such as callbacks
151: * for action associated to the context menu. Also a Displayable role is usually injected to control the rendering
152: * of entities.
153: **********************************************************************************************************************************************************/
154: // START SNIPPET: pmSimpleEntity
155: @Nonnull
156: private PresentationModel pmFor (@Nonnull final SimpleEntity entity)
157: {
158: final Selectable selectable = () -> onSelected(entity);
159: final var action1 = UserAction.of(() -> action1(entity), Displayable.of("Action 1"));
160: final var action2 = UserAction.of(() -> action2(entity), Displayable.of("Action 2"));
161: final var action3 = UserAction.of(() -> action3(entity), Displayable.of("Action 3"));
162: return PresentationModel.of(entity, r(Displayable.of("Item #" + entity.getName()),
163: selectable,
164: UserActionProvider.of(action1, action2, action3)));
165: }
166: // END SNIPPET: pmSimpleEntity
167:
168: /***********************************************************************************************************************************************************
169: * Factory method for the PresentationModel of SimpleDciEntity instances.
170: **********************************************************************************************************************************************************/
171: // START SNIPPET: pmSimpleDciEntity
172: @Nonnull
173: private PresentationModel pmFor (@Nonnull final SimpleDciEntity entity)
174: {
175: // FIXME: column names
176: final Aggregate<PresentationModel> aggregate = PresentationModelAggregate.newInstance()
177: .withPmOf("C1", r(Displayable.of(entity.getName())))
178: .withPmOf("C2", r(Displayable.of("" + entity.getAttribute1())))
179: .withPmOf("C3", r(Displayable.of("" + entity.getAttribute2())));
180: final Selectable selectable = () -> onSelected(entity);
181: final var action1 = UserAction.of(() -> action1(entity), Displayable.of("Action 1"));
182: final var action2 = UserAction.of(() -> action2(entity), Displayable.of("Action 2"));
183: final var action3 = UserAction.of(() -> action3(entity), Displayable.of("Action 3"));
184: // No explicit Displayable here, as the one inside SimpleDciEntity is used.
185: return PresentationModel.of(entity, r(aggregate, selectable, UserActionProvider.of(action1, action2, action3)));
186: }
187: // END SNIPPET: pmSimpleDciEntity
188:
189: // Below simple business methods, as per usual business.
190:
191: /***********************************************************************************************************************************************************
192: *
193: **********************************************************************************************************************************************************/
194: // START SNIPPET: onButtonPressed
195: private void onButtonPressed()
196: {
197: presentation.notify("Button pressed");
198: status++;
199: bindings.textProperty.set(Integer.toString(status));
200: }
201: // END SNIPPET: onButtonPressed
202:
203: /***********************************************************************************************************************************************************
204: *
205: **********************************************************************************************************************************************************/
206: // START SNIPPET: onButtonDialogOkPressed
207: private void onButtonDialogOkPressed()
208: {
209: presentation.notify(notificationWithFeedback()
210: .withCaption("Notification")
211: .withText("Now press the button")
212: .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Pressed ok"))));
213: }
214: // END SNIPPET: onButtonDialogOkPressed
215:
216: /***********************************************************************************************************************************************************
217: *
218: **********************************************************************************************************************************************************/
219: // START SNIPPET: onButtonDialogOkCancelPressed
220: private void onButtonDialogOkCancelPressed()
221: {
222: presentation.notify(notificationWithFeedback()
223: .withCaption("Notification")
224: .withText("Now press the button")
225: .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Pressed ok"))
226: .withOnCancel(() -> presentation.notify("Pressed cancel"))));
227: }
228: // END SNIPPET: onButtonDialogOkCancelPressed
229:
230: /***********************************************************************************************************************************************************
231: * This method demonstrates how to pick a file name by using the proper UI dialog.
232: **********************************************************************************************************************************************************/
233: // START SNIPPET: onButtonPickFilePressed
234: private void onButtonPickFilePressed()
235: {
236: final var selectedFile = new BoundProperty<>(USER_HOME);
237: presentation.pickFile(selectedFile,
238: notificationWithFeedback()
239: .withCaption("Pick a file")
240: .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Selected file: " + selectedFile.get()))
241: .withOnCancel(() -> presentation.notify("Selection cancelled"))));
242: }
243: // END SNIPPET: onButtonPickFilePressed
244:
245: /***********************************************************************************************************************************************************
246: * This method demonstrates how to pick a directory name by using the proper UI dialog.
247: **********************************************************************************************************************************************************/
248: // START SNIPPET: onButtonPickDirectoryPressed
249: private void onButtonPickDirectoryPressed()
250: {
251: final var selectedFolder = new BoundProperty<>(USER_HOME);
252: presentation.pickDirectory(selectedFolder,
253: notificationWithFeedback()
254: .withCaption("Pick a directory")
255: .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Selected directory: " + selectedFolder.get()))
256: .withOnCancel(() -> presentation.notify("Selection cancelled"))));
257: }
258: // END SNIPPET: onButtonPickDirectoryPressed
259:
260: /***********************************************************************************************************************************************************
261: *
262: **********************************************************************************************************************************************************/
263: // START SNIPPET: onSelected
264: private void onSelected (@Nonnull final Object object)
265: {
266: presentation.notify("Selected " + object);
267: }
268: // END SNIPPET: onSelected
269:
270: /***********************************************************************************************************************************************************
271: *
272: **********************************************************************************************************************************************************/
273: // START SNIPPET: action1
274: private void action1 (@Nonnull final Object object)
275: {
276: presentation.notify("Action 1 on " + object);
277: }
278: // END SNIPPET: action1
279:
280: /***********************************************************************************************************************************************************
281: *
282: **********************************************************************************************************************************************************/
283: private void action2 (@Nonnull final Object object)
284: {
285: presentation.notify("Action 2 on " + object);
286: }
287:
288: /***********************************************************************************************************************************************************
289: *
290: **********************************************************************************************************************************************************/
291: private void action3 (@Nonnull final Object object)
292: {
293: presentation.notify("Action 3 on " + object);
294: }
295: }