DefaultMainScreenPresentationControl.java

  1. /*
  2.  * #%L
  3.  * *********************************************************************************************************************
  4.  *
  5.  * SteelBlue
  6.  * http://steelblue.tidalwave.it - git clone git@bitbucket.org:tidalwave/steelblue-src.git
  7.  * %%
  8.  * Copyright (C) 2015 - 2015 Tidalwave s.a.s. (http://tidalwave.it)
  9.  * %%
  10.  *
  11.  * *********************************************************************************************************************
  12.  *
  13.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  14.  * the License. You may obtain a copy of the License at
  15.  *
  16.  *     http://www.apache.org/licenses/LICENSE-2.0
  17.  *
  18.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  19.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  20.  * specific language governing permissions and limitations under the License.
  21.  *
  22.  * *********************************************************************************************************************
  23.  *
  24.  *
  25.  *
  26.  * *********************************************************************************************************************
  27.  * #L%
  28.  */
  29. package it.tidalwave.role.ui.javafx.example.large.mainscreen.impl;

  30. import javax.annotation.Nonnull;
  31. import javax.annotation.PostConstruct;
  32. import javax.inject.Inject;
  33. import java.util.Collection;
  34. import java.nio.file.Path;
  35. import java.nio.file.Paths;
  36. import it.tidalwave.role.Aggregate;
  37. import it.tidalwave.role.ui.BoundProperty;
  38. import it.tidalwave.role.ui.Displayable;
  39. import it.tidalwave.role.ui.PresentationModel;
  40. import it.tidalwave.role.ui.PresentationModelAggregate;
  41. import it.tidalwave.role.ui.Selectable;
  42. import it.tidalwave.role.ui.UserAction;
  43. import it.tidalwave.role.ui.UserActionProvider;
  44. import it.tidalwave.role.ui.Visible;
  45. import it.tidalwave.role.ui.javafx.example.large.data.Dao;
  46. import it.tidalwave.role.ui.javafx.example.large.data.SimpleEntity;
  47. import it.tidalwave.role.ui.javafx.example.large.data.SimpleDciEntity;
  48. import it.tidalwave.role.ui.javafx.example.large.data.impl.FileEntity;
  49. import it.tidalwave.role.ui.javafx.example.large.mainscreen.MainScreenPresentation;
  50. import it.tidalwave.role.ui.javafx.example.large.mainscreen.MainScreenPresentation.Bindings;
  51. import it.tidalwave.role.ui.javafx.example.large.mainscreen.MainScreenPresentationControl;
  52. import static it.tidalwave.role.ui.Presentable._Presentable_;
  53. import static it.tidalwave.util.Parameters.r;
  54. import static it.tidalwave.util.ui.UserNotificationWithFeedback.*;
  55. import static it.tidalwave.role.ui.spi.PresentationModelCollectors.toCompositePresentationModel;

  56. /***********************************************************************************************************************
  57.  *
  58.  * @stereotype  Control
  59.  *
  60.  * @author  Fabrizio Giudici (Fabrizio.Giudici@tidalwave.it)
  61.  *
  62.  **********************************************************************************************************************/
  63. public class DefaultMainScreenPresentationControl implements MainScreenPresentationControl
  64.   {
  65.     private static final Path USER_HOME = Paths.get(System.getProperty("user.home"));

  66.     // The presentation is injected by the infrastructure in form of its interface.
  67.     @Inject
  68.     private MainScreenPresentation presentation;

  69.     // As usual, also other required objects can be injected.
  70.     @Inject
  71.     private Dao dao;

  72.     // For each button on the presentation that can do something, a UserAction is provided.
  73.     private final UserAction buttonAction = UserAction.of(this::onButtonPressed,
  74.                                                           Displayable.of("Press me"));

  75.     private final UserAction actionDialogOk = UserAction.of(this::onButtonDialogOkPressed,
  76.                                                             Displayable.of("Dialog with ok"));

  77.     private final UserAction actionDialogCancelOk = UserAction.of(this::onButtonDialogOkCancelPressed,
  78.                                                                   Displayable.of("Dialog with ok/cancel"));

  79.     private final UserAction actionPickFile = UserAction.of(this::onButtonPickFilePressed,
  80.                                                             Displayable.of("Pick file"));

  81.     private final UserAction actionPickDirectory = UserAction.of(this::onButtonPickDirectoryPressed,
  82.                                                                  Displayable.of("Pick directory"));

  83.     private final Bindings bindings = Bindings.builder()
  84.                                               .buttonAction(buttonAction)
  85.                                               .actionDialogOk(actionDialogOk)
  86.                                               .actionDialogCancelOk(actionDialogCancelOk)
  87.                                               .actionPickFile(actionPickFile)
  88.                                               .actionPickDirectory(actionPickDirectory)
  89.                                               .build();

  90.     // Then there can be a set of variables that represent the internal state of the control.
  91.     private int status = 1;

  92.     /*******************************************************************************************************************
  93.      *
  94.      * At {@link PostConstruct} time the control just performs the binding to the presentation.
  95.      *
  96.      ******************************************************************************************************************/
  97.     @PostConstruct
  98.     private void initialize()
  99.       {
  100.         presentation.bind(bindings);
  101.       }

  102.     /*******************************************************************************************************************
  103.      *
  104.      * {@inheritDoc}
  105.      *
  106.      * This method demonstrates the typical idiom for populating data:
  107.      *
  108.      * 1. A dao is called to provide raw data - let's say in form of collections;
  109.      * 2. Objects in the collection are transformed into PresentationModels.
  110.      * 3. The PresentationModels are then passed to the presentation.
  111.      *
  112.      ******************************************************************************************************************/
  113.     @Override
  114.     public void start()
  115.       {
  116.         presentation.showUp();
  117.         final Collection<SimpleEntity> entities1 = dao.getSimpleEntities();
  118.         final Collection<SimpleDciEntity> entities2 = dao.getDciEntities();
  119.         final Collection<FileEntity> files = dao.getFiles();
  120.         final PresentationModel pm1 = entities1.stream().map(this::pmFor)
  121.                                                         .collect(toCompositePresentationModel());
  122.         final PresentationModel pm2 = entities2.stream().map(this::pmFor)
  123.                                                         .collect(toCompositePresentationModel());
  124.         final PresentationModel pm3 = files.stream().map(item -> item.as(_Presentable_).createPresentationModel())
  125.                                                .collect(toCompositePresentationModel(r(Visible.INVISIBLE)));
  126.         presentation.populate(pm1, pm2, pm3);
  127.       }

  128.     /*******************************************************************************************************************
  129.      *
  130.      * Factory method for the PresentationModel of SimpleEntity instances.
  131.      *
  132.      * It aggregates a few extra roles into the PresentationModel that are used by the control, such as callbacks
  133.      * for action associated to the context menu. Also a Displayable role is usually injected to control the rendering
  134.      * of entities.
  135.      *
  136.      ******************************************************************************************************************/
  137.     @Nonnull
  138.     private PresentationModel pmFor (@Nonnull final SimpleEntity entity)
  139.       {
  140.         final Selectable selectable = () -> onSelected(entity);
  141.         final UserAction action1 = UserAction.of(() -> action1(entity), Displayable.of("Action 1"));
  142.         final UserAction action2 = UserAction.of(() -> action2(entity), Displayable.of("Action 2"));
  143.         final UserAction action3 = UserAction.of(() -> action3(entity), Displayable.of("Action 3"));
  144.         return PresentationModel.of(entity, r(Displayable.of("Item #" + entity.getName()),
  145.                                               selectable,
  146.                                               UserActionProvider.of(action1, action2, action3)));
  147.       }

  148.     /*******************************************************************************************************************
  149.      *
  150.      * Factory method for the PresentationModel of SimpleDciEntity instances.
  151.      *
  152.      ******************************************************************************************************************/
  153.     @Nonnull
  154.     private PresentationModel pmFor (@Nonnull final SimpleDciEntity entity)
  155.       {
  156.         // FIXME: column names
  157.         final Aggregate<PresentationModel> aggregate = PresentationModelAggregate.newInstance()
  158.              .withPmOf("C1", r(Displayable.of(entity.getName())))
  159.              .withPmOf("C2", r(Displayable.of("" + entity.getAttribute1())))
  160.              .withPmOf("C3", r(Displayable.of("" + entity.getAttribute2())));
  161.         final Selectable selectable = () -> onSelected(entity);
  162.         final UserAction action1 = UserAction.of(() -> action1(entity), Displayable.of("Action 1"));
  163.         final UserAction action2 = UserAction.of(() -> action2(entity), Displayable.of("Action 2"));
  164.         final UserAction action3 = UserAction.of(() -> action3(entity), Displayable.of("Action 3"));
  165.         // No explicit Displayable here, as the one inside SimpleDciEntity is used.
  166.         return PresentationModel.of(entity, r(aggregate, selectable, UserActionProvider.of(action1, action2, action3)));
  167.       }

  168.     // Below simple business methonds, as per usual business.

  169.     /*******************************************************************************************************************
  170.      *
  171.      ******************************************************************************************************************/
  172.     private void onButtonPressed()
  173.       {
  174.         presentation.notify("Button pressed");
  175.         status++;
  176.         bindings.textProperty.set(Integer.toString(status));
  177.       }

  178.     /*******************************************************************************************************************
  179.      *
  180.      ******************************************************************************************************************/
  181.     private void onButtonDialogOkPressed()
  182.       {
  183.         presentation.notify(notificationWithFeedback()
  184.                 .withCaption("Notification")
  185.                 .withText("Now press the button")
  186.                 .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Pressed ok"))));
  187.       }

  188.     /*******************************************************************************************************************
  189.      *
  190.      ******************************************************************************************************************/
  191.     private void onButtonDialogOkCancelPressed()
  192.       {
  193.         presentation.notify(notificationWithFeedback()
  194.                 .withCaption("Notification")
  195.                 .withText("Now press the button")
  196.                 .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Pressed ok"))
  197.                                         .withOnCancel(() -> presentation.notify("Pressed cancel"))));
  198.       }

  199.     /*******************************************************************************************************************
  200.      *
  201.      * This method demonstrates how to pick a file name by using the proper UI dialog.
  202.      *
  203.      ******************************************************************************************************************/
  204.     private void onButtonPickFilePressed()
  205.       {
  206.         final BoundProperty<Path> selectedFile = new BoundProperty<>(USER_HOME);
  207.         presentation.pickFile(selectedFile,
  208.             notificationWithFeedback()
  209.                 .withCaption("Pick a file")
  210.                 .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Selected file: " + selectedFile.get()))
  211.                                         .withOnCancel(() -> presentation.notify("Selection cancelled"))));
  212.       }

  213.     /*******************************************************************************************************************
  214.      *
  215.      * This method demonstrates how to pick a directory name by using the proper UI dialog.
  216.      *
  217.      ******************************************************************************************************************/
  218.     private void onButtonPickDirectoryPressed()
  219.       {
  220.         final BoundProperty<Path> selectedFolder = new BoundProperty<>(USER_HOME);
  221.         presentation.pickDirectory(selectedFolder,
  222.             notificationWithFeedback()
  223.                 .withCaption("Pick a directory")
  224.                 .withFeedback(feedback().withOnConfirm(() -> presentation.notify("Selected folder: " + selectedFolder.get()))
  225.                                         .withOnCancel(() -> presentation.notify("Selection cancelled"))));
  226.       }

  227.     /*******************************************************************************************************************
  228.      *
  229.      ******************************************************************************************************************/
  230.     private void onSelected (@Nonnull final Object object)
  231.       {
  232.         presentation.notify("Selected " + object);
  233.       }

  234.     /*******************************************************************************************************************
  235.      *
  236.      ******************************************************************************************************************/
  237.     private void action1 (@Nonnull final Object object)
  238.       {
  239.         presentation.notify("Action 1 on " + object);
  240.       }

  241.     /*******************************************************************************************************************
  242.      *
  243.      ******************************************************************************************************************/
  244.     private void action2 (@Nonnull final Object object)
  245.       {
  246.         presentation.notify("Action 2 on " + object);
  247.       }

  248.     /*******************************************************************************************************************
  249.      *
  250.      ******************************************************************************************************************/
  251.     private void action3 (@Nonnull final Object object)
  252.       {
  253.         presentation.notify("Action 3 on " + object);
  254.       }
  255.   }