com.jfoenix.controls.JFXTogglePane Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.jfoenix.controls;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
/**
* @author Shadi Shaheen toggle pane is a hidden pane that is shown upon mouse click on its toggle
* node NOTE : the toggle animation is specified by the pane clipping shape TODO :
* reimplement, currently not used
*/
public class JFXTogglePane extends StackPane
{
private Timeline toggleAnimation = null;
private ObjectProperty toggleNode = new SimpleObjectProperty<>();
private ObjectProperty contentNode = new SimpleObjectProperty<>();
/*
* the scaling factor controls area of the clipping node when toggeling the pane
*/
private DoubleProperty scalingFactor = new SimpleDoubleProperty(2.4);
public JFXTogglePane()
{
this.clipProperty().addListener((o, oldVal, newVal) ->
{
if (newVal != null)
{
if (getToggleNode() != null)
{
Region toggleNode = getToggleNode();
newVal.layoutXProperty()
.bind(Bindings.createDoubleBinding(() -> toggleNode.getLayoutX() + toggleNode.getWidth() / 2,
toggleNode.widthProperty(),
toggleNode.layoutXProperty()));
newVal.layoutYProperty()
.bind(Bindings.createDoubleBinding(() -> toggleNode.getLayoutY() + toggleNode.getHeight() / 2,
toggleNode.heightProperty(),
toggleNode.layoutYProperty()));
}
}
});
this.widthProperty().addListener((o, oldVal, newVal) -> updateToggleAnimation());
this.heightProperty().addListener((o, oldVal, newVal) -> updateToggleAnimation());
toggleNode.addListener((o, oldVal, newVal) ->
{
if (newVal != null)
{
if (getClip() != null)
{
getClip().layoutXProperty().unbind();
getClip().layoutYProperty().unbind();
getClip().layoutXProperty()
.bind(Bindings.createDoubleBinding(() -> newVal.getLayoutX() + newVal.getWidth() / 2,
newVal.widthProperty(),
newVal.layoutXProperty()));
getClip().layoutYProperty()
.bind(Bindings.createDoubleBinding(() -> newVal.getLayoutY() + newVal.getHeight() / 2,
newVal.heightProperty(),
newVal.layoutYProperty()));
}
}
updateToggleAnimation();
newVal.widthProperty().addListener((o1, oldVal1, newVal1) -> updateToggleAnimation());
newVal.heightProperty().addListener((o1, oldVal1, newVal1) -> updateToggleAnimation());
newVal.setOnMouseClicked((click) -> togglePane());
});
}
public void togglePane()
{
if (toggleAnimation == null)
{
updateToggleAnimation();
}
this.getClip().scaleXProperty().unbind();
this.getClip().scaleYProperty().unbind();
toggleAnimation.setRate(toggleAnimation.getRate() * -1);
if (toggleAnimation.getCurrentTime().equals(Duration.millis(0)) && toggleAnimation.getRate() == -1)
{
toggleAnimation.playFrom(Duration.millis(510));
}
else
{
toggleAnimation.play();
}
}
private void updateToggleAnimation()
{
if (getContentNode() == null)
{
return;
}
double rateX = this.getWidth() / getClip().getLayoutBounds().getWidth();
double rateY = this.getHeight() / getClip().getLayoutBounds().getHeight();
double newRate = Math.max(rateX, rateY) * getScalingFactor();
double animationRate = toggleAnimation == null ? -1 : toggleAnimation.getRate();
toggleAnimation = new Timeline(new KeyFrame(Duration.millis(0), new KeyValue(getClip().scaleXProperty(), 1, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.millis(0), new KeyValue(getClip().scaleYProperty(), 1, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.millis(0), new KeyValue(getContentNode().opacityProperty(), 0, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.millis(350), new KeyValue(getClip().scaleXProperty(), newRate, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.millis(350), new KeyValue(getClip().scaleYProperty(), newRate, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.millis(370), new KeyValue(getContentNode().opacityProperty(), 0, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.millis(510), new KeyValue(getContentNode().opacityProperty(), 1, Interpolator.EASE_BOTH)));
toggleAnimation.setOnFinished((finish) ->
{
if (toggleAnimation.getRate() == 1)
{
this.getClip().scaleXProperty().bind(Bindings.createDoubleBinding(() ->
{
double X = this.getWidth() / getClip().getLayoutBounds().getWidth();
double Y = this.getHeight() / getClip().getLayoutBounds().getHeight();
return Math.max(X, Y) * getScalingFactor();
}, this.widthProperty(), this.heightProperty()));
this.getClip().scaleYProperty().bind(Bindings.createDoubleBinding(() ->
{
double X = this.getWidth() / getClip().getLayoutBounds().getWidth();
double Y = this.getHeight() / getClip().getLayoutBounds().getHeight();
return Math.max(X, Y) * getScalingFactor();
}, this.widthProperty(), this.heightProperty()));
}
});
toggleAnimation.setRate(animationRate);
}
/***************************************************************************
* * Public Properties * *
**************************************************************************/
public final ObjectProperty toggleNodeProperty()
{
return this.toggleNode;
}
public final Control getToggleNode()
{
return this.toggleNodeProperty().get();
}
public final void setToggleNode(final Control toggleNode)
{
this.toggleNodeProperty().set(toggleNode);
}
public final ObjectProperty contentNodeProperty()
{
return this.contentNode;
}
public final Node getContentNode()
{
return this.contentNodeProperty().get();
}
public final void setContentNode(final Node content)
{
this.contentNodeProperty().set(content);
content.setOpacity(0);
}
public final DoubleProperty scalingFactorProperty()
{
return this.scalingFactor;
}
public final double getScalingFactor()
{
return this.scalingFactorProperty().get();
}
public final void setScalingFactor(final double scalingFactor)
{
this.scalingFactorProperty().set(scalingFactor);
}
}