io.github.palexdev.mfxeffects.animations.TransitionPane Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of materialfx-all Show documentation
Show all versions of materialfx-all Show documentation
Material Design/Modern components for JavaFX, now packed as a single Jar
/*
* Copyright (C) 2023 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.mfxeffects.animations;
import io.github.palexdev.mfxeffects.animations.base.ITransitionType;
import io.github.palexdev.mfxeffects.beans.Position;
import io.github.palexdev.mfxeffects.beans.Size;
import io.github.palexdev.mfxeffects.utils.LayoutUtils;
import io.github.palexdev.mfxeffects.utils.TriFunction;
import javafx.animation.Animation;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import javafx.scene.layout.StackPane;
import java.util.function.Supplier;
public class TransitionPane extends StackPane {
//================================================================================
// Properties
//================================================================================
private final String STYLE_CLASS = "transition-pane";
public static final PseudoClass CLOSED_PSEUDO_CLASS = PseudoClass.getPseudoClass("closed");
public static final PseudoClass OPEN_PSEUDO_CLASS = PseudoClass.getPseudoClass("open");
private final ObjectProperty closedNode = new SimpleObjectProperty<>() {
@Override
public void set(Node newValue) {
Node oldValue = get();
if (oldValue != null)
TransitionPane.super.getChildren().remove(oldValue);
if (newValue != null)
TransitionPane.super.getChildren().add(newValue);
super.set(newValue);
}
};
private final ObjectProperty openNode = new SimpleObjectProperty<>() {
@Override
public void set(Node newValue) {
Node oldValue = get();
if (oldValue != null)
TransitionPane.super.getChildren().remove(oldValue);
if (newValue != null) {
TransitionPane.super.getChildren().add(newValue);
newValue.setManaged(false);
newValue.setVisible(false);
newValue.setOpacity(0.0);
}
super.set(newValue);
}
};
private final ReadOnlyBooleanWrapper open = new ReadOnlyBooleanWrapper(false);
private final ObjectProperty> targetSize = new SimpleObjectProperty<>() {
@Override
protected void invalidated() {
cachedClosedSize = null;
cachedOpenSize = null;
}
};
private final ObjectProperty> targetOffset = new SimpleObjectProperty<>(Position::origin);
private Size cachedClosedSize;
private Size cachedOpenSize;
private final ObjectProperty> closeAnimationFactory = new SimpleObjectProperty<>();
private final ObjectProperty> openAnimationFactory = new SimpleObjectProperty<>();
private Animation cachedCloseAnimation;
private Animation cachedOpenAnimation;
//================================================================================
// Constructors
//================================================================================
public TransitionPane() {
this(null, null);
}
public TransitionPane(Node closedNode, Node openNode) {
setClosedNode(closedNode);
setOpenNode(openNode);
initialize();
}
//================================================================================
// Methods
//================================================================================
private void initialize() {
getStyleClass().add(STYLE_CLASS);
pseudoClassStateChanged(CLOSED_PSEUDO_CLASS, true);
setTargetSize(() -> {
Node node = getOpenNode();
if (node == null) return Size.invalid();
return Size.of(
LayoutUtils.boundWidth(node),
LayoutUtils.boundHeight(node)
);
});
setMinSize(USE_PREF_SIZE, USE_PREF_SIZE);
setMaxSize(USE_PREF_SIZE, USE_PREF_SIZE);
}
public void open() {
if (isOpen()) return;
Node openNode = getOpenNode();
Size size = getOpenSize();
if (openNode == null || Size.invalid().equals(size)) return;
setOpen(true);
if (cachedOpenAnimation == null)
cachedOpenAnimation = getOpenAnimationFactory().apply(this, openNode, getClosedNode());
if (cachedCloseAnimation != null) cachedCloseAnimation.stop();
cachedOpenAnimation.playFromStart();
}
public void close() {
if (!isOpen()) return;
Node closedNode = getClosedNode();
if (closedNode == null) return;
getClosedSize();
setOpen(false);
if (cachedCloseAnimation == null)
cachedCloseAnimation = getCloseAnimationFactory().apply(this, getOpenNode(), closedNode);
if (cachedOpenAnimation != null) cachedOpenAnimation.stop();
cachedCloseAnimation.playFromStart();
}
public void setAnimationType(ITransitionType type) {
setOpenAnimationFactory(type::open);
setCloseAnimationFactory(type::close);
}
public Size getOpenSize() {
if (cachedOpenSize == null || Size.invalid().equals(cachedOpenSize)) {
cachedOpenSize = getTargetSize().get();
}
return cachedOpenSize;
}
public Size getClosedSize() {
if (cachedClosedSize == null || Size.invalid().equals(cachedClosedSize)) {
Node closedNode = getClosedNode();
cachedClosedSize = (closedNode != null) ?
Size.of(
LayoutUtils.boundWidth(closedNode),
LayoutUtils.boundHeight(closedNode)
) :
Size.invalid();
}
return cachedClosedSize;
}
//================================================================================
// Overridden Methods
//================================================================================
@Override
public ObservableList getChildren() {
return getChildrenUnmodifiable();
}
@Override
protected void layoutChildren() {
super.layoutChildren();
Node node = getOpenNode();
if (node == null) return;
node.resizeRelocate(0, 0, getWidth(), getHeight());
}
//================================================================================
// Getters/Setters
//================================================================================
public Node getClosedNode() {
return closedNode.get();
}
public ObjectProperty closedNodeProperty() {
return closedNode;
}
public void setClosedNode(Node closedNode) {
this.closedNode.set(closedNode);
}
public Node getOpenNode() {
return openNode.get();
}
public ObjectProperty openNodeProperty() {
return openNode;
}
public void setOpenNode(Node openNode) {
this.openNode.set(openNode);
}
public boolean isOpen() {
return open.get();
}
public ReadOnlyBooleanProperty openProperty() {
return open.getReadOnlyProperty();
}
protected void setOpen(boolean open) {
this.open.set(open);
pseudoClassStateChanged(CLOSED_PSEUDO_CLASS, !open);
pseudoClassStateChanged(OPEN_PSEUDO_CLASS, open);
}
public Supplier getTargetSize() {
return targetSize.get();
}
public ObjectProperty> targetSizeProperty() {
return targetSize;
}
public void setTargetSize(Supplier targetSize) {
this.targetSize.set(targetSize);
}
public Supplier getTargetOffset() {
return targetOffset.get();
}
public ObjectProperty> targetOffsetProperty() {
return targetOffset;
}
public void setTargetOffset(Supplier targetOffset) {
this.targetOffset.set(targetOffset);
}
public TriFunction getCloseAnimationFactory() {
return closeAnimationFactory.get();
}
public ObjectProperty> closeAnimationFactoryProperty() {
return closeAnimationFactory;
}
public void setCloseAnimationFactory(TriFunction closeAnimationFactory) {
this.closeAnimationFactory.set(closeAnimationFactory);
}
public TriFunction getOpenAnimationFactory() {
return openAnimationFactory.get();
}
public ObjectProperty> openAnimationFactoryProperty() {
return openAnimationFactory;
}
public void setOpenAnimationFactory(TriFunction openAnimationFactory) {
this.openAnimationFactory.set(openAnimationFactory);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy