package com.twasyl.slideshowfx.controls; import com.twasyl.slideshowfx.utils.ResourceHelper; import de.jensd.fx.glyphs.GlyphIcon; import javafx.animation.TranslateTransition; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import javafx.util.Duration; /** * This pane is used to display icons. If an icon is triggered, the content associated to this this icon is displayed * by translating in the scene. * * @author Thierry Wasylczenko * @version 1.0 * @since SlideshowFX 1.0 */ public class CollapsibleToolPane extends Region { private final ObjectProperty<Region> content = new SimpleObjectProperty<>(); private final ReadOnlyBooleanProperty collapsed = new SimpleBooleanProperty(true); private final VBox toolbar = new VBox(5); private final ToggleGroup iconsGroup = new ToggleGroup(); public CollapsibleToolPane() { this.getStylesheets().add(ResourceHelper.getExternalForm("/com/twasyl/slideshowfx/css/collapsible-tool-pane.css")); /* Ensure that when the scene is shown, the panel is placed completely * on the right of the screen, only displaying the toolbar */ this.sceneProperty().addListener((sceneValue, oldScene, newScene) -> { if(newScene != null) { newScene.widthProperty().addListener((widthValue, oldValue, newWidth) -> { if (newWidth != null) { this.setTranslateX(newWidth.doubleValue() - this.toolbar.getWidth()); } }); } }); this.toolbar.setLayoutX(0); this.toolbar.setLayoutY(0); // Ensure the content is always next to the toolbar this.content.addListener((value, oldContent, newContent) -> { if(oldContent != null) { this.getChildren().remove(oldContent); } if(newContent != null) { newContent.layoutXProperty().bind(this.toolbar.widthProperty()); newContent.setLayoutY(0); this.getChildren().add(newContent); this.layout(); } }); this.getChildren().add(this.toolbar); } /** * Indicates if this panel is collapse or not. * @return The property indicating if this panel is collapsed. */ public ReadOnlyBooleanProperty collapsedProperty() { return collapsed; } /** * Indicates if this panel is collapse or not. * @return <code>true</code> if this panel is collapsed, <code>false</code> otherwise. */ public boolean isCollapsed() { return collapsed.get(); } /** * Adds an icon associated to its content to this panel. * @param icon The icon that will always be visible in the toolbar. * @param content The content that will be displayed when the icon is triggered. * @return Return this panel. */ public CollapsibleToolPane addContent(final GlyphIcon icon, final Region content) { final ToggleButton button = new ToggleButton(); button.setToggleGroup(this.iconsGroup); button.setGraphic(icon); button.setOnAction(event -> { // If the panel is already opened, close it and only open it if the current content is different of the given content if(!this.isCollapsed()) { final TranslateTransition translation = new TranslateTransition(Duration.millis(500), this); translation.setByX(this.content.get().getWidth()); translation.setOnFinished(animationEvent -> { ((SimpleBooleanProperty) this.collapsedProperty()).set(true); // Reopen the panel if this content is different from the given one if(this.content.get() != content) { this.content.set(content); final TranslateTransition internalTranslation = new TranslateTransition(Duration.millis(500), this); internalTranslation.setByX(-this.content.get().getWidth()); internalTranslation.setOnFinished(internalAnimationEvent -> { ((SimpleBooleanProperty) this.collapsedProperty()).set(false); }); internalTranslation.play(); } }); translation.play(); } else { this.content.set(content); final TranslateTransition translation = new TranslateTransition(Duration.millis(500), this); translation.setByX(-this.content.get().getWidth()); translation.setOnFinished(animationEvent -> { ((SimpleBooleanProperty) this.collapsedProperty()).set(false); }); translation.play(); } }); this.toolbar.getChildren().add(button); return this; } }