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

io.github.palexdev.mfxcomponents.skins.MFXButtonSkin Maven / Gradle / Ivy

There is a newer version: 11.26.8
Show newest version
/*
 * Copyright (C) 2022 Parisi Alessandro - [email protected]
 * This file is part of MaterialFX (https://github.com/palexdev/MaterialFX)
 *
 * MaterialFX is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 3 of the License,
 * or (at your option) any later version.
 *
 * MaterialFX is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with MaterialFX. If not, see .
 */

package io.github.palexdev.mfxcomponents.skins;

import io.github.palexdev.mfxcomponents.behaviors.MFXButtonBehaviorBase;
import io.github.palexdev.mfxcomponents.controls.MaterialSurface;
import io.github.palexdev.mfxcomponents.controls.base.MFXButtonBase;
import io.github.palexdev.mfxcomponents.controls.buttons.MFXButton;
import io.github.palexdev.mfxcomponents.skins.base.MFXLabeledSkin;
import io.github.palexdev.mfxcomponents.theming.enums.PseudoClasses;
import io.github.palexdev.mfxcore.utils.fx.LayoutUtils;
import io.github.palexdev.mfxeffects.ripple.MFXRippleGenerator;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ContentDisplay;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;

import static io.github.palexdev.mfxcore.events.WhenEvent.intercept;
import static io.github.palexdev.mfxcore.observables.When.onChanged;

/**
 * Base skin implementation for all components of type {@link MFXButtonBase}.
 * 

* This skin uses behaviors of type {@link MFXButtonBehaviorBase}. *

* The layout is simple, there are just the label to show the text and the {@link MaterialSurface} responsible for * showing the various interaction states (applying an overlay background) and generating ripple effects. */ public class MFXButtonSkin, B extends MFXButtonBehaviorBase> extends MFXLabeledSkin { //================================================================================ // Properties //================================================================================ protected final MaterialSurface surface; // Specs protected static double MIN_HEIGHT = 40.0; //================================================================================ // Constructors //================================================================================ public MFXButtonSkin(T button) { super(button); initTextMeasurementCache(); // Init surface surface = new MaterialSurface(button) .initRipple(rg -> rg.setRippleColor(Color.web("#d7d1e7"))); // Finalize init getChildren().addAll(surface, label); addListeners(); } //================================================================================ // Methods //================================================================================ /** * Adds the following listeners: *

- A listener on the {@link MFXButton#contentDisplayProperty()} to activate/disable the pseudo classes * {@link PseudoClasses#WITH_ICON_LEFT} and {@link PseudoClasses#WITH_ICON_RIGHT} accordingly */ protected void addListeners() { T button = getSkinnable(); listeners( onChanged(button.contentDisplayProperty()) .then((o, n) -> { Node graphic = button.getGraphic(); boolean wil = (graphic != null) && (n == ContentDisplay.LEFT); boolean wir = (graphic != null) && (n == ContentDisplay.RIGHT); PseudoClasses.WITH_ICON_LEFT.setOn(button, wil); PseudoClasses.WITH_ICON_RIGHT.setOn(button, wir); }) .executeNow() .invalidating(button.graphicProperty()) ); } //================================================================================ // Overridden Methods //================================================================================ /** * Initializes the given {@link MFXButtonBehaviorBase} to handle events such as: {@link MouseEvent#MOUSE_PRESSED}, * {@link MouseEvent#MOUSE_RELEASED}, {@link MouseEvent#MOUSE_CLICKED}, {@link MouseEvent#MOUSE_EXITED} and * {@link KeyEvent#KEY_PRESSED}. */ @Override protected void initBehavior(B behavior) { T button = getSkinnable(); MFXRippleGenerator rg = surface.getRippleGenerator(); behavior.init(); events( intercept(button, MouseEvent.MOUSE_PRESSED) .process(e -> behavior.mousePressed(e, c -> rg.generate(e))), intercept(button, MouseEvent.MOUSE_RELEASED) .process(e -> behavior.mouseReleased(e, c -> rg.release())), intercept(button, MouseEvent.MOUSE_CLICKED) .process(behavior::mouseClicked), intercept(button, MouseEvent.MOUSE_EXITED) .process(e -> behavior.mouseExited(e, c -> rg.release())), intercept(button, KeyEvent.KEY_PRESSED) .process(e -> behavior.keyPressed(e, c -> { if (e.getCode() == KeyCode.ENTER) { Bounds b = button.getLayoutBounds(); rg.generate(b.getCenterX(), b.getCenterY()); rg.release(); } })) ); } @Override public double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { return Math.max(MIN_HEIGHT, super.computeMinHeight(width, topInset, rightInset, bottomInset, leftInset)); } @Override public double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { T button = getSkinnable(); double insets = leftInset + rightInset; double tW = getCachedTextWidth(); if (button.getContentDisplay() == ContentDisplay.GRAPHIC_ONLY) tW = 0; double gW = (button.getGraphic() != null) ? LayoutUtils.boundWidth(button.getGraphic()) + button.getGraphicTextGap() : 0.0; return insets + tW + gW; } @Override public double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { T button = getSkinnable(); double insets = topInset + bottomInset; double tH = getCachedTextHeight(); double gH = button.getGraphic() != null ? LayoutUtils.boundHeight(button.getGraphic()) : 0.0; return insets + Math.max(tH, gH); } @Override public double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { return getSkinnable().prefWidth(height); } @Override public double computeMaxHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { return getSkinnable().prefHeight(width); } @Override protected void layoutChildren(double x, double y, double w, double h) { T button = getSkinnable(); Pos pos = button.getAlignment(); layoutInArea(label, x, y, w, h, 0, pos.getHpos(), pos.getVpos()); surface.resizeRelocate(0, 0, button.getWidth(), button.getHeight()); } @Override public void dispose() { surface.dispose(); super.dispose(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy