All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jfoenix.controls.JFXTogglePane Maven / Gradle / Ivy

There is a newer version: 9.0.10
Show 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);
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy