JavaFxAudioExplorerPresentationDelegate.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * blueMarine II: Semantic Media Centre
  5.  * http://tidalwave.it/projects/bluemarine2
  6.  *
  7.  * Copyright (C) 2015 - 2021 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
  12.  * the License. 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
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/bluemarine2-src
  23.  * git clone https://github.com/tidalwave-it/bluemarine2-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.bluemarine2.ui.audio.explorer.impl.javafx;

  28. import javax.annotation.Nonnull;
  29. import javax.inject.Inject;
  30. import java.util.Optional;
  31. import java.util.stream.Stream;
  32. import java.net.URI;
  33. import javafx.fxml.FXML;
  34. import javafx.scene.input.KeyCode;
  35. import javafx.scene.input.KeyEvent;
  36. import javafx.scene.layout.VBox;
  37. import javafx.scene.layout.HBox;
  38. import javafx.scene.layout.Pane;
  39. import javafx.scene.image.Image;
  40. import javafx.scene.image.ImageView;
  41. import javafx.scene.control.Button;
  42. import javafx.scene.control.Label;
  43. import javafx.scene.control.ListView;
  44. import it.tidalwave.role.ui.PresentationModel;
  45. import it.tidalwave.role.ui.UserAction;
  46. import it.tidalwave.role.ui.javafx.JavaFXBinder;
  47. import it.tidalwave.bluemarine2.ui.audio.explorer.AudioExplorerPresentation;
  48. import it.tidalwave.bluemarine2.ui.audio.renderer.AudioRendererPresentation;
  49. import lombok.Getter;
  50. import lombok.ToString;
  51. import lombok.extern.slf4j.Slf4j;
  52. import static java.util.stream.Collectors.*;
  53. import static it.tidalwave.bluemarine2.ui.impl.javafx.NodeFactory.*;

  54. /***********************************************************************************************************************
  55.  *
  56.  * The JavaFX Delegate for {@link AudioRendererPresentation}.
  57.  *
  58.  * @stereotype  JavaFXDelegate
  59.  *
  60.  * @author  Fabrizio Giudici
  61.  *
  62.  **********************************************************************************************************************/
  63. @Slf4j
  64. public class JavaFxAudioExplorerPresentationDelegate implements AudioExplorerPresentation
  65.   {
  66.     @Getter @ToString
  67.     static class Memento
  68.       {
  69.         private final int selectedIndex;

  70.         public Memento()
  71.           {
  72.             selectedIndex = 0;
  73.           }

  74.         public Memento (@Nonnull final ListView<PresentationModel> lvFiles)
  75.           {
  76.         // TODO: add further properties, such as the precise scroller position
  77.             selectedIndex = lvFiles.getSelectionModel().getSelectedIndex();
  78.           }

  79.         public void applyTo (@Nonnull final ListView<PresentationModel> lvFiles)
  80.           {
  81.             lvFiles.getSelectionModel().select(selectedIndex);
  82.             lvFiles.scrollTo(selectedIndex);
  83.           }
  84.       }

  85.     @FXML
  86.     private ListView<PresentationModel> lvFiles;

  87.     @FXML
  88.     private Button btUp;

  89.     @FXML
  90.     private Label lbFolderName;

  91.     @FXML
  92.     private HBox hbBrowserButtons;

  93.     @FXML
  94.     private Pane pnCoverArt;

  95.     @FXML
  96.     private ImageView ivCoverArt;

  97.     @FXML
  98.     private VBox vbDetails;

  99.     @Inject
  100.     private JavaFXBinder binder;

  101.     @FXML
  102.     private void initialize()
  103.       {
  104.         pnCoverArt.prefHeightProperty().bind(pnCoverArt.widthProperty());
  105.         ivCoverArt.fitWidthProperty().bind(pnCoverArt.widthProperty().multiply(0.9));
  106.         ivCoverArt.fitHeightProperty().bind(pnCoverArt.heightProperty().multiply(0.9));
  107.       }

  108.     @Override
  109.     public void bind (@Nonnull final Properties properties, @Nonnull final UserAction upAction)
  110.       {
  111.         binder.bind(btUp, upAction);
  112.         lbFolderName.textProperty().bind(properties.folderNameProperty());
  113.       }

  114.     @Override
  115.     public void showUp (@Nonnull final Object control)
  116.       {
  117.       }

  118.     @Override
  119.     public void populateBrowsers (@Nonnull final PresentationModel pm)
  120.       {
  121.         binder.bindToggleButtons(hbBrowserButtons, pm);
  122.       }

  123.     @Override
  124.     public void populateItems (@Nonnull final PresentationModel pm, @Nonnull final Optional<Object> optionalMemento)
  125.       {
  126.         binder.bind(lvFiles, pm, () ->
  127.           {
  128.             if (!lvFiles.getItems().isEmpty())
  129.               {
  130.                 ((Memento)optionalMemento.orElse(new Memento())).applyTo(lvFiles);
  131.                 lvFiles.requestFocus();
  132.               }
  133.           });
  134.       }

  135.     @Override
  136.     public void renderDetails (@Nonnull final String entityDetails)
  137.       {
  138.         vbDetails.getChildren().setAll(Stream.of(entityDetails.split("\n"))
  139.                                              .map(s -> label("track-details", s))
  140.                                              .collect(toList()));
  141.       }

  142.     @Override
  143.     public void focusOnMediaItems()
  144.       {
  145.         lvFiles.requestFocus();
  146.       }

  147.     @Override @Nonnull
  148.     public Object getMemento()
  149.       {
  150.         return new Memento(lvFiles);
  151.       }

  152.     @Override
  153.     public void setCoverArt (@Nonnull final Optional<URI> optionalCoverArtUri)
  154.       {
  155.         ivCoverArt.setImage(optionalCoverArtUri.map(uri -> new Image(uri.toString())).orElse(null));
  156.       }

  157.     /*******************************************************************************************************************
  158.      *
  159.      * With a remote there's no TAB key, so we must emulate some tab control with left and right arrows.
  160.      *
  161.      * FIXME: try to generalise (e.g. cyclefocus?) and move to JavaFxApplicationPresentationDelegate.
  162.      *
  163.      * @param   event   the key event
  164.      *
  165.      ******************************************************************************************************************/
  166.     @FXML
  167.     public void onKeyPressed (@Nonnull final KeyEvent event)
  168.       {
  169.         log.debug("onKeyPressed({})", event);

  170.         if (lvFiles.isFocused())
  171.           {
  172.             if (event.getCode().equals(KeyCode.LEFT))
  173.               {
  174.                 btUp.requestFocus();
  175.               }
  176.             else if (event.getCode().equals(KeyCode.RIGHT))
  177.               {
  178.                 hbBrowserButtons.getChildren().get(0).requestFocus();
  179.               }
  180.           }
  181.       }
  182.   }