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

com.guigarage.extreme.ExtremeMenuButtonSkin Maven / Gradle / Ivy

The newest version!
package com.guigarage.extreme;

import com.guigarage.css.CssHelper;
import com.guigarage.css.SkinPropertyBasedCssMetaData;
import com.guigarage.ui.UiUtilities;
import com.sun.javafx.css.converters.PaintConverter;
import com.sun.javafx.scene.control.behavior.ButtonBehavior;
import com.sun.javafx.scene.control.skin.LabeledSkinBase;
import javafx.animation.ParallelTransition;
import javafx.animation.ScaleTransition;
import javafx.animation.Transition;
import javafx.css.CssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleableObjectProperty;
import javafx.scene.control.Control;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.util.Duration;

import java.util.List;

public class ExtremeMenuButtonSkin extends LabeledSkinBase> {

    private Circle buttonCircle;
    private Circle springCircle;
    private Rectangle textRectangle;
    private Text label;
    private Text iconText;
    private double textInsets = 4;
    private double gap = 6;
    private StyleableObjectProperty backgroundFill;


    public ExtremeMenuButtonSkin(ExtremeMenuButton button) {
        this(button, Duration.millis(320));
    }

    public ExtremeMenuButtonSkin(ExtremeMenuButton button, Duration animationDuration) {
        super(button, new ButtonBehavior(button));
        getChildren().clear();

        getSkinnable().setMinHeight(Region.USE_PREF_SIZE);
        getSkinnable().setMinWidth(Region.USE_PREF_SIZE);
        getSkinnable().setMaxHeight(Region.USE_PREF_SIZE);
        getSkinnable().setMaxWidth(Region.USE_PREF_SIZE);

        buttonCircle = new Circle();
        springCircle = new Circle();
        springCircle.radiusProperty().bind(buttonCircle.radiusProperty());
        springCircle.centerXProperty().bind(buttonCircle.centerXProperty());
        springCircle.centerYProperty().bind(buttonCircle.centerYProperty());
        springCircle.fillProperty().bind(buttonCircle.fillProperty());
        springCircle.setVisible(false);

        ScaleTransition springCirlceScale = new ScaleTransition(animationDuration, springCircle);
        springCirlceScale.setFromX(1.0);
        springCirlceScale.setToX(2.0);
        springCirlceScale.setFromY(1.0);
        springCirlceScale.setToY(2.0);
        Transition springCirlceOpacity = new Transition() {

            {
                setCycleDuration(animationDuration);
            }

            @Override
            protected void interpolate(double frac) {
                springCircle.setOpacity(0.7 - frac * 0.7);
            }
        };
        ParallelTransition springCircleTransition = new ParallelTransition(springCirlceScale, springCirlceOpacity);
        springCircleTransition.setOnFinished((e) -> springCircle.setVisible(false));


        getSkinnable().pressedProperty().addListener((e) -> {
            if (getSkinnable().isPressed()) {
                springCircle.toFront();
                springCircle.setOpacity(0.7);
                springCircle.setVisible(true);
                springCircleTransition.playFromStart();
            }
        });


        textRectangle = new Rectangle();
        label = new Text();
        iconText = UiUtilities.createIconText(getSkinnable().iconProperty().get(), 64);
        iconText.textProperty().bind(getSkinnable().iconProperty().asString());
        iconText.setFill(Color.WHITE);
        iconText.setOpacity(0.8);

        textRectangle.setFill(((Color) getBackgroundFill()).brighter());
        textRectangle.visibleProperty().bind(getSkinnable().hoverProperty());

        label.textProperty().bind(button.textProperty());
        label.setFill(Color.WHITE);
        label.setTextAlignment(TextAlignment.CENTER);
        label.visibleProperty().bind(getSkinnable().hoverProperty());
        getChildren().addAll(buttonCircle, textRectangle, label, iconText, springCircle);
        iconText.toFront();

        getSkinnable().hoverProperty().addListener((e) -> updateColors());
        backgroundFillProperty().addListener((e) -> updateColors());
        updateColors();

        button.fontSizePropertyProperty().addListener(e -> {
            label.setFont(UiUtilities.create(label.getFont(), button.getFontSize()));
            iconText.setFont(UiUtilities.create(iconText.getFont(), button.getFontSize() * 4));
        });
    }

    public static List> getClassCssMetaData() {
        return StyleableProperties.STYLEABLES;
    }

    private void updateColors() {
        Color c = (Color) getBackgroundFill();
        textRectangle.setFill(c.deriveColor(1.0, 1.0, 1.0, 0.4));
        if (getSkinnable().isHover()) {
            buttonCircle.setFill(c);
            textRectangle.setFill(c.deriveColor(1.0, 1.0, 1.0, 0.4));
        } else {
            buttonCircle.setFill(c.deriveColor(1.0, 1.0, 1.0, 0.4));
            textRectangle.setFill(c.deriveColor(1.0, 1.0, 1.0, 0.1));
        }
    }

    public Paint getBackgroundFill() {
        return backgroundFill == null ? Color.RED : backgroundFill.get();
    }

    public void setBackgroundFill(Paint backgroundFill) {
        this.backgroundFill.set(backgroundFill);
    }

    public StyleableObjectProperty backgroundFillProperty() {
        if (backgroundFill == null) {
            backgroundFill = CssHelper.createProperty(StyleableProperties.BACKGROUND_FILL, this);
        }
        return backgroundFill;
    }

    @Override
    protected void layoutChildren(double x, double y, double w, double h) {
        super.layoutChildren(x, y, w, h);
        textRectangle.setHeight(label.getLayoutBounds().getHeight() + textInsets * 2);
        textRectangle.setWidth(w);
        textRectangle.relocate(x, h - textRectangle.getHeight());
        buttonCircle.setRadius(textRectangle.getWidth() / 2);
        buttonCircle.setCenterX(x + w / 2);
        buttonCircle.setCenterY(y + w / 2);

        iconText.relocate((x + w / 2) - iconText.getLayoutBounds().getWidth() / 2, (y + buttonCircle.getRadius()) - iconText.getLayoutBounds().getHeight() / 2);

        label.relocate(x + (w - label.getLayoutBounds().getWidth()) / 2, h - textRectangle.getHeight() + textInsets);
    }

    @Override
    protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
        double circleWidth = computePrefWidth(0, topInset, rightInset, bottomInset, leftInset);

        return (label.getLayoutBounds().getHeight() + textInsets * 2) + gap + circleWidth + topInset + bottomInset;
    }

    @Override
    protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
        return Math.max(label.getLayoutBounds().getWidth(), label.getLayoutBounds().getHeight() * 6) + textInsets * 2 + rightInset + leftInset;
    }

    @Override
    public List> getCssMetaData() {
        return getClassCssMetaData();    //To change body of overridden methods use File | Settings | File Templates.
    }

    private static class StyleableProperties {
        private static final SkinPropertyBasedCssMetaData BACKGROUND_FILL = CssHelper.createSkinMetaData("-fx-background-fill", PaintConverter.getInstance(), "backgroundFill", Color.RED);
        private static final List> STYLEABLES = CssHelper.createCssMetaDataList(Control.getClassCssMetaData(), BACKGROUND_FILL);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy