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

impl.jfxtras.styles.jmetro8.ToggleSwitchSkin Maven / Gradle / Ivy

Go to download

A theme / look and feel for JavaFX inspired (but not a copy) by Microsoft's Fluent Design

There is a newer version: 11.6.16
Show newest version
package impl.jfxtras.styles.jmetro8;

import com.sun.javafx.css.converters.EnumConverter;
import com.sun.javafx.css.converters.SizeConverter;
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.beans.property.DoubleProperty;
import javafx.css.CssMetaData;
import javafx.css.SimpleStyleableObjectProperty;
import javafx.css.Styleable;
import javafx.css.StyleableDoubleProperty;
import javafx.css.StyleableObjectProperty;
import javafx.css.StyleableProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.SkinBase;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
import org.controlsfx.control.ToggleSwitch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ToggleSwitchSkin extends SkinBase
{
    private final StackPane thumb;
    private final StackPane thumbArea;
    private final Label label;
    private final StackPane labelContainer;
    private final TranslateTransition transition;

    /**
     * Constructor for all ToggleSwitchSkin instances.
     *
     * @param control The ToggleSwitch for which this Skin should attach to.
     */
    public ToggleSwitchSkin(ToggleSwitch control) {
        super(control);

        thumb = new StackPane();
        thumbArea = new StackPane();
        label = new Label();
        labelContainer = new StackPane();
        transition = new TranslateTransition(Duration.millis(getThumbMoveAnimationTime()), thumb);
        transition.setInterpolator(Interpolator.EASE_OUT);

        label.textProperty().bind(control.textProperty());
        getChildren().addAll(labelContainer, thumbArea, thumb);
        labelContainer.getChildren().addAll(label);
        StackPane.setAlignment(label, Pos.CENTER_LEFT);

        thumb.getStyleClass().setAll("thumb");
        thumbArea.getStyleClass().setAll("thumb-area");

        thumbArea.setOnMouseReleased(event -> mousePressedOnToggleSwitch(control));
        thumb.setOnMouseReleased(event -> mousePressedOnToggleSwitch(control));
        control.selectedProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue.booleanValue() != oldValue.booleanValue())
                selectedStateChanged();
        });
    }

    private void selectedStateChanged() {
        if(transition != null){
            transition.stop();
            transition.setDuration(Duration.millis(getThumbMoveAnimationTime()));
        }

        double thumbAreaWidth = snapSize(thumbArea.prefWidth(-1));
        Insets thumbAreaPadding = thumbArea.getPadding();
        double thumbWidth = snapSize(thumb.prefWidth(-1));
        double distance = thumbAreaWidth - thumbWidth - thumbAreaPadding.getRight() - thumbAreaPadding.getLeft();

        /*
         * If we are not selected, we need to go from right to left.
         */
        if (!getSkinnable().isSelected()) {
            thumb.setLayoutX(thumbArea.getLayoutX());
            transition.setFromX(distance);
            transition.setToX(0);
        } else {
            thumb.setTranslateX(thumbArea.getLayoutX());
            transition.setFromX(0);
            transition.setToX(distance);
        }
        transition.setCycleCount(1);
        transition.play();
    }

    private void mousePressedOnToggleSwitch(ToggleSwitch toggleSwitch) {
        toggleSwitch.setSelected(!toggleSwitch.isSelected());
    }


    /**
     * How many milliseconds it should take for the thumb to go from
     * one edge to the other
     */
    private DoubleProperty thumbMoveAnimationTime = null;

    private DoubleProperty thumbMoveAnimationTimeProperty() {
        if (thumbMoveAnimationTime == null) {
            thumbMoveAnimationTime = new StyleableDoubleProperty(200) {

                @Override
                public Object getBean() {
                    return ToggleSwitchSkin.this;
                }

                @Override
                public String getName() {
                    return "thumbMoveAnimationTime";
                }

                @Override
                public CssMetaData getCssMetaData() {
                    return THUMB_MOVE_ANIMATION_TIME_META_DATA;
                }
            };
        }
        return thumbMoveAnimationTime;
    }

    private double getThumbMoveAnimationTime() {
        return thumbMoveAnimationTime == null ? 200 : thumbMoveAnimationTime.get();
    }

    private StyleableObjectProperty thumbDisplay = new SimpleStyleableObjectProperty(THUMB_DISPLAY_META_DATA, ThumbDisplay.RIGHT) {
        @Override
        protected void invalidated() {
            ToggleSwitchSkin.this.getSkinnable().requestLayout();
        }
    };

    private StyleableObjectProperty thumbDisplayProperty() { return thumbDisplay; }

    private ThumbDisplay getThumbDisplay() { return thumbDisplay.get(); }

    @Override
    protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {
        ToggleSwitch toggleSwitch = getSkinnable();
        double thumbAreaX;
        double labelX;

        double thumbWidth = thumb.prefWidth(-1);
        double thumbHeight = thumb.prefHeight(-1);
        thumb.resize(snapSize(thumbWidth), snapSize(thumbHeight));

        double labelWidth = labelContainer.prefWidth(-1);

        Insets thumbAreaPadding = thumbArea.getPadding();
        double thumbAreaWidth = thumbArea.prefWidth(-1);
        double thumbAreaHeight = thumbArea.prefHeight(-1);
        if (getThumbDisplay().equals(ThumbDisplay.RIGHT)) {
            thumbAreaX = contentWidth - thumbAreaWidth;
            labelX = contentX;
        } else if (getThumbDisplay().equals(ThumbDisplay.LEFT)) {
            thumbAreaX = contentX;
            labelX = contentWidth - labelWidth;
        } else { // ThumbDisplay.THUMB_ONLY
            thumbAreaX = contentX;
            labelX = 0;
        }
        double thumbAreaY = contentY;

        thumbArea.resize(snapSize(thumbAreaWidth), snapSize(thumbAreaHeight));

        thumbArea.setLayoutX(snapPosition(thumbAreaX));
        thumbArea.setLayoutY(snapPosition(thumbAreaY));

        if (!getThumbDisplay().equals(ThumbDisplay.THUMB_ONLY)) {
            labelContainer.resize(snapSize(contentWidth - thumbAreaWidth), snapSize(thumbAreaHeight));
            labelContainer.setLayoutY(snapPosition(thumbAreaY));
            labelContainer.setLayoutX(snapPosition(labelX));
        }

        if (!toggleSwitch.isSelected())
            thumb.setLayoutX(snapPosition(thumbAreaX + thumbAreaPadding.getLeft()));
        else
            thumb.setLayoutX(snapPosition(thumbAreaX + thumbAreaWidth - thumbAreaPadding.getRight() - thumbWidth));
        thumb.setLayoutY(snapPosition(thumbAreaY + thumbAreaPadding.getBottom()));
    }


    @Override protected double computeMinWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
        return leftInset + label.prefWidth(-1) + thumbArea.prefWidth(-1) + rightInset;
    }

    @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
        return topInset + Math.max(thumb.prefHeight(-1), label.prefHeight(-1)) + bottomInset;
    }

    @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
        return leftInset + label.prefWidth(-1) + 20 + thumbArea.prefWidth(-1) + rightInset;
    }

    @Override protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
        return topInset + Math.max(thumb.prefHeight(-1), label.prefHeight(-1)) + bottomInset;
    }

    private static final CssMetaData THUMB_MOVE_ANIMATION_TIME_META_DATA =
            new CssMetaData("-thumb-move-animation-time",
                    SizeConverter.getInstance(), 200) {

                @Override
                public boolean isSettable(ToggleSwitch toggleSwitch) {
                    final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin();
                    return skin.thumbMoveAnimationTime == null ||
                            !skin.thumbMoveAnimationTime.isBound();
                }

                @Override
                public StyleableProperty getStyleableProperty(ToggleSwitch toggleSwitch) {
                    final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin();
                    return (StyleableProperty) skin.thumbMoveAnimationTimeProperty();
                }
            };

    private static final CssMetaData THUMB_DISPLAY_META_DATA =
            new CssMetaData("-toggle-display", new EnumConverter<>(ThumbDisplay.class)) {

                @Override
                public boolean isSettable(ToggleSwitch toggleSwitch) {
                    final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin();
                    return !skin.thumbDisplay.isBound();
                }

                @Override
                public StyleableProperty getStyleableProperty(ToggleSwitch toggleSwitch) {
                    final ToggleSwitchSkin skin = (ToggleSwitchSkin) toggleSwitch.getSkin();
                    return skin.thumbDisplayProperty();
                }
            };

    private static final List> STYLEABLES;

    static {
        final List> styleables =
                new ArrayList<>(SkinBase.getClassCssMetaData());
        styleables.add(THUMB_MOVE_ANIMATION_TIME_META_DATA);
        styleables.add(THUMB_DISPLAY_META_DATA);
        STYLEABLES = Collections.unmodifiableList(styleables);
    }

    /**
     * @return The CssMetaData associated with this class, which may include the
     * CssMetaData of its super classes.
     */
    public static List> getClassCssMetaData() {
        return STYLEABLES;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List> getCssMetaData() {
        return getClassCssMetaData();
    }

    private enum ThumbDisplay {
        LEFT, RIGHT, THUMB_ONLY
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy