io.github.palexdev.mfxcomponents.controls.progress.MFXProgressIndicator 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) 2024 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.controls.progress;
import io.github.palexdev.mfxcomponents.controls.base.MFXControl;
import io.github.palexdev.mfxcomponents.controls.base.MFXSkinBase;
import io.github.palexdev.mfxcomponents.skins.MFXCircularProgressIndicatorSkin;
import io.github.palexdev.mfxcomponents.skins.MFXLinearProgressIndicatorSkin;
import io.github.palexdev.mfxcore.base.properties.styleable.StyleableBooleanProperty;
import io.github.palexdev.mfxcore.base.properties.styleable.StyleableDoubleProperty;
import io.github.palexdev.mfxcore.base.properties.styleable.StyleableObjectProperty;
import io.github.palexdev.mfxcore.behavior.BehaviorBase;
import io.github.palexdev.mfxcore.controls.Control;
import io.github.palexdev.mfxcore.controls.SkinBase;
import io.github.palexdev.mfxcore.utils.NumberUtils;
import io.github.palexdev.mfxcore.utils.fx.StyleUtils;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.css.CssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleablePropertyFactory;
import java.util.List;
import java.util.function.Supplier;
/**
* Custom implementation of a progress indicator according to the Material Design 3 guidelines. Extends {@link MFXControl}
* and has two skins:
* - {@link MFXLinearProgressIndicatorSkin} is to show the progress as a bar
*
- {@link MFXCircularProgressIndicatorSkin} is to show progress as a circle/arc
*
* You can switch skins either by calling {@link #changeSkin(SkinBase)} or preferably by setting the {@link #displayModeProperty()}.
*
* The default style class is: '.mfx-progress-indicator'.
*
* There are only two properties, one is the {@link #progressProperty()} which expresses progress in the range
* {@code [0.0, 1.0]}; the other is {@link #indeterminateProperty()} and it's read-only. The latter will be active/true
* when the progress is {@code -1.0}. Also note that any progress value lesser than 0 will set the {@link #progressProperty()}
* automatically to {@code -1.0}.
*/
public class MFXProgressIndicator extends MFXControl> {
//================================================================================
// Properties
//================================================================================
private final DoubleProperty progress = new SimpleDoubleProperty() {
@Override
public void set(double newValue) {
if (newValue < 0) {
super.set(-1.0);
return;
}
super.set(NumberUtils.clamp(
newValue, 0.0, 1.0
));
}
@Override
protected void invalidated() {
setIndeterminate(get() < 0);
}
};
private final ReadOnlyBooleanWrapper indeterminate = new ReadOnlyBooleanWrapper(false);
//================================================================================
// Constructors
//================================================================================
public MFXProgressIndicator() {
this(-1.0);
}
public MFXProgressIndicator(double progress) {
setProgress(progress);
initialize();
}
//================================================================================
// Methods
//================================================================================
private void initialize() {
getStyleClass().setAll(defaultStyleClasses());
setDefaultBehaviorProvider();
}
//================================================================================
// Overridden Methods
//================================================================================
@Override
protected MFXSkinBase, ?> buildSkin() {
return new MFXLinearProgressIndicatorSkin(this);
}
@Override
public List defaultStyleClasses() {
return List.of("mfx-progress-indicator");
}
@Override
public Supplier> defaultBehaviorProvider() {
return () -> new BehaviorBase<>(this) {};
}
//================================================================================
// Styleable Properties
//================================================================================
private final StyleableObjectProperty displayMode = new StyleableObjectProperty<>(
StyleableProperties.DISPLAY_MODE,
this,
"displayMode",
ProgressDisplayMode.LINEAR
) {
@Override
protected void invalidated() {
ProgressDisplayMode mode = get();
if (mode == null) return;
changeSkin(mode == ProgressDisplayMode.LINEAR ?
new MFXLinearProgressIndicatorSkin(MFXProgressIndicator.this) :
new MFXCircularProgressIndicatorSkin(MFXProgressIndicator.this)
);
}
};
private final StyleableBooleanProperty showStopPoint = new StyleableBooleanProperty(
StyleableProperties.SHOW_STOP_POINT,
this,
"showStopPoint",
true
);
private final StyleableDoubleProperty clipRadius = new StyleableDoubleProperty(
StyleableProperties.CLIP_RADIUS,
this,
"clipRadius",
6.0
);
public ProgressDisplayMode getDisplayMode() {
return displayMode.get();
}
/**
* Specifies how to display progress, currently, and by the Material Design 3 specs, there are only two ways:
* with a bar or a circle/arc.
*
* This property will automatically change the component's skin according to the specified mode to
* {@link MFXLinearProgressIndicatorSkin} or {@link MFXCircularProgressIndicatorSkin}. If you set it to {@code null},
* nothing will happen.
*
* Can be set in CSS via the property: '-mfx-display-mode'.
*/
public StyleableObjectProperty displayModeProperty() {
return displayMode;
}
public void setDisplayMode(ProgressDisplayMode displayMode) {
this.displayMode.set(displayMode);
}
public boolean isShowStopPoint() {
return showStopPoint.get();
}
/**
* According to Material Design 3 specs, linear progress indicators can show a little dot at the end of the bar for
* better accessibility. It's suggested to turn it on if the contrast between the track and the node containing the
* indicator is below 3:1.
*
* Can be set in CSS via the property: '-mfx-show-stop-point'.
*/
public StyleableBooleanProperty showStopPointProperty() {
return showStopPoint;
}
public void setShowStopPoint(boolean showStopPoint) {
this.showStopPoint.set(showStopPoint);
}
public double getClipRadius() {
return clipRadius.get();
}
/**
* The {@link MFXLinearProgressIndicatorSkin} applies a clip to the component to avoid bars from overflowing when
* animated. Since by design the bars are rounded, the clip must be rounded too. This property specifies the clip's radius.
*
* Can be set in CSS via the property: '-mfx-clip-radius'.
*/
public StyleableDoubleProperty clipRadiusProperty() {
return clipRadius;
}
public void setClipRadius(double clipRadius) {
this.clipRadius.set(clipRadius);
}
//================================================================================
// CssMetaData
//================================================================================
private static class StyleableProperties {
private static final StyleablePropertyFactory FACTORY = new StyleablePropertyFactory<>(Control.getClassCssMetaData());
private static final List> cssMetaDataList;
private static final CssMetaData DISPLAY_MODE =
FACTORY.createEnumCssMetaData(
ProgressDisplayMode.class,
"-mfx-display-mode",
MFXProgressIndicator::displayModeProperty,
ProgressDisplayMode.LINEAR
);
private static final CssMetaData SHOW_STOP_POINT =
FACTORY.createBooleanCssMetaData(
"-mfx-show-stop-point",
MFXProgressIndicator::showStopPointProperty,
true
);
private static final CssMetaData CLIP_RADIUS =
FACTORY.createSizeCssMetaData(
"-mfx-clip-radius",
MFXProgressIndicator::clipRadiusProperty,
6.0
);
static {
cssMetaDataList = StyleUtils.cssMetaDataList(
Control.getClassCssMetaData(),
DISPLAY_MODE, SHOW_STOP_POINT, CLIP_RADIUS
);
}
}
public static List> getClassCssMetaData() {
return StyleableProperties.cssMetaDataList;
}
@Override
protected List> getControlCssMetaData() {
return getClassCssMetaData();
}
//================================================================================
// Getters/Setters
//================================================================================
public double getProgress() {
return progress.get();
}
/**
* Specifies the progress in the range {@code [0.0, 1.0]}. Any negative number will automatically set the property
* to {@code -1.0}, causing the {@link #indeterminateProperty()} to become {@code true}.
*/
public DoubleProperty progressProperty() {
return progress;
}
public void setProgress(double progress) {
this.progress.set(progress);
}
public boolean isIndeterminate() {
return indeterminate.get();
}
/**
* Specifies whether the {@link #progressProperty()} is negative.
*/
public ReadOnlyBooleanProperty indeterminateProperty() {
return indeterminate.getReadOnlyProperty();
}
protected void setIndeterminate(boolean indeterminate) {
this.indeterminate.set(indeterminate);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy