Skip to content

Instantly share code, notes, and snippets.

@tserber98
Last active March 16, 2020 14:39
Show Gist options
  • Save tserber98/4b8e30b788dfb8564d1b6e1362dbfbb2 to your computer and use it in GitHub Desktop.
Save tserber98/4b8e30b788dfb8564d1b6e1362dbfbb2 to your computer and use it in GitHub Desktop.
Slider Pane implementation for JavaFX.
import javafx.animation.*;
import javafx.beans.property.*;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.util.Duration;
public class SliderPane extends Pane{
public SliderPane(){
}
public SliderPane(Node... children){
super(children);
}
private final IntegerProperty openedIndex = new SimpleIntegerProperty(0);
{
openedIndex.addListener((obs, o, n) -> openedIndexChanged(o.intValue(), n.intValue()));
}
public final int getOpenedIndex(){
return openedIndex.get();
}
public final IntegerProperty openedIndexProperty(){
return openedIndex;
}
public final void setOpenedIndex(int openedIndex){
this.openedIndex.set(openedIndex);
}
private final BooleanProperty animated = new SimpleBooleanProperty(false);
public final boolean isAnimated(){
return animated.get();
}
public final BooleanProperty animatedProperty(){
return animated;
}
public final void setAnimated(boolean animated){
this.animated.set(animated);
}
private final IntegerProperty animationTime = new SimpleIntegerProperty(1000);
public final int getAnimationTime(){
return animationTime.get();
}
public final IntegerProperty animationTimeProperty(){
return animationTime;
}
public final void setAnimationTime(int animationTime){
this.animationTime.set(animationTime);
}
private final ReadOnlyBooleanWrapper animating = new ReadOnlyBooleanWrapper(false);
public final boolean isAnimating(){
return animating.get();
}
public final ReadOnlyBooleanProperty animatingProperty(){
return animating.getReadOnlyProperty();
}
private double offsetIndex;
private Timeline timeline;
private void openedIndexChanged(int oldIndex, int newIndex){
if(isAnimated()){
if(timeline != null){
timeline.stop();
}
DoubleProperty percentProperty = new SimpleDoubleProperty(0);
timeline = new Timeline(new KeyFrame(Duration.millis(getAnimationTime()), new KeyValue(percentProperty, 1.0)));
timeline.statusProperty().addListener((obs, o, n) -> {
animating.set(n == Animation.Status.RUNNING);
});
percentProperty.addListener((obs, o, n) -> {
if(isAnimated()){
offsetIndex = Interpolator.EASE_OUT.interpolate((double)oldIndex, newIndex, n.doubleValue());
}
else{
timeline.stop();
offsetIndex = newIndex;
}
requestLayout();
});
timeline.play();
}
else{
offsetIndex = newIndex;
layoutChildren();
}
}
@Override
protected void layoutChildren(){
super.layoutChildren();
double width = getWidth();
double height = getHeight();
int i = 0;
for(Node node : getManagedChildren()){
node.resizeRelocate((width * i++) - (offsetIndex * width), 0, width, height);
}
}
}
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SliderPaneUsage extends Application{
private static final int PROJECT_LIST_INDEX = 0;
private static final int CREATE_PROJECT_INDEX = 1;
private SliderPane root;
@Override
public void start(Stage stage) throws Exception{
final ListView<String> projectsList = new ListView<>(FXCollections.observableArrayList("Project 1", "Project 2", "Project 3"));
final HBox controlsWrapper;
{
final Button createProjectButton = new Button("Create project");
createProjectButton.setOnAction((e) -> root.setOpenedIndex(CREATE_PROJECT_INDEX));
controlsWrapper = new HBox(createProjectButton);
controlsWrapper.setPadding(new Insets(4));
}
VBox projectListWrapper = new VBox(projectsList, controlsWrapper);
VBox.setVgrow(projectsList, Priority.ALWAYS);
final VBox createProjectWrapper;
{
final TextField projectNameField = new TextField();
projectNameField.setPromptText("Project name");
final Button cancelButton = new Button("Cancel");
cancelButton.setOnAction((e) -> root.setOpenedIndex(PROJECT_LIST_INDEX));
final Button createButton = new Button("Create");
createButton.setOnAction((e) -> {
projectsList.getItems().add(projectNameField.getText());
root.setOpenedIndex(PROJECT_LIST_INDEX);
});
VBox fieldsWrapper = new VBox(projectNameField);
VBox.setVgrow(fieldsWrapper, Priority.ALWAYS);
final HBox buttonsWrapper = new HBox(cancelButton, createButton);
buttonsWrapper.setSpacing(4);
buttonsWrapper.setAlignment(Pos.CENTER_RIGHT);
createProjectWrapper = new VBox(fieldsWrapper, buttonsWrapper);
}
root = new SliderPane(projectListWrapper, createProjectWrapper);
root.setAnimated(true);
root.setAnimationTime(500);
root.getChildren().forEach((node) -> node.disableProperty().bind(root.animatingProperty()));
stage.setScene(new Scene(root, 640, 480));
stage.show();
}
public static void main(String[] args){
launch(args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment