diff --git a/CHANGELOG.md b/CHANGELOG.md index 799a2455..f146a609 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [//]: ##[Unreleased] +## [11.13.3] - 10-03-2022 + +### Added + +- MFXTextField: added a label to specify the unit of measure (optional, leave blank string to remove) + +### Changed + +- Update Gradle plugins +- Update VirtualizedFX to 11.2.5 +- Improve ROADMAP + ## [11.13.2] - 09-02-2022 ### Added diff --git a/ROADMAP.md b/ROADMAP.md index cf9c491b..ab55da3a 100755 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,18 +1,52 @@ # TODOs and Future Plans -- [ ] *MFXCard* -- [ ] *MFXChipView(?)* -- [x] *MFXSlider* -- [ ] *MFXRangeSlider* -- [ ] *MFXHighlighter(?)* -

-- [ ] *MFXColorPicker* -- [ ] *MFXDateTimePicker(?)* -- [ ] *MFXTimePicker* -

-- [ ] *MFXCheckboxTableView* -- [ ] *Scrollable MFXTableView* -

-- [ ] *MFXToastNotification* -- [ ] *Improve Notification System(?)* -- [ ] *Introduce StringConverters for listviews' cells too?* \ No newline at end of file +# IMPORTANT! + +A more complete roadmap is now available at [Trello](https://trello.com/b/RqRwBIRh/materialfx-roadmap) + +## Priority Legend + +- **HIGH**: you can expect the feature in the next major version +- **LOW**: the feature will be implemented when I feel like it, or if the request is so high that it escalates to ** + HIGH** priority +- **TBD**: the idea is there, the feature will be implemented at some point in the future + +Note that you can influence the ROADMAP priority in two ways: + +1) There's a high request for the feature +2) You can sponsor the project with the $50 one time tier + +### New Features + +| Priority | Feature | Notes | +| -------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| **[HIGH]** | MFXColorPicker | | +| **[HIGH]** | MFXToasts | | +| **[HIGH]** | Screenshot Tool | | +| **[HIGH]** | MFXTextArea | | +| **[HIGH/TBD]** | NavBar/Drawer/TabPane/SideMenu | The idea is definitely there. But I still have to figure out the exact differences between those controls, which to implement and how to do it | +| **[HIGH/TBD]** | Theme API and Dark Theme for MaterialFX controls | The idea is definitely there. But I still have to figure out the best way to implement it | +| **[LOW]** | MFXCard | | +| **[LOW]** | MFXCheckTableView | | +| **[LOW]** | MFXChipView | | +| **[LOW]** | MFXDateTimePicker | | +| **[LOW]** | MFXRangeSlider | | +| **[LOW]** | MFXTimePicker | | +| **[LOW]** | MFXBadges | | +| **[LOW]** | MFXAccordion | | +| **[TBD]** | MFXCheckComboBox | | +| **[TBD]** | MFXImageView | | +| **[TBD]** | MFXHighlighter | | +| **[TBD]** | MFXSplitButton | | +| **[TBD]** | MFXProgressButton | | +| **[TBD]** | MFXWaveProgressBar | | +| **[TBD]** | MFXRate | | +| **[TDB]** | Compare Slider | | + +### Improvements + +| Priority | Feature | +| --------- | ------------------------------------- | +| **[LOW]** | Further improve the NotifcationSystem | +| **[LOW]** | Improve MFXSlider | +| **[TBD]** | Auto completion for text fields | \ No newline at end of file diff --git a/build.gradle b/build.gradle index c9885bce..c4e6ab7a 100755 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ plugins { id 'java-library' - id 'org.openjfx.javafxplugin' version '0.0.11' apply false + id 'org.openjfx.javafxplugin' version '0.0.12' apply false } group 'io.github.palexdev' -version '11.13.2' +version '11.13.3' repositories { mavenCentral() diff --git a/demo/build.gradle b/demo/build.gradle index 79365384..324a0b65 100755 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,6 +1,6 @@ plugins { id 'application' - id 'org.beryx.jlink' version '2.24.4' + id 'org.beryx.jlink' version '2.25.0' } repositories { @@ -24,7 +24,7 @@ dependencies { implementation 'org.kordamp.ikonli:ikonli-core:12.2.0' implementation 'org.kordamp.ikonli:ikonli-javafx:12.2.0' implementation 'org.kordamp.ikonli:ikonli-fontawesome5-pack:12.2.0' - implementation 'io.github.palexdev:virtualizedfx:11.2.4' + implementation 'io.github.palexdev:virtualizedfx:11.2.5' implementation project(':materialfx') } diff --git a/demo/src/main/java/module-info.java b/demo/src/main/java/module-info.java index a3f637f8..83cb70d6 100755 --- a/demo/src/main/java/module-info.java +++ b/demo/src/main/java/module-info.java @@ -1,5 +1,6 @@ module MaterialFX.Demo { requires MaterialFX; + requires VirtualizedFX; requires jdk.localedata; diff --git a/demo/src/test/java/Launcher.java b/demo/src/test/java/Launcher.java index e051d53d..a81c1780 100755 --- a/demo/src/test/java/Launcher.java +++ b/demo/src/test/java/Launcher.java @@ -3,6 +3,6 @@ import javafx.application.Application; public class Launcher { public static void main(String[] args) { - Application.launch(MagnifierTest.class, args); + Application.launch(Playground.class, args); } } diff --git a/demo/src/test/java/Playground.java b/demo/src/test/java/Playground.java index e3c3391b..c22acbc8 100755 --- a/demo/src/test/java/Playground.java +++ b/demo/src/test/java/Playground.java @@ -1,72 +1,35 @@ -import fr.brouillard.oss.cssfx.CSSFX; -import io.github.palexdev.materialfx.MFXResourcesLoader; import io.github.palexdev.materialfx.controls.MFXButton; -import io.github.palexdev.materialfx.controls.MFXSpinner; -import io.github.palexdev.materialfx.controls.models.spinner.ListSpinnerModel; +import io.github.palexdev.materialfx.controls.MFXTextField; import javafx.application.Application; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; import javafx.geometry.Pos; import javafx.scene.Scene; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; import javafx.stage.Stage; import org.scenicview.ScenicView; -import java.util.List; - public class Playground extends Application { + private final double w = 445; + private final double h = 270; @Override public void start(Stage primaryStage) { - CSSFX.start(); - BorderPane borderPane = new BorderPane(); + VBox vBox = new VBox(10); + vBox.setAlignment(Pos.CENTER); - ObservableList strings = FXCollections.observableArrayList( - "String 1", - "String 2", - "String 3", - "String 4", - "String 5", - "String 6", - "String 7", - "String 8" - ); + MFXTextField textField = new MFXTextField("15.0", "", "Pixels"); - MFXSpinner spinner = new MFXSpinner<>(); - spinner.getStylesheets().add(MFXResourcesLoader.load("css/MFXSpinner.css")); - spinner.setSpinnerModel(new ListSpinnerModel<>()); - spinner.getSpinnerModel().setWrapAround(true); - ((ListSpinnerModel) spinner.getSpinnerModel()).setItems(strings); - spinner.setTextTransformer((focused, text) -> ((!focused || !spinner.isEditable()) && !text.isEmpty()) ? text + " cm" : text); - - MFXButton add = new MFXButton("Add"); - add.setOnAction(event -> ((ListSpinnerModel) spinner.getSpinnerModel()).getItems().addAll(2, List.of("String Added 1", "String Added 2"))); - MFXButton remove = new MFXButton("Remove"); - remove.setOnAction(event -> ((ListSpinnerModel) spinner.getSpinnerModel()).getItems().clear()); - MFXButton removeSel = new MFXButton("Remove Selected"); - removeSel.setOnAction(event -> ((ListSpinnerModel) spinner.getSpinnerModel()).getItems().remove(((ListSpinnerModel) spinner.getSpinnerModel()).getCurrentIndex())); - MFXButton replace = new MFXButton("Replace"); - replace.setOnAction(event -> ((ListSpinnerModel) spinner.getSpinnerModel()).getItems().set(((ListSpinnerModel) spinner.getSpinnerModel()).getCurrentIndex(), "Replaced")); - MFXButton change = new MFXButton("Change List"); - change.setOnAction(event -> { - ListSpinnerModel model = (ListSpinnerModel) spinner.getSpinnerModel(); - model.setItems(FXCollections.observableArrayList( - "String 9", - "String 10", - "String 11", - "String 12", - "String 1234567890" - )); + MFXButton button = new MFXButton("Change Measure Unit"); + button.setOnAction(event -> { + String measureUnit = textField.getMeasureUnit(); + measureUnit = (measureUnit == null || measureUnit.isEmpty()) ? "px" : "cm"; + textField.setMeasureUnit(measureUnit); }); - HBox box = new HBox(15, add, remove, removeSel, replace, change); - box.setAlignment(Pos.CENTER); - borderPane.setCenter(spinner); - borderPane.setBottom(box); - Scene scene = new Scene(borderPane, 800, 600); + vBox.getChildren().addAll(button, textField); + Scene scene = new Scene(vBox, 800, 800); primaryStage.setScene(scene); primaryStage.show(); + ScenicView.show(scene); } } diff --git a/demo/src/test/java/ScreenTest.java b/demo/src/test/java/ScreenTest.java new file mode 100644 index 00000000..27d40b67 --- /dev/null +++ b/demo/src/test/java/ScreenTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 Parisi Alessandro + * 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 . + */ + +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.image.ImageView; +import javafx.scene.image.WritableImage; +import javafx.scene.layout.BorderPane; +import javafx.scene.robot.Robot; +import javafx.stage.Screen; +import javafx.stage.Stage; + +public class ScreenTest extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + ImageView iv = new ImageView(); + + BorderPane bp = new BorderPane(iv); + Robot robot = new Robot(); + WritableImage capture = robot.getScreenCapture(null, Screen.getPrimary().getBounds()); + iv.setImage(capture); + + Scene scene = new Scene(bp, 800, 800); + primaryStage.setScene(scene); + primaryStage.show(); + } +} diff --git a/materialfx/build.gradle b/materialfx/build.gradle index 2dfa65b1..e0efa110 100755 --- a/materialfx/build.gradle +++ b/materialfx/build.gradle @@ -1,9 +1,9 @@ import org.apache.tools.ant.taskdefs.condition.Os plugins { - id 'biz.aQute.bnd.builder' version '5.3.0' - id 'com.vanniktech.maven.publish' version '0.18.0' - id 'com.github.johnrengelman.shadow' version '7.0.0' + id 'biz.aQute.bnd.builder' version '6.2.0' + id 'com.vanniktech.maven.publish' version '0.19.0' + id 'com.github.johnrengelman.shadow' version '7.1.2' } repositories { @@ -21,9 +21,9 @@ compileJava { dependencies { testImplementation('junit:junit:4.13.2') - implementation 'com.vanniktech:gradle-maven-publish-plugin:0.18.0' + implementation 'com.vanniktech:gradle-maven-publish-plugin:0.19.0' - implementation 'io.github.palexdev:virtualizedfx:11.2.4' + implementation 'io.github.palexdev:virtualizedfx:11.2.5' } javadoc { @@ -70,7 +70,7 @@ jar { shadowJar { mergeServiceFiles() dependencies { - include(dependency('io.github.palexdev:virtualizedfx:11.2.4')) + include(dependency('io.github.palexdev:virtualizedfx:11.2.5')) } } diff --git a/materialfx/gradle.properties b/materialfx/gradle.properties index 37cd21a4..2088c0bc 100755 --- a/materialfx/gradle.properties +++ b/materialfx/gradle.properties @@ -1,6 +1,6 @@ GROUP=io.github.palexdev POM_ARTIFACT_ID=materialfx -VERSION_NAME=11.13.2 +VERSION_NAME=11.13.3 POM_NAME=materialfx POM_DESCRIPTION=Material Desgin components for JavaFX diff --git a/materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTextField.java b/materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTextField.java index 5aa0778c..36078fa0 100644 --- a/materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTextField.java +++ b/materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTextField.java @@ -137,6 +137,8 @@ public class MFXTextField extends TextField implements Validated, MFXMenuControl }; private static final PseudoClass FLOATING_PSEUDO_CLASS = PseudoClass.getPseudoClass("floating"); + private final StringProperty measureUnit = new SimpleStringProperty(""); + protected final MFXValidator validator = new MFXValidator(); protected MFXContextMenu contextMenu; @@ -579,6 +581,24 @@ public class MFXTextField extends TextField implements Validated, MFXMenuControl return floating; } + public String getMeasureUnit() { + return measureUnit.get(); + } + + /** + * Specifies the unit of measure of the field. + *

+ * This is useful of course when dealing with numeric fields that represent for example: + * weight, volume, length and so on... + */ + public StringProperty measureUnitProperty() { + return measureUnit; + } + + public void setMeasureUnit(String measureUnit) { + this.measureUnit.set(measureUnit); + } + //================================================================================ // Styleable Properties //================================================================================ @@ -631,6 +651,13 @@ public class MFXTextField extends TextField implements Validated, MFXMenuControl 10.0 ); + private final StyleableDoubleProperty measureUnitGap = new StyleableDoubleProperty( + StyleableProperties.MEASURE_UNIT_GAP, + this, + "measureUnitGap", + 5.0 + ); + private final StyleableBooleanProperty scaleOnAbove = new StyleableBooleanProperty( StyleableProperties.SCALE_ON_ABOVE, this, @@ -778,6 +805,21 @@ public class MFXTextField extends TextField implements Validated, MFXMenuControl this.scaleOnAbove.set(scaleOnAbove); } + public double getMeasureUnitGap() { + return measureUnitGap.get(); + } + + /** + * Specifies the gap between the field and the measure unit label. + */ + public StyleableDoubleProperty measureUnitGapProperty() { + return measureUnitGap; + } + + public void setMeasureUnitGap(double measureUnitGap) { + this.measureUnitGap.set(measureUnitGap); + } + public Color getTextFill() { return textFill.get(); } @@ -865,6 +907,13 @@ public class MFXTextField extends TextField implements Validated, MFXMenuControl 10.0 ); + private static final CssMetaData MEASURE_UNIT_GAP = + FACTORY.createSizeCssMetaData( + "-mfx-measure-unit-gap", + MFXTextField::measureUnitGapProperty, + 5.0 + ); + private static final CssMetaData SCALE_ON_ABOVE = FACTORY.createBooleanCssMetaData( "-mfx-scale-on-above", @@ -890,7 +939,7 @@ public class MFXTextField extends TextField implements Validated, MFXMenuControl cssMetaDataList = StyleablePropertiesUtils.cssMetaDataList( TextField.getClassCssMetaData(), ANIMATED, CARET_VISIBLE, BORDER_GAP, - EDITABLE, FLOAT_MODE, FLOATING_TEXT_GAP, GRAPHIC_TEXT_GAP, + EDITABLE, FLOAT_MODE, FLOATING_TEXT_GAP, GRAPHIC_TEXT_GAP, MEASURE_UNIT_GAP, SCALE_ON_ABOVE, TEXT_FILL, TEXT_LIMIT ); } diff --git a/materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTextFieldSkin.java b/materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTextFieldSkin.java index d09df031..7a95fdde 100644 --- a/materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTextFieldSkin.java +++ b/materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTextFieldSkin.java @@ -62,6 +62,7 @@ public class MFXTextFieldSkin extends SkinBase { //================================================================================ private final BoundTextField boundField; private final Label floatingText; + private final Label mUnitLabel; private static final PseudoClass FOCUS_WITHIN_PSEUDO_CLASS = PseudoClass.getPseudoClass("focus-within"); @@ -87,13 +88,18 @@ public class MFXTextFieldSkin extends SkinBase { floatingText.getTransforms().addAll(scale, translate); if (textField.getFloatMode() == FloatMode.DISABLED) floatingText.setVisible(false); + mUnitLabel = new Label(); + mUnitLabel.getStyleClass().setAll("measure-unit"); + mUnitLabel.textProperty().bind(textField.measureUnitProperty()); + mUnitLabel.visibleProperty().bind(textField.measureUnitProperty().isNotNull().and(textField.measureUnitProperty().isNotEmpty())); + floating = Bindings.createBooleanBinding( () -> getFloatY() != 0, floatingPos ); textField.floatingProperty().bind(floating); - getChildren().setAll(floatingText, boundField); + getChildren().setAll(floatingText, boundField, mUnitLabel); if (!shouldFloat()) { scale.setX(1); @@ -142,6 +148,7 @@ public class MFXTextFieldSkin extends SkinBase { textField.requestLayout(); }); textField.floatingTextGapProperty().addListener((observable, oldValue, newValue) -> textField.requestLayout()); + textField.measureUnitGapProperty().addListener((observable, oldValue, newValue) -> textField.requestLayout()); textField.borderGapProperty().addListener((observable, oldValue, newValue) -> textField.requestLayout()); // Focus Handling @@ -241,19 +248,6 @@ public class MFXTextFieldSkin extends SkinBase { return computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); } - @Override - protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { - MFXTextField textField = getSkinnable(); - Node leading = textField.getLeadingIcon(); - Node trailing = textField.getTrailingIcon(); - double gap = textField.getGraphicTextGap(); - return leftInset + - (leading != null ? leading.prefWidth(-1) + gap : 0) + - Math.max(boundField.prefWidth(-1), floatingText.prefWidth(-1)) + - (trailing != null ? trailing.prefWidth(-1) + gap : 0) + - rightInset; - } - @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) { MFXTextField textField = getSkinnable(); @@ -285,6 +279,20 @@ public class MFXTextFieldSkin extends SkinBase { return Math.max(iconsMax, height); } + @Override + protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { + MFXTextField textField = getSkinnable(); + Node leading = textField.getLeadingIcon(); + Node trailing = textField.getTrailingIcon(); + double gap = textField.getGraphicTextGap(); + double mUnitGap = textField.getMeasureUnitGap(); + return leftInset + + (leading != null ? leading.prefWidth(-1) + gap : 0) + + Math.max(boundField.prefWidth(-1) + mUnitLabel.prefWidth(-1) + mUnitGap, floatingText.prefWidth(-1)) + + (trailing != null ? trailing.prefWidth(-1) + gap : 0) + + rightInset; + } + @Override protected double computeMaxWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) { if (getSkinnable().getMaxWidth() == Double.MAX_VALUE) return Double.MAX_VALUE; @@ -303,6 +311,7 @@ public class MFXTextFieldSkin extends SkinBase { Node leading = textField.getLeadingIcon(); Node trailing = textField.getTrailingIcon(); double graphicTextGap = textField.getGraphicTextGap(); + double mUnitGap = textField.getMeasureUnitGap(); FloatMode floatMode = textField.getFloatMode(); VPos textVAlignment = (floatMode != FloatMode.INLINE) ? VPos.CENTER : VPos.BOTTOM; double scaleValue = (floatMode == FloatMode.ABOVE && !textField.scaleOnAbove()) ? 1 : this.scaleValue; @@ -357,6 +366,18 @@ public class MFXTextFieldSkin extends SkinBase { ); floatingText.resizeRelocate(floatPos.getX(), floatPos.getY(), floatW, floatH); + // Position the Label responsible for showing the measure unit + double unitW = mUnitLabel.prefWidth(-1); + double unitH = mUnitLabel.prefHeight(-1); + PositionBean unitPos = PositionUtils.computePosition( + textField, + mUnitLabel, + x, y, w, h, 0, + Insets.EMPTY, + HPos.RIGHT, textVAlignment + ); + mUnitLabel.resizeRelocate(unitPos.getX(), unitPos.getY(), unitW, unitH); + // The text is always positioned to the LEFT of the Pane, the vertical alignment // depends on the FloatMode, BOTTOM if FloatMode.INLINE, CENTER in every other mode // @@ -364,7 +385,8 @@ public class MFXTextFieldSkin extends SkinBase { // minus the icon's width and gap double textW = w - (leading != null ? leading.prefWidth(-1) + graphicTextGap : 0) - - (trailing != null ? trailing.prefWidth(-1) + graphicTextGap : 0); + (trailing != null ? trailing.prefWidth(-1) + graphicTextGap : 0) - + unitW - mUnitGap; double textH = boundField.prefHeight(-1); PositionBean textPos = PositionUtils.computePosition( textField, diff --git a/materialfx/src/main/java/module-info.java b/materialfx/src/main/java/module-info.java index 0235db42..61d2296c 100755 --- a/materialfx/src/main/java/module-info.java +++ b/materialfx/src/main/java/module-info.java @@ -4,7 +4,7 @@ module MaterialFX { requires transitive javafx.graphics; requires transitive java.desktop; - requires virtualizedfx; + requires VirtualizedFX; exports io.github.palexdev.materialfx; diff --git a/materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXTextField.css b/materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXTextField.css index 6f21e030..94677c23 100755 --- a/materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXTextField.css +++ b/materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXTextField.css @@ -65,6 +65,11 @@ -fx-text-fill: -mfx-main; } +.mfx-text-field .measure-unit { + -fx-font-family: "Open Sans Regular"; + -fx-text-fill: -mfx-text-he; +} + .mfx-text-field .text-field { -fx-text-box-border: transparent; -fx-background-color: transparent; diff --git a/wiki/Text Fields.md b/wiki/Text Fields.md index b44ccfbc..df258441 100644 --- a/wiki/Text Fields.md +++ b/wiki/Text Fields.md @@ -14,28 +14,30 @@ ### Properties -| Property | Description | Type | -| ------------ | ---------------------------------------------------------------- | -------:| -| selectable | Specifies whether selection is allowed | Boolean | -| leadingIcon | Specifies the icon placed before the input field | Node | -| trailingIcon | Specifies the icon placed after the input field | Node | -| floatingText | Specifies the text of the floating text node | String | -| floating | Specifies if the floating text node is currently floating or not | Boolean | +| Property | Description | Type | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------:| +| selectable | Specifies whether selection is allowed | Boolean | +| leadingIcon | Specifies the icon placed before the input field | Node | +| trailingIcon | Specifies the icon placed after the input field | Node | +| floatingText | Specifies the text of the floating text node | String | +| floating | Specifies if the floating text node is currently floating or not | Boolean | +| measureUnit | Specifies the unit of measure of the field.
This is useful of course when dealing with numeric fields that represent for example: weight, volume, length and so on... | String | ### Styleable Properties -| Property | Description | CSS Property | Type | Default Value | -| --------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---------------:| ------------------------:| -| allowEdit | Specifies whether the field is editable | -mfx-editable | Boolean | true | -| animated | Specifies whether the floating text positioning is animated | -mfx-animated | Boolean | true | -| borderGap | For FloatMode.BORDER FloatMode.ABOVE modes, this specifies the distance from the control's x origin (padding not included) | -mfx-border-gap | Double | 10.0 | -| caretVisible | Specifies whether the caret should be visible | -mfx-caret-visible | Boolean | true | -| floatMode | Specifies how the floating text is positioned when floating.
Can be: DISABLED, ABOVE, BORDER, INLINE | -mfx-float-mode | FloatMode[Enum] | INLINE | -| floatingTextGap | For FloatMode.INLINE mode, this specifies the gap between the floating text node and the input field node | -mfx-gap | Double | 5.0 | -| graphicTextGap | Specifies the gap between the input field and the icons | -fx-graphic-text-gap | Double | 10.0 | -| scaleOnAbove | Specifies whether the floating text node should be scaled or not when the float mode is set to FloatMode.ABOVE | -mfx-scale-on-above | Boolean | false | -| textFill | Specifies the text color | -fx-text-fill | Color | Color.rgb(0, 0, 0, 0.87) | -| textLimit | Specifies the maximum number of characters the field's text can have | -mfx-text-limit | Integer | -1(Unlimited) | +| Property | Description | CSS Property | Type | Default Value | +| --------------- | -------------------------------------------------------------------------------------------------------------------------- | --------------------- | ---------------:| ------------------------:| +| allowEdit | Specifies whether the field is editable | -mfx-editable | Boolean | true | +| animated | Specifies whether the floating text positioning is animated | -mfx-animated | Boolean | true | +| borderGap | For FloatMode.BORDER FloatMode.ABOVE modes, this specifies the distance from the control's x origin (padding not included) | -mfx-border-gap | Double | 10.0 | +| caretVisible | Specifies whether the caret should be visible | -mfx-caret-visible | Boolean | true | +| floatMode | Specifies how the floating text is positioned when floating.
Can be: DISABLED, ABOVE, BORDER, INLINE | -mfx-float-mode | FloatMode[Enum] | INLINE | +| floatingTextGap | For FloatMode.INLINE mode, this specifies the gap between the floating text node and the input field node | -mfx-gap | Double | 5.0 | +| graphicTextGap | Specifies the gap between the input field and the icons | -fx-graphic-text-gap | Double | 10.0 | +| measureUnitGap | Specifies the gap between the field and the measure unit label | -mfx-measure-unit-gap | Double | 5.0 | +| scaleOnAbove | Specifies whether the floating text node should be scaled or not when the float mode is set to FloatMode.ABOVE | -mfx-scale-on-above | Boolean | false | +| textFill | Specifies the text color | -fx-text-fill | Color | Color.rgb(0, 0, 0, 0.87) | +| textLimit | Specifies the maximum number of characters the field's text can have | -mfx-text-limit | Integer | -1(Unlimited) | ### CSS Selectors