package de.calette.mephisto3.ui; import callete.api.Callete; import callete.api.services.Service; import callete.api.services.music.MusicService; import callete.api.services.music.model.AlbumCollection; import callete.api.util.Config; import de.calette.mephisto3.Mephisto3; import de.calette.mephisto3.control.ControlListener; import de.calette.mephisto3.control.ServiceControlEvent; import de.calette.mephisto3.control.ServiceController; import de.calette.mephisto3.control.ServiceState; import de.calette.mephisto3.util.ComponentUtil; import de.calette.mephisto3.util.TransitionQueue; import de.calette.mephisto3.util.TransitionUtil; import javafx.animation.FadeTransition; import javafx.animation.Transition; import javafx.animation.TranslateTransition; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * The chooser that selects the active function of the radio. */ public class ServiceChooser implements ControlListener { private final static Logger LOG = LoggerFactory.getLogger(ServiceChooser.class); public static final int SCROLL_DURATION = 200; public static final int DISPLAY_DELAY = 500; private int index = 0; private List<ServiceNameBox> serviceBoxes = new ArrayList<>(); private Map<Service, Pane> serviceBoxesByService = new HashMap<>(); private Transition showFader; private Transition hideFader; private TranslateTransition scrollTransition; private TransitionQueue transitionQueue; private HBox overlay; private Center center; private final HBox scroller = new HBox(); private Pane musicSelector; private Text byArtist; private Text byName; private Text playbackSelection; private StackPane albumSelectorCenterStack; private MusicPlayerStatusBox playerStatusBox; public ServiceChooser(final Center center) { this.center = center; overlay = new HBox(); overlay.setOpacity(0); this.albumSelectorCenterStack = new StackPane(); overlay.getChildren().add(albumSelectorCenterStack); center.stackPane.getChildren().add(overlay); overlay.setAlignment(Pos.TOP_CENTER); overlay.setId("chooser"); overlay.setMinWidth(Mephisto3.WIDTH); overlay.setMinHeight(80); scroller.setPadding(new Insets(50, 0, 80, 460)); scroller.setAlignment(Pos.CENTER); transitionQueue = new TransitionQueue(scroller); scrollTransition = TransitionUtil.createTranslateByXTransition(scroller, SCROLL_DURATION, 0); showFader = TransitionUtil.createInFader(overlay, DISPLAY_DELAY); hideFader = TransitionUtil.createOutFader(overlay, DISPLAY_DELAY); createServiceNameBox(ServiceController.SERVICE_NAME_RADIO, Callete.getStreamingService()); createServiceNameBox(ServiceController.SERVICE_NAME_WEATHER, Callete.getWeatherService()); createServiceNameBox(ServiceController.SERVICE_NAME_SETTINGS, Callete.getSystemService()); createServiceNameBox(ServiceController.SERVICE_NAME_MP3, Callete.getNetworkMusicService()); if(Config.getConfiguration().getBoolean("google.enabled", true)) { createServiceNameBox(ServiceController.SERVICE_NAME_MUSIC, Callete.getGoogleMusicService()); } } /** * Adds a new entry to the chooser */ public void addService(final Service service) { Platform.runLater(new Runnable() { @Override public void run() { ServiceNameBox serviceBox = (ServiceNameBox) serviceBoxesByService.get(service); serviceBox.setLoaded(); LOG.debug("Activated service chooser for " + service); } }); } @Override public void controlEvent(ServiceControlEvent event) { final Service service = (Service) serviceBoxes.get(index).getUserData(); final ServiceNameBox searchSelectionBox = (ServiceNameBox) serviceBoxesByService.get(service); if(event.getEventType().equals(ServiceControlEvent.EVENT_TYPE.LONG_PUSH)) { //not assigned } else if(event.getEventType().equals(ServiceControlEvent.EVENT_TYPE.PUSH)) { if(!searchSelectionBox.isLoaded()) { return; } if(musicSelector != null && playbackSelection != null) { final FadeTransition blink = TransitionUtil.createBlink(playbackSelection); blink.setOnFinished(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { overlay.getChildren().remove(scroller); if(playbackSelection != null) { ServiceController.getInstance().removeControlListener(ServiceChooser.this); AlbumLetterSelector selector = new AlbumLetterSelector(ServiceChooser.this, albumSelectorCenterStack, (List<AlbumCollection>) playbackSelection.getUserData()); selector.showPanel(); if(playerStatusBox == null) { playerStatusBox = new MusicPlayerStatusBox(); center.stackPane.getChildren().add(playerStatusBox); } playerStatusBox.showPlayer(); } } }); blink.play(); } else { Platform.runLater(new Runnable() { @Override public void run() { if(service.equals(Callete.getGoogleMusicService())) { showMusicOptions(Callete.getGoogleMusicService(), searchSelectionBox); } else if(service.equals(Callete.getNetworkMusicService())) { showMusicOptions(Callete.getNetworkMusicService(), searchSelectionBox); } else { if(playerStatusBox != null) { playerStatusBox.hidePlayer(); } hideServiceChooser(); } } }); } } else { if(event.getEventType().equals(ServiceControlEvent.EVENT_TYPE.NEXT)) { if(musicSelector != null) { togglePlaybackSelection(); } else { scroll(-ServiceNameBox.SERVICE_BOX_WIDTH); } } else if(event.getEventType().equals(ServiceControlEvent.EVENT_TYPE.PREVIOUS)) { if(playbackSelection == null || playbackSelection == byArtist) { scroll(ServiceNameBox.SERVICE_BOX_WIDTH); } else { togglePlaybackSelection(); } } Service selection = (Service) serviceBoxes.get(index).getUserData(); if(!selection.equals(Callete.getGoogleMusicService()) && !selection.equals(Callete.getNetworkMusicService())) { hideMusicOptions(searchSelectionBox); } } } // --------------- Helper ----------------------------- private void togglePlaybackSelection() { Text oldSelection; if(playbackSelection == null || playbackSelection == byName) { playbackSelection = byArtist; oldSelection = byName; } else { playbackSelection = byName; oldSelection = byArtist; } TransitionUtil.createScaler(playbackSelection, 1.2).play(); TransitionUtil.createScaler(oldSelection, 1.0).play(); } /** * Display method of the whole chooser, updates the control. */ public void showServiceChooser() { ServiceController.getInstance().addControlListener(this); ServiceController.getInstance().removeControlListener(center); final ServiceNameBox serviceNameBox = serviceBoxes.get(index); Platform.runLater(new Runnable() { @Override public void run() { overlay.getChildren().add(scroller); showFader.play(); center.activeControlPanel.hidePanel(); serviceNameBox.select(); if(playerStatusBox != null && playerStatusBox.isPlaying()) { playerStatusBox.showPlayer(); } } }); } /** * Hides the Service Chooser, updates the control. */ private void hideServiceChooser() { ServiceController.getInstance().removeControlListener(this); ServiceController.getInstance().addControlListener(center); ServiceController.getInstance().setControlEnabled(false); final FadeTransition blink = TransitionUtil.createBlink(serviceBoxes.get(index)); blink.setOnFinished(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { playCloseAnimationAndHide(); } }); final Service service = (Service) serviceBoxes.get(index).getUserData(); final ServiceState serviceState = ServiceController.getInstance().getServiceState(); if(!serviceState.getService().equals(service)) { blink.play(); } else { playCloseAnimationAndHide(); } } /** * Closes the chooser, resets the UI state. */ private void playCloseAnimationAndHide() { final Service service = (Service) serviceBoxes.get(index).getUserData(); hideFader.play(); Platform.runLater(new Runnable() { @Override public void run() { overlay.getChildren().remove(scroller); ServiceController.getInstance().switchService(service); } }); } private void showMusicOptions(MusicService musicService, Pane searchSelectionBox) { if(musicSelector == null) { musicSelector = new VBox(20); musicSelector.setOpacity(0); byArtist = ComponentUtil.createText("Albums by Artist", "selector", musicSelector, musicService.getAlbumsByArtistLetter()); byName = ComponentUtil.createText("Albums by Name", "selector", musicSelector, musicService.getAlbumByNameLetter()); } if(!searchSelectionBox.getChildren().contains(musicSelector)) { searchSelectionBox.getChildren().add(musicSelector); TransitionUtil.createInFader(musicSelector).play(); } } private void hideMusicOptions(final Pane searchSelectionBox) { if(musicSelector == null) { return; } final FadeTransition inFader = TransitionUtil.createOutFader(musicSelector); inFader.setOnFinished(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { final boolean remove = searchSelectionBox.getChildren().remove(musicSelector); musicSelector = null; playbackSelection = null; } }); inFader.play(); } private void scroll(final int width) { if(index == serviceBoxes.size() - 1 && width < 0) { return; } if(index == 0 && width > 0) { return; } scrollTransition.setByX(width); transitionQueue.addTransition(scrollTransition); transitionQueue.play(); ServiceNameBox oldSelection = serviceBoxes.get(index); oldSelection.deselect(); if(width > 0) { index--; } else { index++; } ServiceNameBox newSelection = serviceBoxes.get(index); newSelection.select(); } private void createServiceNameBox(String label, Service service) { ServiceNameBox serviceBox = new ServiceNameBox(label, service); scroller.getChildren().add(serviceBox); serviceBoxes.add(serviceBox); serviceBoxesByService.put(service, serviceBox); } }