Browse Source

Minor fixes and improvements

Demo
FontResourcesDemoController:
:recycle: Align list labels to CENTER_LEFT

ListViewsDemo, ListViewsDemoController:
:recycle: Layout remade with an AnchorPane as root

MaterialFX
IListCheckModel, ListCheckModel, MFXFlowlessCheckListCell:
:recycle: :sparkles: Added a way to specify if the check list view should also allow selection. If it is not allowed the selection method of the cell is skipped. If it is allowed selection will be kept only if no checkbox is pressed, e.g if you select some cells and then check a cell with the checkbox the selection will be cleared

MFXComboBox:
:memo: Added warning for selection using the context menu not working if the data is or contains a node (dunno if it can be fixed)

MFXDatePicker, MFXDatePickerContent:
:recycle: Do not set LocalDate.EPOCH if the property needs to be "force-updated", use null instead. As a result in many parts of the code we need null checks
:sparkles: Added the possibility of closing the popup when enter is pressed

MFXFilterComboBoxSkin:
:bug: Fixed validate label icon having wrong color is scene is switched

MFXLabelSkin:
:bug: Fixed inconsistencies between label and editor focus

MFXTextField:
:sparkles: Added redo and undo to the context menu

MFXTextFieldSkin:
:bug: Fixed selection being cleared when context menu was opened

MFXFilterComboBox.css, MFXLabelStyles(all).css:
:bug: Remove the text fields lines, files changed to reflect recent changes

FontResources:
:recycle: Added new resources

README.md:
:sparkles: Added preview GIFs

:sparkles: Added ROADMAP.md
PAlex404 4 years ago
parent
commit
b41e0b62b0
25 changed files with 532 additions and 180 deletions
  1. 128 0
      README.md
  2. 16 0
      ROADMAP.md
  3. 2 0
      demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/FontResourcesDemoController.java
  4. 14 4
      demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/ListViewsDemoController.java
  5. 21 23
      demo/src/main/resources/io/github/palexdev/materialfx/demo/CheckBoxesDemo.fxml
  6. 2 2
      demo/src/main/resources/io/github/palexdev/materialfx/demo/DatePickersDemo.fxml
  7. 84 73
      demo/src/main/resources/io/github/palexdev/materialfx/demo/ListViewsDemo.fxml
  8. 1 1
      demo/src/main/resources/io/github/palexdev/materialfx/demo/TextFieldsDemo.fxml
  9. 6 0
      materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXComboBox.java
  10. 46 0
      materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXDatePicker.java
  11. 16 1
      materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTextField.java
  12. 3 2
      materialfx/src/main/java/io/github/palexdev/materialfx/controls/base/AbstractMFXFlowlessListCell.java
  13. 39 22
      materialfx/src/main/java/io/github/palexdev/materialfx/controls/cell/MFXFlowlessCheckListCell.java
  14. 29 27
      materialfx/src/main/java/io/github/palexdev/materialfx/font/FontResources.java
  15. 25 0
      materialfx/src/main/java/io/github/palexdev/materialfx/selection/ListCheckModel.java
  16. 4 0
      materialfx/src/main/java/io/github/palexdev/materialfx/selection/base/IListCheckModel.java
  17. 6 2
      materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXDatePickerContent.java
  18. 2 3
      materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXFilterComboBoxSkin.java
  19. 39 19
      materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXLabelSkin.java
  20. 18 1
      materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTextFieldSkin.java
  21. 10 0
      materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXFilterComboBox.css
  22. 6 0
      materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXLabelStyle1.css
  23. 10 0
      materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXLabelStyle2.css
  24. 5 0
      materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXLabelStyle3.css
  25. BIN
      materialfx/src/main/resources/io/github/palexdev/materialfx/fonts/MFXResources.ttf

+ 128 - 0
README.md

