org.fxyz3d.ExtrasAndTests.AbstractPopoutClient Maven / Gradle / Ivy
The newest version!
/**
* AbstractPopoutClient.java
*
* Copyright (c) 2013-2016, F(X)yz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of F(X)yz, any associated website, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.fxyz3d.ExtrasAndTests;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* @author Jason Pollastrini aka jdub1581
*/
public abstract class AbstractPopoutClient extends AnchorPane {
@FXML
protected StackPane topPane;
@FXML
protected StackPane menuPane;
@FXML
protected HBox centerPane;
@FXML
protected StackPane center;
@FXML
protected StackPane right;
@FXML
protected StackPane bottomPane;
@FXML
protected Pane menuPaneTrigger;
@FXML
protected Pane bottomPaneTrigger;
@FXML
protected Pane topPaneTrigger;
protected Stage stage;
private AbstractPopoutClient() {
try {
FXMLLoader ldr = getUILoader();
ldr.setController(this);
ldr.setRoot(this);
ldr.load();
} catch (IOException ex) {
Logger.getLogger(SimpleSamplerClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
public AbstractPopoutClient(Stage stage, boolean popsEnabled) {
this();
if (popsEnabled) {
initialize();
}
this.stage = stage;
}
private void initialize() {
menuPaneLocation.addListener(it -> updateMenuPaneAnchors());
bottomPaneLocation.addListener(it -> updateBottomPaneAnchors());
showMenuPaneProperty().addListener(it -> animateMenuPane());
showBottomPaneProperty().addListener(it -> animateBottomPane());
menuPane.setOnMouseExited(evt -> {
if (menuPane.getOpacity() == 1) {
setShowMenuPane(false);
menuPaneTrigger.toFront();
menuPaneTrigger.setVisible(true);
}
});
menuPaneTrigger.setOnMouseEntered(e -> {
if (menuPane.getOpacity() != 1) {
setShowMenuPane(true);
menuPaneTrigger.toBack();
menuPaneTrigger.setVisible(false);
}
});
bottomPaneTrigger.setOnMouseEntered(e -> {
if (bottomPane.getOpacity() != 1) {
setShowBottomPane(true);
bottomPaneTrigger.toBack();
bottomPaneTrigger.setVisible(false);
}
});
bottomPane.setOnMouseClicked(evt -> {
if (bottomPane.getOpacity() == 1) {
setShowBottomPane(false);
bottomPaneTrigger.toFront();
bottomPaneTrigger.setVisible(true);
}
});
}
private final BooleanProperty showMenuPane = new SimpleBooleanProperty(this, "showMenuPane", true);
public final boolean isShowMenuPane() {
return showMenuPane.get();
}
public final void setShowMenuPane(boolean showMenu) {
showMenuPane.set(showMenu);
}
/**
* Returns the property used to control the visibility of the menu panel.
* When the value of this property changes to false then the menu panel will
* slide out to the left).
*
* @return the property used to control the menu panel
*/
public final BooleanProperty showMenuPaneProperty() {
return showMenuPane;
}
private final BooleanProperty showBottomPane = new SimpleBooleanProperty(this, "showBottomPane", true);
public final boolean isShowBottomPane() {
return showBottomPane.get();
}
public final void setShowBottomPane(boolean showBottom) {
showBottomPane.set(showBottom);
}
/**
* Returns the property used to control the visibility of the bottom panel.
* When the value of this property changes to false then the bottom panel
* will slide out to the left).
*
* @return the property used to control the bottom panel
*/
public final BooleanProperty showBottomPaneProperty() {
return showBottomPane;
}
/*
* The updateMenu/BottomPaneAnchors methods get called whenever the value of
* menuPaneLocation or bottomPaneLocation changes. Setting anchor pane
* constraints will automatically trigger a relayout of the anchor pane
* children.
*/
private void updateMenuPaneAnchors() {
setLeftAnchor(menuPane, getMenuPaneLocation());
setLeftAnchor(centerPane, getMenuPaneLocation() + menuPane.getWidth());
}
private void updateBottomPaneAnchors() {
setBottomAnchor(bottomPane, getBottomPaneLocation());
setBottomAnchor(centerPane,
getBottomPaneLocation() + bottomPane.getHeight());
setBottomAnchor(menuPane,
getBottomPaneLocation() + bottomPane.getHeight());
}
/*
* Starts the animation for the menu pane.
*/
private void animateMenuPane() {
if (isShowMenuPane()) {
slideMenuPane(0);
} else {
slideMenuPane(-menuPane.prefWidth(-1));
}
}
/*
* Starts the animation for the bottom pane.
*/
private void animateBottomPane() {
if (isShowBottomPane()) {
slideBottomPane(0);
} else {
slideBottomPane(-bottomPane.prefHeight(-1));
}
}
/*
* The animations are using the JavaFX timeline concept. The timeline updates
* properties. In this case we have to introduce our own properties further
* below (menuPaneLocation, bottomPaneLocation) because ultimately we need to
* update layout constraints, which are not properties. So this is a little
* work-around.
*/
private void slideMenuPane(double toX) {
KeyValue keyValue = new KeyValue(menuPaneLocation, toX, Interpolator.EASE_BOTH);
KeyValue visible = new KeyValue(menuPane.opacityProperty(), menuPane.getOpacity() == 1 ? 0 : 1);
KeyFrame keyFrame = new KeyFrame(Duration.millis(600), keyValue, visible);
Timeline timeline = new Timeline(keyFrame);
timeline.play();
}
private void slideBottomPane(double toY) {
KeyValue keyValue = new KeyValue(bottomPaneLocation, toY, Interpolator.EASE_BOTH);
KeyValue visible = new KeyValue(bottomPane.opacityProperty(), bottomPane.getOpacity() == 1 ? 0 : 1);
KeyFrame keyFrame = new KeyFrame(Duration.millis(600), keyValue, visible);
Timeline timeline = new Timeline(keyFrame);
timeline.play();
}
private DoubleProperty menuPaneLocation = new SimpleDoubleProperty(this, "menuPaneLocation");
private double getMenuPaneLocation() {
return menuPaneLocation.get();
}
private DoubleProperty bottomPaneLocation = new SimpleDoubleProperty(this, "bottomPaneLocation");
private double getBottomPaneLocation() {
return bottomPaneLocation.get();
}
protected String getFXMLPath() {
return "Client_Slide_Outs.fxml";
}
private FXMLLoader getUILoader() {
return new FXMLLoader(getClass().getResource(getFXMLPath()));
}
public StackPane getTopPane() {
return topPane;
}
public StackPane getMenuPane() {
return menuPane;
}
public StackPane getCenter() {
return center;
}
public StackPane getRight() {
return right;
}
public StackPane getBottomPane() {
return bottomPane;
}
public Pane getBottomPaneTrigger() {
return bottomPaneTrigger;
}
}