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

com.dlsc.gemsfx.LimitedTextArea Maven / Gradle / Ivy

There is a newer version: 2.81.0
Show newest version
package com.dlsc.gemsfx;

import com.dlsc.gemsfx.skins.LimitedTextAreaSkin;
import com.dlsc.gemsfx.util.IntegerRange;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.css.CssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleableBooleanProperty;
import javafx.css.StyleableProperty;
import javafx.css.converter.BooleanConverter;
import javafx.scene.control.Skin;

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

/**
 * A specialized text area view that imposes restrictions on the input text length, allowing
 * specification of minimum and maximum character limits. It provides the functionality to define
 * a range of allowed text lengths and supports the removal of specified strings by replacing them
 * with an empty string. This component is designed for scenarios where input text needs to adhere
 * to specific length requirements and certain substrings are not permitted.
 *
 * 

* If the text length range is not specified, the value of the text length indicator label will reflect the number of characters in the text area. * If a range is specified, the label will show the difference between the current text length and the maximum allowed character count. * Should the text exceed the allowed maximum, the label will display a negative number. * *

* Use cases include form fields where input character count is restricted within a certain range * for validation purposes, or text areas that need to filter out specific unwanted characters or * phrases. */ public class LimitedTextArea extends ResizableTextArea { private static final String DEFAULT_STYLE_CLASS = "limited-text-area"; private static final boolean DEFAULT_SHOW_BOTTOM = true; public enum LengthDisplayMode { /** * When in a warning or error state, the text length indicator label will be displayed. */ AUTO, /** * Always show the length indicator. */ ALWAYS_SHOW, /** * Always hide the length indicator. */ ALWAYS_HIDE } public LimitedTextArea() { getStyleClass().add(DEFAULT_STYLE_CLASS); getStylesheets().add(Objects.requireNonNull(LimitedTextArea.class.getResource("limited-text-area.css")).toExternalForm()); } public LimitedTextArea(String text) { this(); setText(text); } @Override protected Skin createDefaultSkin() { return new LimitedTextAreaSkin(this, outOfRange); } private BooleanProperty showBottom; public final BooleanProperty showBottomProperty() { if (showBottom == null) { showBottom = new StyleableBooleanProperty(DEFAULT_SHOW_BOTTOM) { @Override public Object getBean() { return LimitedTextArea.this; } @Override public String getName() { return "showBottom"; } @Override public CssMetaData getCssMetaData() { return StyleableProperties.SHOW_BOTTOM; } }; } return showBottom; } public final boolean isShowBottom() { return showBottom == null ? DEFAULT_SHOW_BOTTOM : showBottom.get(); } public final void setShowBottom(boolean showBottom) { showBottomProperty().set(showBottom); } private final ObjectProperty characterRangeLimit = new SimpleObjectProperty<>(this, "characterRangeLimit"); public final IntegerRange getCharacterRangeLimit() { return characterRangeLimit.get(); } /** * The character range limit property defines the minimum and maximum number of characters allowed in the text area. * * @return the character range limit property */ public final ObjectProperty characterRangeLimitProperty() { return characterRangeLimit; } public final void setCharacterRangeLimit(IntegerRange characterRangeLimit) { this.characterRangeLimit.set(characterRangeLimit); } /** * A list of items that should be excluded from the text content. * e.g. "\r", "\n", "\t" ,"." etc. */ private final ObservableList excludedItems = FXCollections.observableArrayList(); public final ObservableList getExcludedItems() { return excludedItems; } private final StringProperty tips = new SimpleStringProperty(this, "tips"); public final String getTips() { return tips.get(); } /** * The tips property used to display a hint or description of the text area. */ public final StringProperty tipsProperty() { return tips; } public final void setTips(String tips) { this.tips.set(tips); } private final ReadOnlyBooleanWrapper outOfRange = new ReadOnlyBooleanWrapper(this, "isOverLimit", false); public final boolean isOutOfRange() { return outOfRange.get(); } /** * A read-only property indicating whether the text content is over the maximum length or under the minimum length. */ public final ReadOnlyBooleanProperty outOfRangeProperty() { return outOfRange.getReadOnlyProperty(); } private final void setOutOfRange(boolean outOfRange) { this.outOfRange.set(outOfRange); } private final ObjectProperty lengthDisplayMode = new SimpleObjectProperty<>(this, "lengthDisplayMode", LengthDisplayMode.AUTO); public final LengthDisplayMode getLengthDisplayMode() { return lengthDisplayMode.get(); } /** * The length display mode property defines when the text length indicator label should be displayed. * {@link LengthDisplayMode#AUTO}, {@link LengthDisplayMode#ALWAYS_SHOW}, {@link LengthDisplayMode#ALWAYS_HIDE} * * @return the length display mode property */ public final ObjectProperty lengthDisplayModeProperty() { return lengthDisplayMode; } public final void setLengthDisplayMode(LengthDisplayMode lengthDisplayMode) { this.lengthDisplayMode.set(lengthDisplayMode); } private final DoubleProperty warningThreshold = new SimpleDoubleProperty(this, "warningThreshold", 0.9); public final double getWarningThreshold() { return warningThreshold.get(); } /** * The warning threshold is a value between 0 and 1. * When the text length is greater than or equal to the maximum length times the warning threshold, the warning style will be applied. */ public final DoubleProperty warningThresholdProperty() { return warningThreshold; } public final void setWarningThreshold(double warningThreshold) { this.warningThreshold.set(warningThreshold); } public final double getValidWarningThreshold() { return Math.min(Math.max(getWarningThreshold(), 0), 0.999999); } private static class StyleableProperties { private static final CssMetaData SHOW_BOTTOM = new CssMetaData<>( "-fx-show-bottom", BooleanConverter.getInstance(), DEFAULT_SHOW_BOTTOM) { @Override public StyleableProperty getStyleableProperty(LimitedTextArea control) { return (StyleableProperty) control.showBottomProperty(); } @Override public boolean isSettable(LimitedTextArea control) { return control.showBottom == null || !control.showBottom.isBound(); } }; private static final List> STYLEABLES; static { final List> styleables = new ArrayList<>(ResizableTextArea.getClassCssMetaData()); styleables.add(SHOW_BOTTOM); STYLEABLES = Collections.unmodifiableList(styleables); } } @Override public List> getControlCssMetaData() { return getClassCssMetaData(); } public static List> getClassCssMetaData() { return LimitedTextArea.StyleableProperties.STYLEABLES; } // Issue: some css styles will fail. All css files merged into one maybe a solution //@Override //public String getUserAgentStylesheet() { // return LimitedTextArea.class.getResource("limited-text-area.css").toExternalForm(); //} }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy