瀏覽代碼

Version 11.6.0
Updated plugins and libraries.
Demo: added previews for tree views and progress spinners.

MFXTreeView and MFXCheckTreeView: added no-arg constructors for usage in SceneBuilder and refactored the control initialization to allow no-arg.
Added bottom padding to root thus fixing selection of bottom items.

SelectionModel: scanTree added condition to check if element is already selected.

mfx-treeview.css: must set viewport background color, otherwise it will appear grey when items are expanded.

Signed-off-by: PAlex404 <alessandro.parisi406@gmail.com>

PAlex404 4 年之前
父節點
當前提交
75f9b11573

+ 18 - 0
.run/Run Tests.run.xml

@@ -0,0 +1,18 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="Run Tests" type="JUnit" factoryName="JUnit">
+    <module name="MaterialFX.demo.test" />
+    <extension name="coverage">
+      <pattern>
+        <option name="PATTERN" value="treeview.*" />
+        <option name="ENABLED" value="true" />
+      </pattern>
+    </extension>
+    <option name="PACKAGE_NAME" value="treeview" />
+    <option name="MAIN_CLASS_NAME" value="treeview.TreeViewTests" />
+    <option name="METHOD_NAME" value="" />
+    <option name="TEST_OBJECT" value="class" />
+    <method v="2">
+      <option name="Make" enabled="true" />
+    </method>
+  </configuration>
+</component>

+ 2 - 2
README.md

@@ -86,7 +86,7 @@ repositories {
 }
 
 dependencies {
-implementation 'io.github.palexdev:materialfx:11.5.6'
+implementation 'io.github.palexdev:materialfx:11.6.0'
 }
 ```
 ###### Maven
@@ -94,7 +94,7 @@ implementation 'io.github.palexdev:materialfx:11.5.6'
 <dependency>
   <groupId>io.github.palexdev</groupId>
   <artifactId>materialfx</artifactId>
-  <version>11.5.6</version>
+  <version>11.6.0</version>
 </dependency>
 ```
 

+ 2 - 2
build.gradle

@@ -4,7 +4,7 @@ plugins {
 }
 
 group 'io.github.palexdev'
-version '11.5.6'
+version '11.6.0'
 
 repositories {
     mavenCentral()
@@ -15,7 +15,7 @@ subprojects {
     apply plugin: 'org.openjfx.javafxplugin'
 
     javafx {
-        version = "14.0.2.1"
+        version = "15.0.1"
         modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.web' ]
     }
 }

+ 5 - 5
demo/build.gradle

@@ -1,6 +1,6 @@
 plugins {
     id 'application'
-    id 'org.beryx.jlink' version '2.21.3'
+    id 'org.beryx.jlink' version '2.23.3'
 }
 
 repositories {
@@ -10,13 +10,13 @@ repositories {
 
 dependencies {
     testCompile "org.testfx:testfx-core:4.0.16-alpha"
-    testCompile "junit:junit:4.13-beta-3"
+    testCompile "junit:junit:4.13.1"
     testCompile "org.testfx:testfx-junit:4.0.16-alpha"
 
     implementation "fr.brouillard.oss:cssfx:11.4.0"
-    implementation 'org.kordamp.ikonli:ikonli-core:11.5.0'
-    implementation 'org.kordamp.ikonli:ikonli-javafx:11.5.0'
-    implementation 'org.kordamp.ikonli:ikonli-fontawesome5-pack:11.5.0'
+    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 project(':materialfx')
 }
 

+ 6 - 4
demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/DemoController.java

@@ -132,10 +132,12 @@ public class DemoController implements Initializable {
         vLoader.addItem(4, "DIALOGS", new MFXToggleNode("DIALOGS"), MFXResourcesLoader.load("dialogs_demo.fxml"), controller -> new DialogsController(demoPane));
         vLoader.addItem(5, "LISTVIEWS", new MFXToggleNode("LISTVIEWS"), MFXResourcesLoader.load("listviews_demo.fxml"));
         vLoader.addItem(6, "NOTIFICATIONS", new MFXToggleNode("NOTIFICATIONS"), MFXResourcesLoader.load("notifications_demo.fxml"));
-        vLoader.addItem(7, "RADIOBUTTONS", new MFXToggleNode("RADIOBUTTONS"), MFXResourcesLoader.load("radio_buttons_demo.fxml"));
-        vLoader.addItem(8, "SCROLLPANES", new MFXToggleNode("SCROLLPANES"), MFXResourcesLoader.load("scrollpanes_demo.fxml"));
-        vLoader.addItem(9, "TEXTFIELDS", new MFXToggleNode("TEXTFIELDS"), MFXResourcesLoader.load("textfields_demo.fxml"));
-        vLoader.addItem(10, "TOGGLES", new MFXToggleNode("TOGGLES"), MFXResourcesLoader.load("toggle_buttons_demo.fxml"));
+        vLoader.addItem(7, "PROGRESS_SPINNERS", new MFXToggleNode("PROGRESS_SPINNERS"), MFXResourcesLoader.load("progress_spinners_demo.fxml"));
+        vLoader.addItem(8, "RADIOBUTTONS", new MFXToggleNode("RADIOBUTTONS"), MFXResourcesLoader.load("radio_buttons_demo.fxml"));
+        vLoader.addItem(9, "SCROLLPANES", new MFXToggleNode("SCROLLPANES"), MFXResourcesLoader.load("scrollpanes_demo.fxml"));
+        vLoader.addItem(10, "TEXTFIELDS", new MFXToggleNode("TEXTFIELDS"), MFXResourcesLoader.load("textfields_demo.fxml"));
+        vLoader.addItem(11, "TOGGLES", new MFXToggleNode("TOGGLES"), MFXResourcesLoader.load("toggle_buttons_demo.fxml"));
+        vLoader.addItem(12, "TREEVIEWS", new MFXToggleNode("TREEVIEWS"), MFXResourcesLoader.load("treeviews_demo.fxml"));
         vLoader.setDefault("BUTTONS");
 
         // Others

+ 43 - 0
demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/ProgressSpinnersDemoController.java

@@ -0,0 +1,43 @@
+package io.github.palexdev.materialfx.demo.controllers;
+
+import io.github.palexdev.materialfx.controls.MFXProgressSpinner;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.util.Duration;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+public class ProgressSpinnersDemoController implements Initializable {
+
+    @FXML
+    private MFXProgressSpinner progress1;
+
+    @FXML
+    private MFXProgressSpinner progress2;
+
+    @Override
+    public void initialize(URL location, ResourceBundle resources) {
+        Timeline timeline = new Timeline(
+                new KeyFrame(
+                        Duration.ZERO,
+                        new KeyValue(progress1.progressProperty(), 0),
+                        new KeyValue(progress2.progressProperty(), 0)
+                ),
+                new KeyFrame(
+                        Duration.seconds(0.5),
+                        new KeyValue(progress1.progressProperty(), 0.5)
+                ),
+                new KeyFrame(
+                        Duration.seconds(2),
+                        new KeyValue(progress1.progressProperty(), 1),
+                        new KeyValue(progress2.progressProperty(), 1)
+                )
+        );
+        timeline.setCycleCount(Timeline.INDEFINITE);
+        timeline.play();
+    }
+}

+ 167 - 0
demo/src/main/java/io/github/palexdev/materialfx/demo/controllers/TreeviewsDemoController.java

@@ -0,0 +1,167 @@
+package io.github.palexdev.materialfx.demo.controllers;
+
+import io.github.palexdev.materialfx.controls.*;
+import io.github.palexdev.materialfx.font.MFXFontIcon;
+import io.github.palexdev.materialfx.utils.ColorUtils;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.geometry.Pos;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.text.Text;
+
+import java.net.URL;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class TreeviewsDemoController implements Initializable {
+
+    @FXML
+    private MFXTreeView<String> treeView;
+
+    @FXML
+    private MFXTreeView<HBox> treeViewHide;
+
+    @FXML
+    private MFXCheckTreeView<String> checkTreeView;
+
+    @FXML
+    private Text text1;
+
+    @FXML
+    private Text text2;
+
+    @FXML
+    private Text text3;
+
+    @Override
+    public void initialize(URL location, ResourceBundle resources) {
+        treeView.setRoot(createRoot());
+
+        treeViewHide.setRoot(createNodeRoot());
+        treeViewHide.setShowRoot(false);
+
+        checkTreeView.setRoot(createCheckRoot());
+
+        MFXScrollPane.smoothVScrolling(treeView);
+        MFXScrollPane.smoothVScrolling(treeViewHide);
+        MFXScrollPane.smoothVScrolling(checkTreeView);
+
+        treeView.getSelectionModel().getSelectedItems().addListener(
+                (observable, oldValue, newValue) -> text1.setText("Selected Items Count: " + treeView.getSelectionModel().getSelectedItems().size()));
+        treeViewHide.getSelectionModel().getSelectedItems().addListener(
+                (observable, oldValue, newValue) -> text2.setText("Selected Items Count: " + newValue.size()));
+        checkTreeView.getCheckModel().getCheckedItems().addListener(
+                (observable, oldValue, newValue) -> text3.setText("Checked Items Count: " + newValue.size()));
+    }
+
+    public MFXTreeItem<String> createRoot() {
+        MFXTreeItem<String> root = new MFXTreeItem<>("Tree View Root");
+
+        MFXTreeItem<String> item1 = new MFXTreeItem<>("ITEM1");
+        item1.getItems().addAll(List.of(
+                new MFXTreeItem<>("ITEM1-Sub1"),
+                new MFXTreeItem<>("ITEM1-Sub2")
+                )
+        );
+
+        MFXTreeItem<String> item2 = new MFXTreeItem<>("ITEM2");
+        item2.getItems().addAll(List.of(
+                new MFXTreeItem<>("ITEM2-Sub1"),
+                new MFXTreeItem<>("ITEM2-Sub2"),
+                new MFXTreeItem<>("ITEM2-Sub3"),
+                new MFXTreeItem<>("ITEM2-Sub4")
+                )
+        );
+
+        MFXTreeItem<String> item3 = new MFXTreeItem<>("ITEM3");
+
+        MFXTreeItem<String> item4 = new MFXTreeItem<>("ITEM4");
+        item2.getItems().add(
+                new MFXTreeItem<>("ITEM4-Sub1")
+        );
+
+        MFXTreeItem<String> item5 = new MFXTreeItem<>("ITEM5");
+        item2.getItems().addAll(List.of(
+                new MFXTreeItem<>("ITEM5-Sub1"),
+                new MFXTreeItem<>("ITEM5-Sub2"),
+                new MFXTreeItem<>("ITEM5-Sub3")
+                )
+        );
+
+        root.getItems().addAll(List.of(item1, item2, item3, item4, item5));
+        return root;
+    }
+
+    public MFXTreeItem<HBox> createNodeRoot() {
+        MFXTreeItem<HBox> root = new MFXTreeItem<>(createBox("mfx-google", "Google Root"));
+
+        MFXTreeItem<HBox> item1 = new MFXTreeItem<>(createBox("mfx-google", "ITEM1"));
+        item1.getItems().addAll(List.of(
+                new MFXTreeItem<>(createBox("mfx-google", "ITEM1-Sub1")),
+                new MFXTreeItem<>(createBox("mfx-google", "ITEM1-Sub2"))
+                )
+        );
+
+        MFXTreeItem<HBox> item2 = new MFXTreeItem<>(createBox("mfx-calendar-black", "ITEM2"));
+        item2.getItems().addAll(List.of(
+                new MFXTreeItem<>(createBox("mfx-calendar-black", "ITEM2-Sub1")),
+                new MFXTreeItem<>(createBox("mfx-calendar-black", "ITEM2-Sub2")),
+                new MFXTreeItem<>(createBox("mfx-calendar-black", "ITEM2-Sub3")),
+                new MFXTreeItem<>(createBox("mfx-calendar-black", "ITEM2-Sub4"))
+                )
+        );
+
+        MFXTreeItem<HBox> item3 = new MFXTreeItem<>(createBox("mfx-exclamation-triangle", "ITEM3"));
+
+        MFXTreeItem<HBox> item4 = new MFXTreeItem<>(createBox("mfx-circle", "ITEM4"));
+        item4.getItems().add(
+                new MFXTreeItem<>(createBox("mfx-info-circle", "ITEM4-Sub1"))
+        );
+
+        MFXTreeItem<HBox> item5 = new MFXTreeItem<>(createBox("mfx-circle", "ITEM5"));
+        item5.getItems().addAll(List.of(
+                new MFXTreeItem<>(createBox("mfx-circle", "ITEM5-Sub1")),
+                new MFXTreeItem<>(createBox("mfx-circle", "ITEM5-Sub2")),
+                new MFXTreeItem<>(createBox("mfx-circle", "ITEM5-Sub3"))
+                )
+        );
+
+        root.getItems().addAll(List.of(item1, item2, item3, item4, item5));
+        return root;
+    }
+
+    public MFXCheckTreeItem<String> createCheckRoot() {
+        MFXCheckTreeItem<String> root = new MFXCheckTreeItem<>("ROOT");
+
+        MFXCheckTreeItem<String> i1 = new MFXCheckTreeItem<>("I1");
+        MFXCheckTreeItem<String> i1a = new MFXCheckTreeItem<>("I1A");
+        i1a.getItems().add(new MFXCheckTreeItem<>("I11A"));
+
+        MFXCheckTreeItem<String> i1b = new MFXCheckTreeItem<>("I1B");
+        i1.getItems().addAll(List.of(i1a, i1b));
+
+        MFXCheckTreeItem<String> i2 = new MFXCheckTreeItem<>("I2");
+        MFXCheckTreeItem<String> i2a = new MFXCheckTreeItem<>("I2A");
+        i2.getItems().add(i2a);
+
+        MFXCheckTreeItem<String> i3 = new MFXCheckTreeItem<>("I3");
+        MFXCheckTreeItem<String> i3a = new MFXCheckTreeItem<>("I3A");
+        MFXCheckTreeItem<String> i3b = new MFXCheckTreeItem<>("I3B");
+        i3.getItems().addAll(List.of(i3a, i3b));
+
+        MFXCheckTreeItem<String> i4 = new MFXCheckTreeItem<>("I4");
+        MFXCheckTreeItem<String> i4a = new MFXCheckTreeItem<>("I4A");
+        i4.getItems().add(i4a);
+
+        root.getItems().addAll(List.of(i1, i2, i3, i4));
+        return root;
+    }
+
+    private HBox createBox(String iconDescription, String text) {
+        MFXFontIcon icon = new MFXFontIcon(iconDescription, ColorUtils.getRandomColor());
+        HBox hBox = new HBox(10, icon, new Label(text));
+        hBox.setAlignment(Pos.CENTER_LEFT);
+        return hBox;
+    }
+}

+ 1 - 2
demo/src/main/java/module-info.java

@@ -2,7 +2,7 @@ module MaterialFX.demo.main {
     requires MaterialFX.materialfx.main;
 
     requires fr.brouillard.oss.cssfx;
-    requires org.kordamp.iconli.core;
+    requires org.kordamp.ikonli.core;
     requires org.kordamp.ikonli.javafx;
     requires org.kordamp.ikonli.fontawesome5;
     requires javafx.fxml;
@@ -11,5 +11,4 @@ module MaterialFX.demo.main {
 
     opens io.github.palexdev.materialfx.demo;
     opens io.github.palexdev.materialfx.demo.controllers;
-    exports io.github.palexdev.materialfx.demo;
 }

+ 27 - 0
demo/src/main/resources/io/github/palexdev/materialfx/demo/css/progress_spinners_demo.css

@@ -0,0 +1,27 @@
+.progress1 .text {
+    -fx-fill: green;
+}
+
+.progress1 .arc {
+    -fx-stroke: purple;
+}
+
+.progress2 .text {
+    visibility: false;
+}
+
+.progress2 .arc {
+    -fx-stroke: orange;
+}
+
+#cssSpinner1 {
+    -fx-stroke: #4285f4;
+}
+
+#cssSpinner1 .track {
+    -fx-stroke: #d0d0d0;
+}
+
+#cssSpinner2 .track {
+    -fx-stroke: #ffccc5;
+}

+ 63 - 0
demo/src/main/resources/io/github/palexdev/materialfx/demo/progress_spinners_demo.fxml

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import io.github.palexdev.materialfx.controls.*?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.*?>
+<StackPane prefHeight="400.0" prefWidth="600.0" stylesheets="@css/progress_spinners_demo.css" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.ProgressSpinnersDemoController">
+    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Progress Spinners" StackPane.alignment="TOP_CENTER">
+        <StackPane.margin>
+          <Insets top="20.0" />
+        </StackPane.margin>
+    </Label>
+    <MFXProgressSpinner maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" startingAngle="-40.0" StackPane.alignment="TOP_CENTER">
+        <StackPane.margin>
+          <Insets right="350.0" top="155.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <MFXProgressSpinner maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" startingAngle="-60.0" StackPane.alignment="TOP_CENTER">
+        <StackPane.margin>
+          <Insets right="120.0" top="155.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <MFXProgressSpinner maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" startingAngle="-120.0" StackPane.alignment="TOP_CENTER">
+        <StackPane.margin>
+          <Insets left="120.0" top="155.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <MFXProgressSpinner maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" startingAngle="-210.0" StackPane.alignment="TOP_CENTER">
+        <StackPane.margin>
+          <Insets left="350.0" top="155.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Spinning" StackPane.alignment="TOP_CENTER">
+        <StackPane.margin>
+          <Insets top="100.0" />
+        </StackPane.margin>
+    </Label>
+    <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Progress and CSS">
+        <StackPane.margin>
+          <Insets top="100.0" />
+        </StackPane.margin>
+    </Label>
+    <MFXProgressSpinner fx:id="progress1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" progress="0.0" startingAngle="-40.0" styleClass="progress1">
+        <StackPane.margin>
+          <Insets right="350.0" top="225.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <MFXProgressSpinner fx:id="progress2" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" progress="0.0" startingAngle="-60.0" styleClass="progress2">
+        <StackPane.margin>
+          <Insets right="120.0" top="225.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <MFXProgressSpinner id="cssSpinner1" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" startingAngle="-120.0">
+        <StackPane.margin>
+          <Insets left="120.0" top="225.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+    <MFXProgressSpinner id="cssSpinner2" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="50.0" prefWidth="50.0" startingAngle="-210.0">
+        <StackPane.margin>
+          <Insets left="350.0" top="225.0" />
+        </StackPane.margin>
+    </MFXProgressSpinner>
+</StackPane>

+ 2 - 2
demo/src/main/resources/io/github/palexdev/materialfx/demo/textfields_demo.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/textfields_demo.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.TextfieldsDemoController">
+<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/textfields_demo.css" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.github.palexdev.materialfx.demo.controllers.TextfieldsDemoController">
     <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="TextFields" StackPane.alignment="TOP_CENTER">
         <StackPane.margin>
           <Insets top="20.0" />
@@ -39,7 +39,7 @@
          <Insets left="150.0" top="180.0" />
       </StackPane.margin>
    </MFXTextField>
-   <MFXCheckbox fx:id="checkbox" checkedColor="#00e240" markType="mfx-variant9-mark" text="CheckBox Validation" StackPane.alignment="BOTTOM_LEFT">
+   <MFXCheckbox fx:id="checkbox" checkedColor="#00e240" markSize="9.0" markType="mfx-variant9-mark" text="CheckBox Validation" StackPane.alignment="BOTTOM_LEFT">
       <StackPane.margin>
          <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
       </StackPane.margin>

+ 52 - 0
demo/src/main/resources/io/github/palexdev/materialfx/demo/treeviews_demo.fxml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+<?import io.github.palexdev.materialfx.controls.MFXCheckTreeView?>
+<?import io.github.palexdev.materialfx.controls.MFXTreeView?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.text.Text?>
+<StackPane prefHeight="520.0" prefWidth="720.0" xmlns="http://javafx.com/javafx/15.0.1"
+           xmlns:fx="http://javafx.com/fxml/1"
+           fx:controller="io.github.palexdev.materialfx.demo.controllers.TreeviewsDemoController">
+   <Label id="customLabel" alignment="CENTER" prefHeight="26.0" prefWidth="266.0" text="Tree Views"
+          StackPane.alignment="TOP_CENTER">
+      <StackPane.margin>
+         <Insets top="20.0"/>
+      </StackPane.margin>
+   </Label>
+   <MFXTreeView fx:id="treeView" prefHeight="300.0" prefWidth="200.0" StackPane.alignment="TOP_CENTER">
+      <StackPane.margin>
+         <Insets right="500.0" top="60.0"/>
+      </StackPane.margin>
+   </MFXTreeView>
+   <MFXTreeView fx:id="treeViewHide" prefHeight="300.0" prefWidth="200.0" StackPane.alignment="TOP_CENTER">
+      <StackPane.margin>
+         <Insets top="60.0"/>
+      </StackPane.margin>
+   </MFXTreeView>
+   <MFXCheckTreeView fx:id="checkTreeView" prefHeight="300.0" prefWidth="200.0" StackPane.alignment="TOP_CENTER">
+      <StackPane.margin>
+         <Insets left="500.0" top="60.0"/>
+      </StackPane.margin>
+   </MFXCheckTreeView>
+   <Text fx:id="text1" strokeType="OUTSIDE" strokeWidth="0.0" textAlignment="CENTER" wrappingWidth="200.0"
+         StackPane.alignment="BOTTOM_CENTER">
+      <StackPane.margin>
+         <Insets bottom="20.0" right="500.0" top="250.0"/>
+      </StackPane.margin>
+   </Text>
+   <Text fx:id="text2" strokeType="OUTSIDE" strokeWidth="0.0" textAlignment="CENTER" wrappingWidth="200.0"
+         StackPane.alignment="BOTTOM_CENTER">
+      <StackPane.margin>
+         <Insets bottom="20.0" top="250.0"/>
+      </StackPane.margin>
+   </Text>
+   <Text fx:id="text3" strokeType="OUTSIDE" strokeWidth="0.0" textAlignment="CENTER" wrappingWidth="200.0"
+         StackPane.alignment="BOTTOM_CENTER">
+      <StackPane.margin>
+         <Insets bottom="20.0" left="500.0" top="250.0"/>
+      </StackPane.margin>
+   </Text>
+</StackPane>

+ 1 - 1
materialfx/build.gradle

@@ -1,5 +1,5 @@
 plugins {
-    id 'biz.aQute.bnd.builder' version '5.1.2'
+    id 'biz.aQute.bnd.builder' version '5.2.0'
     id 'com.vanniktech.maven.publish' version '0.13.0'
 }
 

+ 4 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXCheckTreeView.java

@@ -11,6 +11,10 @@ public class MFXCheckTreeView<T> extends MFXTreeView<T> {
     //================================================================================
     // Constructors
     //================================================================================
+    public MFXCheckTreeView() {
+        super();
+    }
+
     public MFXCheckTreeView(MFXTreeItem<T> root) {
         super(root);
     }

+ 15 - 4
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXTreeView.java

@@ -33,6 +33,12 @@ public class MFXTreeView<T> extends MFXScrollPane {
     //================================================================================
     // Constructors
     //================================================================================
+    public MFXTreeView() {
+        installSelectionModel();
+
+        initialize();
+    }
+
     public MFXTreeView(MFXTreeItem<T> root) {
         installSelectionModel();
 
@@ -54,8 +60,6 @@ public class MFXTreeView<T> extends MFXScrollPane {
         getStyleClass().add(STYLE_CLASS);
         setMaxSize(USE_PREF_SIZE, USE_PREF_SIZE);
         setPrefSize(250, 500);
-        setPadding(new Insets(3));
-        MFXScrollPane.smoothVScrolling(this);
 
         AbstractMFXTreeItem<T> root = getRoot();
         rootProperty().addListener((observable, oldRoot, newRoot) -> {
@@ -63,9 +67,15 @@ public class MFXTreeView<T> extends MFXScrollPane {
             setContent(newRoot);
             setupRoot();
         });
-        setupRoot();
+        if (root != null) {
+            setupRoot();
+        }
 
-        showRoot.addListener((observable, oldValue, newValue) -> root.fireEvent(new TreeViewEvent(TreeViewEvent.HIDE_ROOT_EVENT, newValue)));
+        showRoot.addListener((observable, oldValue, newValue) -> {
+            if (root != null) {
+                root.fireEvent(new TreeViewEvent(TreeViewEvent.HIDE_ROOT_EVENT, newValue));
+            }
+        });
     }
 
     /**
@@ -74,6 +84,7 @@ public class MFXTreeView<T> extends MFXScrollPane {
     public void setupRoot() {
         AbstractMFXTreeItem<T> root = getRoot();
         root.prefWidthProperty().bind(widthProperty().subtract(10));
+        root.setPadding(new Insets(0, 0, 5, 0));
         root.skinProperty().addListener(new ChangeListener<>() {
             @Override
             public void changed(ObservableValue<? extends Skin<?>> observable, Skin<?> oldValue, Skin<?> newValue) {

+ 3 - 1
materialfx/src/main/java/io/github/palexdev/materialfx/controls/SelectionModel.java

@@ -94,7 +94,9 @@ public class SelectionModel<T> implements ISelectionModel<T> {
     @Override
     public void scanTree(AbstractMFXTreeItem<T> item) {
         TreeItemStream.flattenTree(item).forEach(treeItem -> {
-            if (treeItem.isSelected()) select(treeItem);
+            if (treeItem.isSelected() && !selectedItems.contains(treeItem)) {
+                select(treeItem);
+            }
         });
     }
 

+ 1 - 1
materialfx/src/main/java/io/github/palexdev/materialfx/controls/base/AbstractMFXTreeCell.java

@@ -7,7 +7,7 @@ import javafx.geometry.Pos;
 import javafx.scene.Node;
 import javafx.scene.layout.HBox;
 
-// TODO implement StringConverter
+// TODO implement StringConverter (low priority)
 
 /**
  * Base class for every cell used by {@code MFXTreeItem}s.

+ 3 - 6
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTreeItemSkin.java

@@ -9,10 +9,7 @@ import javafx.animation.*;
 import javafx.collections.FXCollections;
 import javafx.collections.ListChangeListener;
 import javafx.geometry.Insets;
-import javafx.geometry.Side;
 import javafx.scene.Node;
-import javafx.scene.control.ContextMenu;
-import javafx.scene.control.MenuItem;
 import javafx.scene.control.SkinBase;
 import javafx.scene.input.MouseButton;
 import javafx.scene.input.MouseEvent;
@@ -73,7 +70,7 @@ public class MFXTreeItemSkin<T> extends SkinBase<MFXTreeItem<T>> {
     // Properties
     //================================================================================
     private final VBox box;
-    private final ContextMenu menu;
+    //private final ContextMenu menu;
     private final AbstractMFXTreeCell<T> cell;
     private final ListChangeListener<AbstractMFXTreeItem<T>> itemsListener;
 
@@ -103,7 +100,7 @@ public class MFXTreeItemSkin<T> extends SkinBase<MFXTreeItem<T>> {
         clip.heightProperty().bind(box.heightProperty());
         box.setClip(clip);
 
-        // TODO refactor, testing purpose
+/*        // TODO refactor, testing purpose
         menu = new ContextMenu();
         MenuItem mItemAdd = new MenuItem("ADD ITEM");
         MenuItem mItemRemove = new MenuItem("REMOVE ITEM");
@@ -122,7 +119,7 @@ public class MFXTreeItemSkin<T> extends SkinBase<MFXTreeItem<T>> {
             if (item.getItemParent() != null) {
                 item.getItemParent().getItems().remove(item);
             }
-        });
+        });*/
 
         interpolator = Interpolator.SPLINE(0.0825D, 0.3025D, 0.0875D, 0.9975D);
 

+ 4 - 1
materialfx/src/main/resources/io/github/palexdev/materialfx/css/mfx-treeview.css

@@ -1,10 +1,13 @@
 @import "mfx-scrollpane.css";
 
 .mfx-tree-view {
-    -fx-padding: 3;
     -fx-border-insets: -1;
     -fx-border-color: lightgray;
     -fx-border-width: 1.5;
     -fx-border-radius: 1.5;
     -fx-background-radius: 1.5;
+}
+
+.mfx-tree-view .viewport {
+    -fx-background-color: white;
 }