@@ -35,6 +35,7 @@
 ## Table of Contents
 
 * [About the Project and History of JavaFX](#about-the-project-and-history-of-javafx)
+* [Some GIFs](#preview-gifs)
 * [Getting Started](#getting-started)
     * [Build](#build)
     * [Usage](#usage)
@@ -76,6 +77,133 @@ available [JFoenix](https://github.com/jfoenixadmin/JFoenix) library, which is a
 In recent months the project has evolved a lot, to the point that it is no longer a simple substitute.
 To date MaterialFX offers not only restyled controls, but also: new and unique controls such as the Stepper, controls completely redone from scratch such as ComboBoxes or TableViews (and many others), and many utilities for JavaFX and Java (NodeUtils, ColorUtils, StringUtils ...).
 
+<!-- PREVIEW GIFS -->
+
+## Preview GIFs
+
+#### Imgur Link: [Gallery](https://imgur.com/gallery/J0HUrSZ)
+
+<i>
+<details>
+<summary>Buttons</summary>
+<br>
+<a href="https://imgur.com/n3bKDN9"><img src="https://i.imgur.com/n3bKDN9.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>CheckBoxes</summary>
+<br>
+<a href="https://imgur.com/gbf69gq"><img src="https://i.imgur.com/gbf69gq.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>ComboBoxes</summary>
+<br>
+<a href="https://imgur.com/uS8rwgS"><img src="https://i.imgur.com/uS8rwgS.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>DatePickers</summary>
+<br>
+<a href="https://imgur.com/QVOBaXG"><img src="https://imgur.com/QVOBaXG.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>Dialogs</summary>
+<br>
+<a href="https://imgur.com/ilKuKF9"><img src="https://imgur.com/ilKuKF9.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>Labels</summary>
+<br>
+<a href="https://imgur.com/XWO40LR"><img src="https://imgur.com/XWO40LR.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>ListViews</summary>
+<br>
+<a href="https://imgur.com/WhYKgUI"><img src="https://imgur.com/WhYKgUI.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>Notifications</summary>
+<br>
+<a href="https://imgur.com/lT8zqzV"><img src="https://imgur.com/lT8zqzV.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>ProgressBars</summary>
+<br>
+<a href="https://imgur.com/8FEW5bt"><img src="https://imgur.com/8FEW5bt.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>ProgressSpinners</summary>
+<br>
+<a href="https://imgur.com/x0FiFXW"><img src="https://imgur.com/x0FiFXW.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>RadioButtons</summary>
+<br>
+<a href="https://imgur.com/i2fEmjB"><img src="https://imgur.com/i2fEmjB.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>ScrollPanes</summary>
+<br>
+<a href="https://imgur.com/bqRADeQ"><img src="https://imgur.com/bqRADeQ.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>Stepper</summary>
+<br>
+<a href="https://imgur.com/tNuAwF4"><img src="https://imgur.com/tNuAwF4.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>TableViews</summary>
+<br>
+<a href="https://imgur.com/GZYQtDT"><img src="https://imgur.com/GZYQtDT.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>TextFields</summary>
+<br>
+<a href="https://imgur.com/NYp8LJV"><img src="https://imgur.com/NYp8LJV.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>Toggles</summary>
+<br>
+<a href="https://imgur.com/HcXXi8q"><img src="https://imgur.com/HcXXi8q.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+
+<details>
+<summary>FontResources</summary>
+<br>
+<a href="https://imgur.com/PkCZM0v"><img src="https://imgur.com/PkCZM0v.gif" title="source: imgur.com" /></a>
+</details>
+<p></p>
+</i>
+
 <!-- GETTING STARTED -->
 
 ## Getting Started

+ 16 - 0
ROADMAP.md

@@ -0,0 +1,16 @@
+# TODOs and Future Plans
+
+- [ ] *MFXCard*
+- [ ] *MFXChipView(?)*
+- [ ] *MFXSlider*
+- [ ] *MFXHighlighter(?)*
+  <br></br>
+- [ ] *MFXColorPicker*
+- [ ] *MFXDateTimePicker(?)*
+- [ ] *MFXTimePicker*
+  <br></br>
+- [ ] *MFXCheckboxTableView*
+- [ ] *Scrollable MFXTableView*
+  <br></br>
+- [ ] *MFXToastNotification*
+- [ ] *Improve Notification System(?)*

+ 2 - 0
demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/FontResourcesDemoController.java

@@ -77,6 +77,7 @@ public class FontResourcesDemoController implements Initializable {
         l1.setStyle("-fx-background-color: transparent");
         l1.setText("Description: " + fontResource.getDescription());
         l1.setMinWidth(300);
+        l1.setAlignment(Pos.CENTER_LEFT);
 
         MFXLabel l2 = new MFXLabel();
         l2.setLineColor(Color.TRANSPARENT);
@@ -84,6 +85,7 @@ public class FontResourcesDemoController implements Initializable {
         l2.setStyle("-fx-background-color: transparent");
         l2.setText("Code: " + Integer.toHexString(fontResource.getCode() | 0x10000).substring(1).toUpperCase());
         l2.setMinWidth(300);
+        l2.setAlignment(Pos.CENTER_LEFT);
 
         Separator s1 = new Separator(Orientation.VERTICAL);
         s1.setStyle("-fx-fill: white");

+ 14 - 4
demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/ListViewDemoController.java → demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/ListViewsDemoController.java

@@ -39,7 +39,7 @@ import java.util.List;
 import java.util.Random;
 import java.util.ResourceBundle;
 
-public class ListViewDemoController implements Initializable {
+public class ListViewsDemoController implements Initializable {
     private final Random random = new Random(System.currentTimeMillis());
 
     private enum State {
@@ -82,7 +82,7 @@ public class ListViewDemoController implements Initializable {
     private MFXFlowlessListView<String> cssViewNew;
 
     @FXML
-    private MFXButton switchButton;
+    private MFXButton swapButton;
 
     @FXML
     private MFXButton depthButton;
@@ -90,6 +90,12 @@ public class ListViewDemoController implements Initializable {
     @FXML
     private MFXButton colorsButton;
 
+    @FXML
+    private Label mulLabel;
+
+    @FXML
+    private MFXCheckbox allowSelection;
+
     private ObservableList<String> stringList;
     private ObservableList<Label> labelsList;
     private ObservableList<HBox> hBoxesList;
@@ -103,14 +109,18 @@ public class ListViewDemoController implements Initializable {
 
         state.addListener((observable, oldValue, newValue) -> {
             if (newValue == State.NEW) {
+                mulLabel.setVisible(true);
                 legacyBox.setVisible(false);
                 newBox.setVisible(true);
             } else {
+                mulLabel.setVisible(false);
                 legacyBox.setVisible(true);
                 newBox.setVisible(false);
             }
         });
 
+        checkList.getSelectionModel().allowsSelectionProperty().bind(allowSelection.selectedProperty());
+
         //  LEGACY //
         stringView.setItems(stringList);
         labelView.setItems(labelsList);
@@ -124,7 +134,7 @@ public class ListViewDemoController implements Initializable {
         checkList.setItems(stringList);
         cssViewNew.setItems(stringList);
 
-        switchButton.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> updateState());
+        swapButton.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> updateState());
         depthButton.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> updateDepth());
         colorsButton.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> updateColors());
 
@@ -235,7 +245,7 @@ public class ListViewDemoController implements Initializable {
 
     private void updateState() {
         State curr = state.get();
-        switchButton.setText(curr == State.LEGACY ?  "Switch to Legacy" : "Switch to New");
+        swapButton.setText(curr == State.LEGACY ?  "Switch to Legacy" : "Switch to New");
         state.set(curr == State.LEGACY ? State.NEW : State.LEGACY);
     }
 

+ 21 - 23
demo/src/main/resources/io/github/palexdev/materialfx/demo/CheckBoxesDemo.fxml

@@ -8,7 +8,7 @@
 <?import javafx.scene.paint.Stop?>
 <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
            prefWidth="600.0" stylesheets="@css/CheckBoxesDemo.css" xmlns="http://javafx.com/javafx/16">
-    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Checkboxes color" StackPane.alignment="TOP_CENTER">
+    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Checkboxes" StackPane.alignment="TOP_CENTER">
         <StackPane.margin>
             <Insets top="20.0" />
         </StackPane.margin>
@@ -48,32 +48,30 @@
     <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Checkboxes Mark Types" />
     <GridPane hgap="25.0" maxHeight="-Infinity" maxWidth="-Infinity" vgap="10.0">
         <columnConstraints>
-            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
-            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
-            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
-            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
+            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
+            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
+            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
+            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
         </columnConstraints>
         <rowConstraints>
-            <RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
-            <RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
-            <RowConstraints minHeight="10.0" vgrow="SOMETIMES"/>
+            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
+            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
+            <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
         </rowConstraints>
         <StackPane.margin>
-            <Insets top="180.0"/>
+            <Insets top="180.0" />
         </StackPane.margin>
-        <MFXCheckbox markType="mfx-caspian-mark" text="Caspian"/>
-        <MFXCheckbox markType="mfx-modena-mark" text="Modena" GridPane.columnIndex="1"/>
-        <MFXCheckbox markType="mfx-variant3-mark" text="Variant 3" GridPane.columnIndex="2"/>
-        <MFXCheckbox markType="mfx-variant4-mark" text="Variant 4" GridPane.columnIndex="3"/>
-        <MFXCheckbox markType="mfx-variant5-mark" text="Variant 5" GridPane.rowIndex="1"/>
-        <MFXCheckbox markType="mfx-variant6-mark" text="Variant 6" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
-        <MFXCheckbox markType="mfx-variant7-mark" text="Variant 7" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
-        <MFXCheckbox markSize="13.0" markType="mfx-variant8-mark" text="Variant 8" GridPane.columnIndex="3"
-                     GridPane.rowIndex="1"/>
-        <MFXCheckbox markType="mfx-variant9-mark" text="Variant 9" GridPane.rowIndex="2"/>
-        <MFXCheckbox markType="mfx-variant10-mark" text="Variant 10" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
-        <MFXCheckbox markType="mfx-variant11-mark" text="Variant 11" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
-        <MFXCheckbox markSize="9.0" markType="mfx-variant12-mark" text="Variant 12" GridPane.columnIndex="3"
-                     GridPane.rowIndex="2"/>
+        <MFXCheckbox markType="mfx-caspian-mark" text="Caspian" />
+        <MFXCheckbox markType="mfx-modena-mark" text="Modena" GridPane.columnIndex="1" />
+        <MFXCheckbox markType="mfx-variant3-mark" text="Variant 3" GridPane.columnIndex="2" />
+        <MFXCheckbox markType="mfx-variant4-mark" text="Variant 4" GridPane.columnIndex="3" />
+        <MFXCheckbox markType="mfx-variant5-mark" text="Variant 5" GridPane.rowIndex="1" />
+        <MFXCheckbox markType="mfx-variant6-mark" text="Variant 6" GridPane.columnIndex="1" GridPane.rowIndex="1" />
+        <MFXCheckbox markType="mfx-variant7-mark" text="Variant 7" GridPane.columnIndex="2" GridPane.rowIndex="1" />
+        <MFXCheckbox markSize="13.0" markType="mfx-variant8-mark" text="Variant 8" GridPane.columnIndex="3" GridPane.rowIndex="1" />
+        <MFXCheckbox markType="mfx-variant9-mark" text="Variant 9" GridPane.rowIndex="2" />
+        <MFXCheckbox markType="mfx-variant10-mark" text="Variant 10" GridPane.columnIndex="1" GridPane.rowIndex="2" />
+        <MFXCheckbox markType="mfx-variant11-mark" text="Variant 11" GridPane.columnIndex="2" GridPane.rowIndex="2" />
+        <MFXCheckbox markSize="9.0" markType="mfx-variant12-mark" text="Variant 12" GridPane.columnIndex="3" GridPane.rowIndex="2" />
     </GridPane>
 </StackPane>

+ 2 - 2
demo/src/main/resources/io/github/palexdev/materialfx/demo/DatePickersDemo.fxml

@@ -4,7 +4,7 @@
 <?import javafx.geometry.*?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.layout.*?>
-<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/DatePickersDemo.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.DatePickersDemoController">
+<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/DatePickersDemo.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.DatePickersDemoController">
    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Date Pickers" StackPane.alignment="TOP_CENTER">
       <StackPane.margin>
          <Insets top="20.0" />
@@ -15,7 +15,7 @@
          <Insets right="300.0" top="70.0" />
       </StackPane.margin>
    </MFXDatePicker>
-   <MFXDatePicker closeOnDaySelected="false" colorText="true" StackPane.alignment="TOP_CENTER">
+   <MFXDatePicker closeOnDaySelected="false" closeOnEnter="true" colorText="true" StackPane.alignment="TOP_CENTER">
       <StackPane.margin>
          <Insets top="70.0" />
       </StackPane.margin>

+ 84 - 73
demo/src/main/resources/io/github/palexdev/materialfx/demo/ListViewsDemo.fxml

@@ -4,76 +4,87 @@
 <?import javafx.geometry.*?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
-<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="920.0" stylesheets="@css/ListViewsDemo.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.ListViewDemoController">
-    <padding>
-        <Insets left="20.0" right="20.0" />
-    </padding>
-    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="ListViews" StackPane.alignment="TOP_CENTER">
-        <StackPane.margin>
-            <Insets top="20.0" />
-        </StackPane.margin>
-    </Label>
-    <HBox fx:id="legacyBox" alignment="TOP_CENTER" maxHeight="-Infinity" prefHeight="250.0" prefWidth="680.0" spacing="20.0" visible="false">
-        <StackPane.margin>
-            <Insets top="40.0" />
-        </StackPane.margin>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="130.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Standard" />
-            <MFXListView fx:id="stringView" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="200.0" prefWidth="120.0" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="160.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Labels" />
-            <MFXListView fx:id="labelView" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="200.0" prefWidth="150.0" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="265.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="HBoxes" />
-            <MFXListView fx:id="hBoxView" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="200.0" prefWidth="265.0" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="135.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="125.0" text="Customized and CSS" />
-            <MFXListView id="customView" fx:id="cssView" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="200.0" prefWidth="110.0" stylesheets="@css/ListViewsDemo.css" />
-        </VBox>
-    </HBox>
-    <HBox fx:id="newBox" alignment="TOP_CENTER" maxHeight="-Infinity" prefHeight="250.0" prefWidth="680.0" spacing="20.0">
-        <StackPane.margin>
-            <Insets top="40.0" />
-        </StackPane.margin>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="130.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Standard" />
-            <MFXFlowlessListView fx:id="stringViewNew" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="160.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Labels" />
-            <MFXFlowlessListView fx:id="labelViewNew" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="265.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="HBoxes" />
-            <MFXFlowlessListView fx:id="hBoxViewNew" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="135.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="125.0" text="CheckListView" />
-            <MFXFlowlessCheckListView fx:id="checkList" />
-        </VBox>
-        <VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="250.0" prefWidth="135.0" spacing="10.0">
-            <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="125.0" text="Customized and CSS" />
-            <MFXFlowlessListView id="customViewNew" fx:id="cssViewNew" />
-        </VBox>
-    </HBox>
-    <VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="90.0" prefWidth="128.0" spacing="10.0" StackPane.alignment="BOTTOM_RIGHT">
-        <StackPane.margin>
-            <Insets bottom="5.0" />
-        </StackPane.margin>
-        <MFXButton fx:id="depthButton" prefWidth="70.0" text="3D" />
-        <MFXButton fx:id="colorsButton" text="Change bars color" />
-    </VBox>
-   <MFXButton fx:id="switchButton" buttonType="RAISED" prefWidth="120.0" text="Switch to Legacy" StackPane.alignment="TOP_CENTER">
-      <StackPane.margin>
-         <Insets top="75.0" />
-      </StackPane.margin>
-   </MFXButton>
-   <Label text="Multiple Selection On" StackPane.alignment="TOP_LEFT">
-      <StackPane.margin>
-         <Insets left="6.0" top="115.0" />
-      </StackPane.margin>
-   </Label>
-</StackPane>
+<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="920.0" stylesheets="@css/ListViewsDemo.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.ListViewsDemoController">
+   <Label id="customLabel" alignment="CENTER" layoutX="327.0" layoutY="14.0" prefHeight="26.0" prefWidth="266.0" text="ListViews" AnchorPane.leftAnchor="327.0" AnchorPane.rightAnchor="327.0" AnchorPane.topAnchor="15.0" />
+   <HBox fx:id="legacyBox" alignment="CENTER" layoutX="5.0" layoutY="68.0" spacing="10.0" visible="false" AnchorPane.bottomAnchor="100.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="60.0">
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Standard">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXListView fx:id="stringView" depthLevel="LEVEL0" prefHeight="200.0" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Labels">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXListView fx:id="labelView" depthLevel="LEVEL0" prefHeight="200.0" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="HBoxes">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXListView fx:id="hBoxView" depthLevel="LEVEL0" prefHeight="200.0" prefWidth="250.0" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Customized and CSS">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXListView id="customView" fx:id="cssView" depthLevel="LEVEL0" prefHeight="200.0" />
+      </VBox>
+   </HBox>
+   <HBox fx:id="newBox" alignment="CENTER" layoutX="-5.0" layoutY="58.0" spacing="10.0" AnchorPane.bottomAnchor="100.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="60.0">
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Standard">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXFlowlessListView fx:id="stringViewNew" prefHeight="220.0" prefWidth="150.0" />
+         <Label fx:id="mulLabel" text="Multiple Selection On" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Labels">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXFlowlessListView fx:id="labelViewNew" prefHeight="220.0" prefWidth="150.0" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="HBoxes">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXFlowlessListView fx:id="hBoxViewNew" prefHeight="220.0" prefWidth="250.0" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="CheckListView">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXFlowlessCheckListView fx:id="checkList" prefHeight="220.0" prefWidth="150.0" />
+         <MFXCheckbox fx:id="allowSelection" markType="mfx-variant7-mark" text="Allow Selection" />
+      </VBox>
+      <VBox alignment="TOP_CENTER" spacing="10.0">
+         <Label id="label" alignment="CENTER" prefHeight="25.0" prefWidth="110.0" text="Customized and CSS">
+            <VBox.margin>
+               <Insets top="10.0" />
+            </VBox.margin>
+         </Label>
+         <MFXFlowlessListView id="customViewNew" fx:id="cssViewNew" prefHeight="220.0" prefWidth="150.0" />
+      </VBox>
+   </HBox>
+   <MFXButton fx:id="swapButton" buttonType="RAISED" depthLevel="LEVEL1" layoutX="385.0" layoutY="461.0" prefWidth="150.0" text="Swap" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="385.0" AnchorPane.rightAnchor="385.0" />
+   <MFXButton fx:id="depthButton" buttonType="RAISED" depthLevel="LEVEL1" layoutX="774.0" layoutY="440.0" text="3D On/Off" AnchorPane.bottomAnchor="50.0" />
+   <MFXButton fx:id="colorsButton" buttonType="RAISED" depthLevel="LEVEL1" layoutX="753.0" layoutY="475.0" text="Change Bar Colors" AnchorPane.bottomAnchor="10.0" />
+</AnchorPane>

+ 1 - 1
demo/src/main/resources/io/github/palexdev/materialfx/demo/TextFieldsDemo.fxml

@@ -29,7 +29,7 @@
       <MFXCheckbox fx:id="checkbox" checkedColor="#00e240" markSize="9.0" markType="mfx-variant9-mark" text="CheckBox Validation" />
       <MFXDatePicker fx:id="picker" colorText="true" lineColor="#00c133b2" maxHeight="-Infinity" maxWidth="-Infinity" pickerColor="#00c133" prefHeight="30.0" prefWidth="120.0" />
    </HBox>
-   <Label id="customLabel" alignment="CENTER" layoutX="167.0" layoutY="235.0" prefHeight="26.0" prefWidth="266.0" text="Customization" AnchorPane.leftAnchor="167.0" AnchorPane.rightAnchor="167.0" AnchorPane.topAnchor="260.0" />
+   <Label id="customLabel" alignment="CENTER" layoutX="167.0" layoutY="235.0" prefHeight="26.0" prefWidth="266.0" text="PasswordFields" AnchorPane.leftAnchor="167.0" AnchorPane.rightAnchor="167.0" AnchorPane.topAnchor="260.0" />
    <HBox alignment="CENTER" layoutX="120.0" layoutY="266.0" prefWidth="200.0" spacing="60.0" AnchorPane.leftAnchor="20.0" AnchorPane.rightAnchor="20.0" AnchorPane.topAnchor="290.0">
       <padding>
          <Insets bottom="20.0" top="20.0" />

+ 6 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXComboBox.java

@@ -19,6 +19,7 @@
 package io.github.palexdev.materialfx.controls;
 
 import io.github.palexdev.materialfx.MFXResourcesLoader;
+import io.github.palexdev.materialfx.beans.MFXSnapshotWrapper;
 import io.github.palexdev.materialfx.controls.enums.DialogType;
 import io.github.palexdev.materialfx.font.MFXFontIcon;
 import io.github.palexdev.materialfx.selection.ComboSelectionModelMock;
@@ -47,6 +48,11 @@ import static io.github.palexdev.materialfx.controls.enums.Styles.ComboBoxStyles
  * Extends {@code Control} and provides a new skin since it is built from scratch.
  * <p>
  * Side note: unlike JavaFX's one this is NOT editable.
+ * <p></p>
+ * <b>
+ * Warning: the selection via context menu won't work properly if the combo box data type is a Node.
+ * This is because {@link MFXSnapshotWrapper#getGraphic()} cannot take a screenshot of it since the popup is hidden.
+ * </b>
  *
  * @param <T> The type of the value that has been selected
  * @see ComboSelectionModelMock

+ 46 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXDatePicker.java

@@ -31,6 +31,8 @@ import javafx.geometry.*;
 import javafx.scene.control.DatePicker;
 import javafx.scene.control.Label;
 import javafx.scene.control.PopupControl;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.StackPane;
 import javafx.scene.layout.VBox;
@@ -172,6 +174,10 @@ public class MFXDatePicker extends VBox {
         });
 
         datePickerContent.currentDateProperty().addListener((observable, oldValue, newValue) -> {
+            if (newValue == null) {
+                return;
+            }
+
             datePicker.setValue(newValue);
             value.setText(newValue.format(datePickerContent.getDateFormatter()));
         });
@@ -181,6 +187,10 @@ public class MFXDatePicker extends VBox {
                 return;
             }
 
+            if (newValue == null || oldValue == null) {
+                return;
+            }
+
             if (oldValue.getYear() == newValue.getYear() ||
                     oldValue.getMonth() == newValue.getMonth()) {
                 if (oldValue.getDayOfMonth() != newValue.getDayOfMonth()) {
@@ -242,6 +252,12 @@ public class MFXDatePicker extends VBox {
                 calendar.setColor(getPickerColor());
             }
         });
+
+        popup.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
+            if (event.getCode() == KeyCode.ENTER && isCloseOnEnter()) {
+                popup.hide();
+            }
+        });
     }
 
     public MFXDatePickerContent getContent() {
@@ -305,6 +321,13 @@ public class MFXDatePicker extends VBox {
             true
     );
 
+    private final StyleableBooleanProperty closeOnEnter = new SimpleStyleableBooleanProperty(
+            StyleableProperties.CLOSE_ON_ENTER,
+            this,
+            "closeOnEnter",
+            false
+    );
+
     private final StyleableBooleanProperty animateCalendar = new SimpleStyleableBooleanProperty(
             StyleableProperties.ANIMATE_CALENDAR,
             this,
@@ -402,6 +425,21 @@ public class MFXDatePicker extends VBox {
         this.closeOnDaySelected.set(closeOnDaySelected);
     }
 
+    public boolean isCloseOnEnter() {
+        return closeOnEnter.get();
+    }
+
+    /**
+     * Specifies if the date picker popup should close on ENTER pressed.
+     */
+    public StyleableBooleanProperty closeOnEnterProperty() {
+        return closeOnEnter;
+    }
+
+    public void setCloseOnEnter(boolean closeOnEnter) {
+        this.closeOnEnter.set(closeOnEnter);
+    }
+
     public boolean isAnimateCalendar() {
         return animateCalendar.get();
     }
@@ -466,6 +504,14 @@ public class MFXDatePicker extends VBox {
                         true
                 );
 
+        private static final CssMetaData<MFXDatePicker, Boolean> CLOSE_ON_ENTER =
+                FACTORY.createBooleanCssMetaData(
+                        "-mfx-close-on-enter",
+                        MFXDatePicker::closeOnEnterProperty,
+                        false
+                );
+
+
         private static final CssMetaData<MFXDatePicker, Boolean> ANIMATE_CALENDAR =
                 FACTORY.createBooleanCssMetaData(
                         "-mfx-animate-calendar",

+ 16 - 1
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTextField.java

@@ -220,14 +220,29 @@ public class MFXTextField extends TextField implements Validated<MFXDialogValida
                 .setAccelerator("Ctrl + A")
                 .setAction(event -> selectAll());
 
+        MFXContextMenuItem redo = new MFXContextMenuItem()
+                .setIcon(new MFXFontIcon("mfx-redo", 12))
+                .setText("Redo")
+                .setAccelerator("Ctrl + Y")
+                .setAction(event -> redo());
+
+        MFXContextMenuItem undo = new MFXContextMenuItem()
+                .setIcon(new MFXFontIcon("mfx-undo", 12))
+                .setText("Undo")
+                .setAccelerator("Ctrl + Z")
+                .setAction(event -> undo());
+
+
         setMFXContextMenu(
                 MFXContextMenu.Builder.build(this)
                         .addMenuItem(copy)
                         .addMenuItem(cut)
                         .addMenuItem(paste)
                         .addMenuItem(delete)
-                        .addSeparator()
                         .addMenuItem(selectAll)
+                        .addSeparator()
+                        .addMenuItem(redo)
+                        .addMenuItem(undo)
                         .install()
         );
     }

+ 3 - 2
materialfx/src/main/java/io/github/palexdev/materialfx/controls/base/AbstractMFXFlowlessListCell.java

@@ -46,10 +46,10 @@ public abstract class AbstractMFXFlowlessListCell<T> extends HBox implements Cel
     protected final DoubleProperty fixedCellHeight = new SimpleDoubleProperty();
 
     private final ReadOnlyBooleanWrapper selected = new ReadOnlyBooleanWrapper();
-    private final ReadOnlyBooleanWrapper empty = new ReadOnlyBooleanWrapper();
     protected final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected");
-    protected final PseudoClass EMPTY_PSEUDO_CLASS = PseudoClass.getPseudoClass("empty");
 
+    private final ReadOnlyBooleanWrapper empty = new ReadOnlyBooleanWrapper();
+    protected final PseudoClass EMPTY_PSEUDO_CLASS = PseudoClass.getPseudoClass("empty");
     protected final BooleanProperty showEmpty = new SimpleBooleanProperty(false);
 
     //================================================================================
@@ -109,6 +109,7 @@ public abstract class AbstractMFXFlowlessListCell<T> extends HBox implements Cel
                 }
             }
         });
+
         addEventFilter(MouseEvent.MOUSE_PRESSED, this::updateSelection);
         index.addListener(invalidated -> afterUpdateIndex());
         getSelectionModel().selectedItemsProperty().addListener((InvalidationListener) invalidated -> setSelected(getSelectionModel().containSelected(getIndex())));

+ 39 - 22
materialfx/src/main/java/io/github/palexdev/materialfx/controls/cell/MFXFlowlessCheckListCell.java

@@ -26,6 +26,8 @@ import io.github.palexdev.materialfx.effects.ripple.MFXCircleRippleGenerator;
 import io.github.palexdev.materialfx.effects.ripple.RipplePosition;
 import io.github.palexdev.materialfx.selection.ListCheckModel;
 import io.github.palexdev.materialfx.selection.base.IListCheckModel;
+import io.github.palexdev.materialfx.selection.base.IListSelectionModel;
+import io.github.palexdev.materialfx.utils.NodeUtils;
 import javafx.beans.property.ReadOnlyBooleanProperty;
 import javafx.beans.property.ReadOnlyBooleanWrapper;
 import javafx.css.PseudoClass;
@@ -53,8 +55,6 @@ public class MFXFlowlessCheckListCell<T> extends AbstractMFXFlowlessListCell<T>
     private final ReadOnlyBooleanWrapper checked = new ReadOnlyBooleanWrapper();
     protected static final PseudoClass CHECKED_PSEUDO_CLASS = PseudoClass.getPseudoClass("checked");
 
-    private boolean clearSelectionOnCheck = true;
-
     //================================================================================
     // Constructors
     //================================================================================
@@ -99,17 +99,20 @@ public class MFXFlowlessCheckListCell<T> extends AbstractMFXFlowlessListCell<T>
      * Sets the following additional behaviors:
      * <p>
      * - Binds the checked property to the selected property of the combo box.<p>
-     * - Clears the selection (if {@link #clearSelectionOnCheck} is true), updates the
-     * checked PseudoClass state and calls {@link #updateCheck()} when the checked property changes.
+     * - Adds a listener to {@link IListCheckModel#allowsSelectionProperty()} to properly handle selection.
      */
     @Override
     protected void setBehavior() {
         super.setBehavior();
-        checked.bind(checkbox.selectedProperty());
-        checked.addListener(invalidated -> {
-            if (clearSelectionOnCheck) {
+
+        getSelectionModel().allowsSelectionProperty().addListener((observable, oldValue, newValue) -> {
+            if (!newValue) {
                 getSelectionModel().clearSelection();
             }
+        });
+
+        checked.bind(checkbox.selectedProperty());
+        checked.addListener(invalidated -> {
             pseudoClassStateChanged(CHECKED_PSEUDO_CLASS, checked.get());
             updateCheck();
         });
@@ -135,6 +138,35 @@ public class MFXFlowlessCheckListCell<T> extends AbstractMFXFlowlessListCell<T>
         }
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * <p></p>
+     * Overridden to manage the selection properly according to {@link IListCheckModel#allowsSelectionProperty()}
+     */
+    @Override
+    protected void updateSelection(MouseEvent mouseEvent) {
+        if (!getSelectionModel().allowsSelection()) {
+            return;
+        }
+
+        if (NodeUtils.inHierarchy(mouseEvent.getPickResult().getIntersectedNode(), checkbox)) {
+            getSelectionModel().clearSelection();
+            return;
+        }
+
+        IListSelectionModel<T> selectionModel = getSelectionModel();
+        setSelected(!isSelected());
+
+        boolean selected = isSelected();
+        int index = getIndex();
+        if (!selected && selectionModel.containSelected(index)) {
+            selectionModel.clearSelectedItem(index);
+        } else if (selected && !selectionModel.containSelected(index)) {
+            selectionModel.select(index, getData(), mouseEvent);
+        }
+    }
+
     /**
      * Inherited doc:
      * <p>
@@ -167,21 +199,6 @@ public class MFXFlowlessCheckListCell<T> extends AbstractMFXFlowlessListCell<T>
         }
     }
 
-    public boolean isClearSelectionOnCheck() {
-        return clearSelectionOnCheck;
-    }
-
-    /**
-     * Sets the behavior of the cell when an item is checked.
-     * <p>
-     * Selection and check are handled separately, this means that you can check and select items
-     * at the same time. By setting this flag to true when an item is checked the selection
-     * will be cleared.
-     */
-    public void setClearSelectionOnCheck(boolean clearSelectionOnCheck) {
-        this.clearSelectionOnCheck = clearSelectionOnCheck;
-    }
-
     public boolean isChecked() {
         return checked.get();
     }

+ 29 - 27
materialfx/src/main/java/io/github/palexdev/materialfx/font/FontResources.java

@@ -19,7 +19,7 @@
 package io.github.palexdev.materialfx.font;
 
 /**
- * Enumerator class for MaterialFX font resources. (Count: 79)
+ * Enumerator class for MaterialFX font resources. (Count: 81)
  */
 public enum FontResources {
     ANGLE_DOWN("mfx-angle-down", '\uE900'),
@@ -75,32 +75,34 @@ public enum FontResources {
     MINUS_CIRCLE("mfx-minus-circle", '\uE932'),
     MODENA_MARK("mfx-modena-mark", '\uE933'),
     NEXT("mfx-next", '\uE934'),
-    RESTORE("mfx-restore", '\uE935'),
-    SEARCH("mfx-search", '\uE936'),
-    SEARCH_PLUS("mfx-search-plus", '\uE937'),
-    SELECT_ALL("mfx-select-all", '\uE938'),
-    SLIDERS("mfx-sliders", '\uE939'),
-    STEP_BACKWARD("mfx-step-backward", '\uE93A'),
-    STEP_FORWARD("mfx-step-forward", '\uE93B'),
-    SYNC("mfx-sync", '\uE93C'),
-    SYNC_LIGHT("mfx-sync-light", '\uE93D'),
-    USER("mfx-user", '\uE93E'),
-    USERS("mfx-users", '\uE93F'),
-    VARIANT10_MARK("mfx-variant10-mark", '\uE940'),
-    VARIANT11_MARK("mfx-variant11-mark", '\uE941'),
-    VARIANT12_MARK("mfx-variant12-mark", '\uE942'),
-    VARIANT3_MARK("mfx-variant3-mark", '\uE943'),
-    VARIANT4_MARK("mfx-variant4-mark", '\uE944'),
-    VARIANT5_MARK("mfx-variant5-mark", '\uE945'),
-    VARIANT6_MARK("mfx-variant6-mark", '\uE946'),
-    VARIANT7_MARK("mfx-variant7-mark", '\uE947'),
-    VARIANT8_MARK("mfx-variant8-mark", '\uE948'),
-    VARIANT9_MARK("mfx-variant9-mark", '\uE949'),
-    X("mfx-x", '\uE94A'),
-    X_ALT("mfx-x-alt", '\uE94B'),
-    X_CIRCLE("mfx-x-circle", '\uE94C'),
-    X_CIRCLE_LIGHT("mfx-x-circle-light", '\uE94D'),
-    X_LIGHT("mfx-x-light", '\uE94E'),
+    REDO("mfx-redo", '\uE935'),
+    RESTORE("mfx-restore", '\uE936'),
+    SEARCH("mfx-search", '\uE937'),
+    SEARCH_PLUS("mfx-search-plus", '\uE938'),
+    SELECT_ALL("mfx-select-all", '\uE939'),
+    SLIDERS("mfx-sliders", '\uE93A'),
+    STEP_BACKWARD("mfx-step-backward", '\uE93B'),
+    STEP_FORWARD("mfx-step-forward", '\uE93C'),
+    SYNC("mfx-sync", '\uE93D'),
+    SYNC_LIGHT("mfx-sync-light", '\uE93E'),
+    UNDO("mfx-undo", '\uE93F'),
+    USER("mfx-user", '\uE940'),
+    USERS("mfx-users", '\uE941'),
+    VARIANT10_MARK("mfx-variant10-mark", '\uE942'),
+    VARIANT11_MARK("mfx-variant11-mark", '\uE943'),
+    VARIANT12_MARK("mfx-variant12-mark", '\uE944'),
+    VARIANT3_MARK("mfx-variant3-mark", '\uE945'),
+    VARIANT4_MARK("mfx-variant4-mark", '\uE946'),
+    VARIANT5_MARK("mfx-variant5-mark", '\uE947'),
+    VARIANT6_MARK("mfx-variant6-mark", '\uE948'),
+    VARIANT7_MARK("mfx-variant7-mark", '\uE949'),
+    VARIANT8_MARK("mfx-variant8-mark", '\uE94A'),
+    VARIANT9_MARK("mfx-variant9-mark", '\uE94B'),
+    X("mfx-x", '\uE94C'),
+    X_ALT("mfx-x-alt", '\uE94D'),
+    X_CIRCLE("mfx-x-circle", '\uE94E'),
+    X_CIRCLE_LIGHT("mfx-x-circle-light", '\uE94F'),
+    X_LIGHT("mfx-x-light", '\uE950'),
     ;
 
     public static FontResources findByDescription(String description) {

+ 25 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/selection/ListCheckModel.java

@@ -19,7 +19,9 @@
 package io.github.palexdev.materialfx.selection;
 
 import io.github.palexdev.materialfx.selection.base.IListCheckModel;
+import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.MapProperty;
+import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.property.SimpleMapProperty;
 
 import java.util.List;
@@ -35,6 +37,7 @@ public class ListCheckModel<T> extends ListSelectionModel<T> implements IListChe
     // Properties
     //================================================================================
     private final MapProperty<Integer, T> checkedItems = new SimpleMapProperty<>(getMap());
+    private final BooleanProperty allowsSelection = new SimpleBooleanProperty(false);
 
     //================================================================================
     // Override Methods
@@ -136,4 +139,26 @@ public class ListCheckModel<T> extends ListSelectionModel<T> implements IListChe
     public MapProperty<Integer, T> checkedItemsProperty() {
         return checkedItems;
     }
+
+    @Override
+    public boolean allowsSelection() {
+        return allowsSelection.get();
+    }
+
+    /**
+     * Specifies if the check list also should allow the selection of cells.
+     * <p></p>
+     * Note that even if this is true selection will be cleared when pressing on a checkbox.
+     * <p>
+     * So, to use both you should first check and then select.
+     */
+    @Override
+    public BooleanProperty allowsSelectionProperty() {
+        return allowsSelection;
+    }
+
+    @Override
+    public void setAllowsSelection(boolean allowsSelection) {
+        this.allowsSelection.set(allowsSelection);
+    }
 }

+ 4 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/selection/base/IListCheckModel.java

@@ -18,6 +18,7 @@
 
 package io.github.palexdev.materialfx.selection.base;
 
+import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.MapProperty;
 
 import java.util.List;
@@ -34,4 +35,7 @@ public interface IListCheckModel<T> extends IListSelectionModel<T> {
     T getCheckedItem(int index);
     List<T> getCheckedItems();
     MapProperty<Integer, T> checkedItemsProperty();
+    boolean allowsSelection();
+    BooleanProperty allowsSelectionProperty();
+    void setAllowsSelection(boolean allowsSelection);
 }

+ 6 - 2
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXDatePickerContent.java

@@ -434,12 +434,16 @@ public class MFXDatePickerContent extends VBox {
         lastSelectedDayCell.addListener((observable, oldValue, newValue) -> {
             LocalDate date = getCurrentDate().withDayOfMonth(Integer.parseInt(newValue.getText()));
             if (date.equals(getCurrentDate())) {
-                setCurrentDate(LocalDate.EPOCH);
+                setCurrentDate(null);
             }
             setCurrentDate(date);
         });
 
-        currentDate.addListener((observable, oldValue, newValue) -> selectedDate.setText(newValue.format(getDateFormatter())));
+        currentDate.addListener((observable, oldValue, newValue) -> {
+            if (newValue != null) {
+                selectedDate.setText(newValue.format(getDateFormatter()));
+            }
+        });
 
         dateFormatter.addListener((observable, oldValue, newValue) -> selectedDate.setText(getCurrentDate().format(newValue)));
     }

+ 2 - 3
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXFilterComboBoxSkin.java

@@ -105,7 +105,8 @@ public class MFXFilterComboBoxSkin<T> extends SkinBase<MFXFilterComboBox<T>> {
         focusedLine.setScaleX(0.0);
         focusedLine.setSmooth(true);
 
-        MFXFontIcon warnIcon = new MFXFontIcon("mfx-exclamation-triangle", Color.RED);
+        MFXFontIcon warnIcon = new MFXFontIcon("mfx-exclamation-triangle", Color.web("#EF6E6B"));
+        warnIcon.setId("validationIcon");
         MFXIconWrapper warnWrapper = new MFXIconWrapper(warnIcon, 10);
 
         validate = new Label();
@@ -530,8 +531,6 @@ public class MFXFilterComboBoxSkin<T> extends SkinBase<MFXFilterComboBox<T>> {
         searchField.setPromptText("Search...");
         searchField.setId("search-field");
         searchField.getStylesheets().setAll(comboBox.getUserAgentStylesheet());
-        searchField.setUnfocusedLineColor(Color.TRANSPARENT);
-        searchField.setLineColor(Color.TRANSPARENT);
         searchField.setFocusTraversable(false);
 
         searchField.textProperty().addListener((observable, oldValue, newValue) -> {

+ 39 - 19
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXLabelSkin.java

@@ -25,6 +25,7 @@ import io.github.palexdev.materialfx.controls.factories.MFXAnimationFactory;
 import io.github.palexdev.materialfx.utils.LabelUtils;
 import javafx.animation.ScaleTransition;
 import javafx.beans.binding.Bindings;
+import javafx.beans.value.ChangeListener;
 import javafx.event.EventHandler;
 import javafx.geometry.Insets;
 import javafx.scene.Node;
@@ -35,7 +36,6 @@ import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.Region;
-import javafx.scene.paint.Color;
 import javafx.scene.shape.Line;
 import javafx.util.Duration;
 
@@ -73,6 +73,8 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
         }
     };
 
+    private ChangeListener<Boolean> editorFocusListener;
+
     //================================================================================
     // Constructors
     //================================================================================
@@ -204,6 +206,13 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
             }
         });
 
+        label.editorFocusedProperty().addListener((observable, oldValue, newValue) -> {
+            if (label.isFocused()) {
+                return;
+            }
+            buildAndPlayAnimation(newValue);
+        });
+
         label.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
             if (label.isAnimateLines() && focusedLine.getScaleX() != 1.0) {
                 buildAndPlayAnimation(true);
@@ -254,33 +263,29 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
         label.editorFocusedProperty().bind(textField.focusedProperty());
         textField.setId("editor-node");
         textField.setManaged(false);
-        textField.setUnfocusedLineColor(Color.TRANSPARENT);
-        textField.setLineColor(Color.TRANSPARENT);
+        textField.getStylesheets().setAll(label.getUserAgentStylesheet());
 
         textField.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
             if (event.getCode() == KeyCode.ENTER) {
-                label.setText(textField.getText());
-                container.getChildren().remove(textField);
-                textNode.setVisible(true);
-                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
+                removeEditor(textField);
                 label.requestFocus();
             } else if (event.getCode() == KeyCode.ESCAPE) {
-                container.getChildren().remove(textField);
-                textNode.setVisible(true);
-                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
+                removeEditor(textField);
                 label.requestFocus();
             }
         });
 
-        textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
-            if (!newValue) {
-                label.setText(textField.getText());
-                container.getChildren().remove(textField);
-                textNode.setVisible(true);
-                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
-                label.requestFocus();
-            }
-        });
+        if (editorFocusListener == null) {
+            editorFocusListener = (observable, oldValue, newValue) -> {
+                if (!newValue) {
+                    label.setText(textField.getText());
+                    container.getChildren().remove(textField);
+                    textNode.setVisible(true);
+                    textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
+                }
+            };
+        }
+        textField.focusedProperty().addListener(editorFocusListener);
 
         container.getChildren().add(textField);
         computeEditorPosition(textField);
@@ -324,6 +329,21 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
         return editor != null;
     }
 
+    /**
+     * Removes the editor and sets its text as the label's text.
+     */
+    private void removeEditor(MFXTextField textField) {
+        MFXLabel label = getSkinnable();
+
+        textNode.setVisible(false);
+        label.setText(textField.getText());
+
+        label.editorFocusedProperty().unbind();
+        textField.focusedProperty().removeListener(editorFocusListener);
+
+        container.getChildren().remove(textField);
+    }
+
     //================================================================================
     // Override Methods
     //================================================================================

+ 18 - 1
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTextFieldSkin.java

@@ -28,8 +28,10 @@ import javafx.animation.ScaleTransition;
 import javafx.beans.binding.Bindings;
 import javafx.scene.Cursor;
 import javafx.scene.Node;
+import javafx.scene.control.IndexRange;
 import javafx.scene.control.Label;
 import javafx.scene.control.skin.TextFieldSkin;
+import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.paint.Color;
 import javafx.scene.shape.Line;
@@ -56,6 +58,7 @@ public class MFXTextFieldSkin extends TextFieldSkin {
     private final Line unfocusedLine;
     private final Line focusedLine;
     private final Label validate;
+    private IndexRange prev = null;
 
     //================================================================================
     // Constructors
@@ -124,7 +127,7 @@ public class MFXTextFieldSkin extends TextFieldSkin {
     //================================================================================
 
     /**
-     * Adds listeners for: icon, icon insets, line, focus, disabled and validator properties.
+     * Adds listeners for: selection, icon, icon insets, line, focus, disabled and validator properties.
      * <p>
      * Validator: when the control is not focused, and of course if {@code isValidated} is true,
      * all the conditions in the validator are evaluated and if one is false the {@code validate} label is shown.
@@ -137,6 +140,20 @@ public class MFXTextFieldSkin extends TextFieldSkin {
         MFXTextField textField = (MFXTextField) getSkinnable();
         MFXDialogValidator validator = textField.getValidator();
 
+        textField.selectionProperty().addListener((observable, oldValue, newValue) ->{
+            if (prev == null) {
+                prev = newValue;
+            } else {
+                prev = oldValue;
+            }
+        });
+
+        textField.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
+            if (prev != null && event.getButton() == MouseButton.SECONDARY) {
+                textField.selectRange(prev.getStart(), prev.getEnd());
+            }
+        });
+
         textField.iconProperty().addListener((observable, oldValue, newValue) -> {
             if (newValue == null) {
                 getChildren().remove(oldValue);

+ 10 - 0
materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXFilterComboBox.css

@@ -22,3 +22,13 @@
     -fx-prompt-text-fill: grey;
 }
 
+#search-field .focused-line,
+#search-field .unfocused-line {
+    -fx-stroke: transparent;
+}
+
+#validationIcon {
+    -mfx-color: #EF6E6B;
+}
+
+

+ 6 - 0
materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXLabelStyle1.css

@@ -38,3 +38,9 @@
 .mfx-label:prompt {
     -mfx-text-fill: #A0A0A0;
 }
+
+
+#editor-node .focused-line,
+#editor-node .unfocused-line {
+    -fx-stroke: transparent;
+}

+ 10 - 0
materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXLabelStyle2.css

@@ -39,7 +39,17 @@
     -fx-border-color: -mfx-line-color;
 }
 
+.mfx-label:editor {
+    -fx-border-color: -mfx-line-color;
+}
+
 .mfx-label:prompt {
     -mfx-text-fill: #A0A0A0;
 }
 
+
+#editor-node .focused-line,
+#editor-node .unfocused-line {
+    -fx-stroke: transparent;
+}
+

+ 5 - 0
materialfx/src/main/resources/io/github/palexdev/materialfx/css/MFXLabelStyle3.css

@@ -36,3 +36,8 @@
 .mfx-label:prompt {
     -mfx-text-fill: #A0A0A0;
 }
+
+#editor-node .focused-line,
+#editor-node .unfocused-line {
+    -fx-stroke: transparent;
+}

BIN
materialfx/src/main/resources/io/github/palexdev/materialfx/fonts/MFXResources.ttf