Browse Source

Version 11.7.1

AbstractMFXDialog, MFXDialogFactory: switch from single close button to a list of generic Nodes, this allows to have much more flexibility.
MFXStageDialog: added more wrapper methods.

AbstractMFXTreeItem: added setItems method (forgot oops).

MFXTableColumnCell, MFXTableColumnCellSkin: added tooltip.

MFXLabel: added text fill property.
MFXLabelSkin: fixed and significantly improved the editor behaviour, now you can open the editor by double clicking on the whole control, the icons are excluded. Now if the editor looses focus the editor is hidden and any changes are confirmed. The width and position are now computed more accurately. Now when the editor is shown it acquires the focus.

MFXIconWrapper: setIcon method fixed once and for all (I hope).

Added new resources.
mfx-dialog.css: fixed dialog title appearing a little blurry.

Signed-off-by: PAlex404 <alessandro.parisi406@gmail.com>
PAlex404 4 years ago
parent
commit
4ca98ea43c

+ 2 - 2
README.md

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

+ 1 - 1
build.gradle

@@ -4,7 +4,7 @@ plugins {
 }
 }
 
 
 group 'io.github.palexdev'
 group 'io.github.palexdev'
-version '11.7.0'
+version '11.7.1'
 
 
 repositories {
 repositories {
     mavenCentral()
     mavenCentral()

+ 19 - 0
demo/src/test/java/treeview/TreeViewTests.java

@@ -4,10 +4,12 @@ import io.github.palexdev.materialfx.controls.MFXTreeItem;
 import io.github.palexdev.materialfx.controls.MFXTreeView;
 import io.github.palexdev.materialfx.controls.MFXTreeView;
 import io.github.palexdev.materialfx.controls.base.AbstractMFXTreeItem;
 import io.github.palexdev.materialfx.controls.base.AbstractMFXTreeItem;
 import io.github.palexdev.materialfx.utils.TreeItemStream;
 import io.github.palexdev.materialfx.utils.TreeItemStream;
+import javafx.collections.FXCollections;
 import javafx.scene.Scene;
 import javafx.scene.Scene;
 import javafx.scene.layout.StackPane;
 import javafx.scene.layout.StackPane;
 import javafx.stage.Stage;
 import javafx.stage.Stage;
 import org.junit.Test;
 import org.junit.Test;
+import org.testfx.api.FxRobot;
 import org.testfx.framework.junit.ApplicationTest;
 import org.testfx.framework.junit.ApplicationTest;
 
 
 import java.io.File;
 import java.io.File;
@@ -21,6 +23,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertNull;
 
 
 public class TreeViewTests extends ApplicationTest {
 public class TreeViewTests extends ApplicationTest {
+    private final FxRobot robot = new FxRobot();
     private final String desktopPath = System.getProperty("user.home") + "/Desktop";
     private final String desktopPath = System.getProperty("user.home") + "/Desktop";
     private MFXTreeView<String> treeView;
     private MFXTreeView<String> treeView;
     private MFXTreeView<String> expandedTreeView;
     private MFXTreeView<String> expandedTreeView;
@@ -269,6 +272,22 @@ public class TreeViewTests extends ApplicationTest {
         System.out.println("TimeSelectedMultiple:" + ((double) (end - start) / 1000000) + "ms");
         System.out.println("TimeSelectedMultiple:" + ((double) (end - start) / 1000000) + "ms");
     }
     }
 
 
+    @SuppressWarnings("ConstantConditions")
+    @Test
+    public void testSetItems() {
+        long start = System.nanoTime();
+        MFXTreeItem<String> root = (MFXTreeItem<String>) treeView.getRoot();
+        MFXTreeItem<String> i1 = (MFXTreeItem<String>) TreeItemStream.stream(root)
+                .filter(i -> i.getData().equals("I1"))
+                .findFirst().orElse(null);
+
+        robot.interact(() -> i1.setItems(FXCollections.observableArrayList()));
+
+        assertEquals(9, root.getItemsCount());
+        long end = System.nanoTime();
+        System.out.println("TimeSelectedMultiple:" + ((double) (end - start) / 1000000) + "ms");
+    }
+
     //================================================================================
     //================================================================================
     // OTHER METHODS
     // OTHER METHODS
     //================================================================================
     //================================================================================

+ 1 - 1
materialfx/gradle.properties

@@ -1,6 +1,6 @@
 GROUP=io.github.palexdev
 GROUP=io.github.palexdev
 POM_ARTIFACT_ID=materialfx
 POM_ARTIFACT_ID=materialfx
-VERSION_NAME=11.7.0
+VERSION_NAME=11.7.1
 
 
 POM_NAME=materialfx
 POM_NAME=materialfx
 POM_DESCRIPTION=Material Desgin components for JavaFX
 POM_DESCRIPTION=Material Desgin components for JavaFX

+ 6 - 3
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXIconWrapper.java

@@ -88,12 +88,15 @@ public class MFXIconWrapper extends StackPane {
      * Sets the icon node.
      * Sets the icon node.
      */
      */
     public void setIcon(Node node) {
     public void setIcon(Node node) {
+        if (getChildren().isEmpty()) {
+            super.getChildren().add(node);
+            return;
+        }
+
         if (getChildren().size() > 1) {
         if (getChildren().size() > 1) {
             super.getChildren().set(1, node);
             super.getChildren().set(1, node);
-        } else if (!getChildren().isEmpty() && (getChildren().get(0) instanceof RippleGenerator)){
-            super.getChildren().add(0, node);
         } else {
         } else {
-            super.getChildren().set(0, node);
+            super.getChildren().add(node);
         }
         }
     }
     }
 
 

+ 16 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXLabel.java

@@ -58,6 +58,7 @@ public class MFXLabel extends Control {
     private final StringProperty text = new SimpleStringProperty();
     private final StringProperty text = new SimpleStringProperty();
     private final StringProperty promptText = new SimpleStringProperty("Label");
     private final StringProperty promptText = new SimpleStringProperty("Label");
     private final ObjectProperty<Font> font = new SimpleObjectProperty<>(Font.getDefault());
     private final ObjectProperty<Font> font = new SimpleObjectProperty<>(Font.getDefault());
+    private final ObjectProperty<Color> textFill = new SimpleObjectProperty<>(Color.BLACK);
     private final ObjectProperty<Pos> labelAlignment = new SimpleObjectProperty<>(Pos.CENTER);
     private final ObjectProperty<Pos> labelAlignment = new SimpleObjectProperty<>(Pos.CENTER);
     private final ObjectProperty<Node> leadingIcon = new SimpleObjectProperty<>();
     private final ObjectProperty<Node> leadingIcon = new SimpleObjectProperty<>();
     private final ObjectProperty<Node> trailingIcon = new SimpleObjectProperty<>();
     private final ObjectProperty<Node> trailingIcon = new SimpleObjectProperty<>();
@@ -147,6 +148,21 @@ public class MFXLabel extends Control {
         this.font.set(font);
         this.font.set(font);
     }
     }
 
 
+    public Color getTextFill() {
+        return textFill.get();
+    }
+
+    /**
+     * Specifies the color of the text.
+     */
+    public ObjectProperty<Color> textFillProperty() {
+        return textFill;
+    }
+
+    public void setTextFill(Color textFill) {
+        this.textFill.set(textFill);
+    }
+
     public Pos getLabelAlignment() {
     public Pos getLabelAlignment() {
         return labelAlignment.get();
         return labelAlignment.get();
     }
     }

+ 12 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXStageDialog.java

@@ -199,6 +199,18 @@ public class MFXStageDialog {
         }
         }
     }
     }
 
 
+    public void toFront() {
+        this.dialogStage.toFront();
+    }
+
+    public void toBack() {
+        this.dialogStage.toBack();
+    }
+
+    public void setAlwaysOnTop(boolean alwaysOnTop) {
+        this.dialogStage.setAlwaysOnTop(alwaysOnTop);
+    }
+
     /**
     /**
      * Returns the AbstractMFXDialog associated with this MFXStageDialog
      * Returns the AbstractMFXDialog associated with this MFXStageDialog
      * You can only change title and content as other properties are ignored
      * You can only change title and content as other properties are ignored

+ 33 - 11
materialfx/src/main/java/io/github/palexdev/materialfx/controls/base/AbstractMFXDialog.java

@@ -26,11 +26,15 @@ import io.github.palexdev.materialfx.utils.NodeUtils;
 import javafx.animation.ParallelTransition;
 import javafx.animation.ParallelTransition;
 import javafx.beans.property.*;
 import javafx.beans.property.*;
 import javafx.event.EventHandler;
 import javafx.event.EventHandler;
+import javafx.scene.Node;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.BorderPane;
 import javafx.scene.layout.BorderPane;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Region;
 import javafx.scene.layout.Region;
 
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
 /**
  * Base class for a material dialog.
  * Base class for a material dialog.
  * <p>
  * <p>
@@ -47,7 +51,7 @@ public abstract class AbstractMFXDialog extends BorderPane {
 
 
     protected final StringProperty title = new SimpleStringProperty("");
     protected final StringProperty title = new SimpleStringProperty("");
     protected final StringProperty content = new SimpleStringProperty("");
     protected final StringProperty content = new SimpleStringProperty("");
-    protected MFXButton closeButton;
+    protected final List<Node> closeButtons = new ArrayList<>();
     protected boolean centerBeforeShow = true;
     protected boolean centerBeforeShow = true;
 
 
     protected final MFXScrimEffect scrimEffect = new MFXScrimEffect();
     protected final MFXScrimEffect scrimEffect = new MFXScrimEffect();
@@ -171,8 +175,9 @@ public abstract class AbstractMFXDialog extends BorderPane {
         setPrefSize(400, 300);
         setPrefSize(400, 300);
         setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
         setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
 
 
-        this.closeButton = new MFXButton("");
-        this.closeButton.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+        MFXButton button = new MFXButton("");
+        button.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+        closeButtons.add(button);
     }
     }
 
 
     //================================================================================
     //================================================================================
@@ -225,17 +230,32 @@ public abstract class AbstractMFXDialog extends BorderPane {
         return scrimEffect;
         return scrimEffect;
     }
     }
 
 
-    public MFXButton getCloseButton() {
-        return closeButton;
+    public void addCloseButton(Node button) {
+        button.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+        closeButtons.add(button);
+    }
+
+    public List<Node> getCloseButtons() {
+        return closeButtons;
     }
     }
 
 
     /**
     /**
      * Replaces the dialog's default close button with a new one and adds the close handler to it.
      * Replaces the dialog's default close button with a new one and adds the close handler to it.
-     * @param closeButton The new close button
+     * @param buttons The new close button
      */
      */
-    public void setCloseButton(MFXButton closeButton) {
-        this.closeButton = closeButton;
-        this.closeButton.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+    public void setCloseButtons(Node... buttons) {
+        for (Node closeButton : closeButtons) {
+            closeButton.removeEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+        }
+        closeButtons.clear();
+        closeButtons.addAll(List.of(buttons));
+        for (Node closeButton : closeButtons) {
+            closeButton.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+        }
+    }
+
+    public EventHandler<MouseEvent> getCloseHandler() {
+        return this.closeHandler;
     }
     }
 
 
     /**
     /**
@@ -245,9 +265,11 @@ public abstract class AbstractMFXDialog extends BorderPane {
      * @param newHandler The new close handler
      * @param newHandler The new close handler
      */
      */
     public void setCloseHandler(EventHandler<MouseEvent> newHandler) {
     public void setCloseHandler(EventHandler<MouseEvent> newHandler) {
-        this.closeButton.removeEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+        for (Node closeButton : closeButtons) {
+            closeButton.removeEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
+            closeButton.addEventHandler(MouseEvent.MOUSE_PRESSED, newHandler);
+        }
         this.closeHandler = newHandler;
         this.closeHandler = newHandler;
-        this.closeButton.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
     }
     }
 
 
     public double getScrimOpacity() {
     public double getScrimOpacity() {

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

@@ -233,6 +233,10 @@ public abstract class AbstractMFXTreeItem<T> extends Control {
         return items;
         return items;
     }
     }
 
 
+    public void setItems(ObservableList<AbstractMFXTreeItem<T>> items) {
+        this.items.setAll(items);
+    }
+
     /**
     /**
      * @return this item's parent item
      * @return this item's parent item
      */
      */

+ 39 - 4
materialfx/src/main/java/io/github/palexdev/materialfx/controls/cell/MFXTableColumnCell.java

@@ -21,10 +21,7 @@ package io.github.palexdev.materialfx.controls.cell;
 import io.github.palexdev.materialfx.MFXResourcesLoader;
 import io.github.palexdev.materialfx.MFXResourcesLoader;
 import io.github.palexdev.materialfx.controls.enums.SortState;
 import io.github.palexdev.materialfx.controls.enums.SortState;
 import io.github.palexdev.materialfx.skins.MFXTableColumnCellSkin;
 import io.github.palexdev.materialfx.skins.MFXTableColumnCellSkin;
-import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
+import javafx.beans.property.*;
 import javafx.scene.control.Label;
 import javafx.scene.control.Label;
 import javafx.scene.control.Skin;
 import javafx.scene.control.Skin;
 import javafx.util.Callback;
 import javafx.util.Callback;
@@ -49,6 +46,8 @@ public class MFXTableColumnCell<T> extends Label {
 
 
     private final ObjectProperty<Callback<T, ? extends MFXTableRowCell>> rowCellFactory = new SimpleObjectProperty<>();
     private final ObjectProperty<Callback<T, ? extends MFXTableRowCell>> rowCellFactory = new SimpleObjectProperty<>();
     private final StringProperty columnName = new SimpleStringProperty("");
     private final StringProperty columnName = new SimpleStringProperty("");
+    private final BooleanProperty hasTooltip = new SimpleBooleanProperty(true);
+    private final StringProperty tooltipText = new SimpleStringProperty();
 
 
     private SortState sortState = SortState.UNSORTED;
     private SortState sortState = SortState.UNSORTED;
     private Comparator<T> comparator;
     private Comparator<T> comparator;
@@ -74,6 +73,7 @@ public class MFXTableColumnCell<T> extends Label {
     //================================================================================
     //================================================================================
     private void initialize() {
     private void initialize() {
         getStyleClass().add(STYLE_CLASS);
         getStyleClass().add(STYLE_CLASS);
+        setTooltipText(getColumnName());
     }
     }
 
 
     public Callback<T, ? extends MFXTableRowCell> getRowCellFactory() {
     public Callback<T, ? extends MFXTableRowCell> getRowCellFactory() {
@@ -92,6 +92,9 @@ public class MFXTableColumnCell<T> extends Label {
         return columnName.get();
         return columnName.get();
     }
     }
 
 
+    /**
+     * Specifies the name of the column.
+     */
     public StringProperty columnNameProperty() {
     public StringProperty columnNameProperty() {
         return columnName;
         return columnName;
     }
     }
@@ -100,6 +103,38 @@ public class MFXTableColumnCell<T> extends Label {
         this.columnName.set(columnName);
         this.columnName.set(columnName);
     }
     }
 
 
+    public boolean hasTooltip() {
+        return hasTooltip.get();
+    }
+
+    /**
+     * Specifies if the column cell should show a tooltip or not.
+     * <p>
+     * By default the tooltip is initialized with the column's name.
+     */
+    public BooleanProperty hasTooltipProperty() {
+        return hasTooltip;
+    }
+
+    public void setHasTooltip(boolean hasTooltip) {
+        this.hasTooltip.set(hasTooltip);
+    }
+
+    public String getTooltipText() {
+        return tooltipText.get();
+    }
+
+    /**
+     * Specifies the text shown by the tooltip.
+     */
+    public StringProperty tooltipTextProperty() {
+        return tooltipText;
+    }
+
+    public void setTooltipText(String tooltipText) {
+        this.tooltipText.set(tooltipText);
+    }
+
     public SortState getSortState() {
     public SortState getSortState() {
         return sortState;
         return sortState;
     }
     }

+ 5 - 3
materialfx/src/main/java/io/github/palexdev/materialfx/controls/factories/MFXDialogFactory.java

@@ -164,10 +164,10 @@ public class MFXDialogFactory {
         MFXFontIcon closeIcon = new MFXFontIcon("mfx-x", Color.WHITE);
         MFXFontIcon closeIcon = new MFXFontIcon("mfx-x", Color.WHITE);
 
 
         if (dialog.getType() != null && dialog.getType().equals(DialogType.GENERIC)) {
         if (dialog.getType() != null && dialog.getType().equals(DialogType.GENERIC)) {
-            dialog.setCloseButton(new MFXButton(""));
+            dialog.setCloseButtons(new MFXButton(""));
         }
         }
 
 
-        MFXButton closeButton = dialog.getCloseButton();
+        MFXButton closeButton = new MFXButton("");
         closeButton.setPrefSize(20, 20);
         closeButton.setPrefSize(20, 20);
         closeButton.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
         closeButton.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
         closeButton.setGraphic(closeIcon);
         closeButton.setGraphic(closeIcon);
@@ -175,6 +175,7 @@ public class MFXDialogFactory {
         closeButton.setRippleColor(Color.rgb(255, 0, 0, 0.1));
         closeButton.setRippleColor(Color.rgb(255, 0, 0, 0.1));
         closeButton.setRippleInDuration(Duration.millis(500));
         closeButton.setRippleInDuration(Duration.millis(500));
         closeButton.setButtonType(ButtonType.FLAT);
         closeButton.setButtonType(ButtonType.FLAT);
+        dialog.setCloseButtons(closeButton);
 
 
         NodeUtils.makeRegionCircular(closeButton);
         NodeUtils.makeRegionCircular(closeButton);
 
 
@@ -271,13 +272,14 @@ public class MFXDialogFactory {
         buttonsBox.setPadding(new Insets(0, 15, 10, 0));
         buttonsBox.setPadding(new Insets(0, 15, 10, 0));
         buttonsBox.getStyleClass().add("buttons-box");
         buttonsBox.getStyleClass().add("buttons-box");
 
 
-        MFXButton closeButton = dialog.getCloseButton();
+        MFXButton closeButton = new MFXButton("");
         closeButton.setText("OK");
         closeButton.setText("OK");
         closeButton.setPrefSize(55, 20);
         closeButton.setPrefSize(55, 20);
         closeButton.setTextFill(Color.rgb(120, 66, 245));
         closeButton.setTextFill(Color.rgb(120, 66, 245));
         closeButton.setRippleRadius(30);
         closeButton.setRippleRadius(30);
         closeButton.setRippleInDuration(Duration.millis(500));
         closeButton.setRippleInDuration(Duration.millis(500));
         closeButton.setRippleColor(Color.rgb(120, 66, 245, 0.3));
         closeButton.setRippleColor(Color.rgb(120, 66, 245, 0.3));
+        dialog.setCloseButtons(closeButton);
 
 
         HBox.setMargin(closeButton, new Insets(5, 10, 0, 0));
         HBox.setMargin(closeButton, new Insets(5, 10, 0, 0));
         buttonsBox.getChildren().add(closeButton);
         buttonsBox.getChildren().add(closeButton);

+ 2 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/font/FontResources.java

@@ -56,6 +56,8 @@ public enum FontResources {
     SEARCH_PLUS("mfx-search-plus", '\uE92a'),
     SEARCH_PLUS("mfx-search-plus", '\uE92a'),
     STEP_BACKWARD("mfx-step-backward", '\uE923'),
     STEP_BACKWARD("mfx-step-backward", '\uE923'),
     STEP_FORWARD("mfx-step-forward", '\uE924'),
     STEP_FORWARD("mfx-step-forward", '\uE924'),
+    USER("mfx-user", '\uE92c'),
+    USERS("mfx-users", '\uE92d'),
     VARIANT3_MARK("mfx-variant3-mark", '\uE90e'),
     VARIANT3_MARK("mfx-variant3-mark", '\uE90e'),
     VARIANT4_MARK("mfx-variant4-mark", '\uE90f'),
     VARIANT4_MARK("mfx-variant4-mark", '\uE90f'),
     VARIANT5_MARK("mfx-variant5-mark", '\uE910'),
     VARIANT5_MARK("mfx-variant5-mark", '\uE910'),

+ 67 - 14
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXLabelSkin.java

@@ -22,9 +22,9 @@ import io.github.palexdev.materialfx.controls.MFXLabel;
 import io.github.palexdev.materialfx.controls.MFXTextField;
 import io.github.palexdev.materialfx.controls.MFXTextField;
 import io.github.palexdev.materialfx.controls.enums.Styles;
 import io.github.palexdev.materialfx.controls.enums.Styles;
 import io.github.palexdev.materialfx.controls.factories.MFXAnimationFactory;
 import io.github.palexdev.materialfx.controls.factories.MFXAnimationFactory;
-import io.github.palexdev.materialfx.utils.NodeUtils;
 import javafx.animation.ScaleTransition;
 import javafx.animation.ScaleTransition;
 import javafx.beans.binding.Bindings;
 import javafx.beans.binding.Bindings;
+import javafx.event.EventHandler;
 import javafx.geometry.Insets;
 import javafx.geometry.Insets;
 import javafx.scene.Node;
 import javafx.scene.Node;
 import javafx.scene.control.Label;
 import javafx.scene.control.Label;
@@ -44,10 +44,17 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
     //================================================================================
     //================================================================================
     private final HBox container;
     private final HBox container;
     private final Label textNode;
     private final Label textNode;
+    private final double lrInsets = 10;
 
 
     private final Line unfocusedLine;
     private final Line unfocusedLine;
     private final Line focusedLine;
     private final Line focusedLine;
 
 
+    private EventHandler<MouseEvent> iconEditorHandler = event -> {
+        if (event.getClickCount() > 1) {
+            event.consume();
+        }
+    };
+
     //================================================================================
     //================================================================================
     // Constructors
     // Constructors
     //================================================================================
     //================================================================================
@@ -78,18 +85,21 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
             return label.getText();
             return label.getText();
         }, label.textProperty(), label.promptTextProperty()));
         }, label.textProperty(), label.promptTextProperty()));
         textNode.fontProperty().bind(label.fontProperty());
         textNode.fontProperty().bind(label.fontProperty());
+        textNode.textFillProperty().bind(label.textFillProperty());
         textNode.alignmentProperty().bind(label.labelAlignmentProperty());
         textNode.alignmentProperty().bind(label.labelAlignmentProperty());
 
 
         container = new HBox(textNode);
         container = new HBox(textNode);
         container.alignmentProperty().bind(label.alignmentProperty());
         container.alignmentProperty().bind(label.alignmentProperty());
         container.spacingProperty().bind(label.graphicTextGapProperty());
         container.spacingProperty().bind(label.graphicTextGapProperty());
-        container.setPadding(new Insets(0, 10, 0, 10));
+        container.setPadding(new Insets(0, lrInsets, 0, lrInsets));
 
 
         if (label.getLeadingIcon() != null) {
         if (label.getLeadingIcon() != null) {
             container.getChildren().add(0, label.getLeadingIcon());
             container.getChildren().add(0, label.getLeadingIcon());
+            label.getLeadingIcon().addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         }
         }
         if (label.getTrailingIcon() != null) {
         if (label.getTrailingIcon() != null) {
             container.getChildren().add(label.getTrailingIcon());
             container.getChildren().add(label.getTrailingIcon());
+            label.getTrailingIcon().addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         }
         }
 
 
         if (label.getLabelStyle() == Styles.LabelStyles.STYLE1) {
         if (label.getLabelStyle() == Styles.LabelStyles.STYLE1) {
@@ -127,10 +137,13 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
                 return;
                 return;
             }
             }
             if (oldValue != null) {
             if (oldValue != null) {
+                oldValue.removeEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
                 container.getChildren().set(0, newValue);
                 container.getChildren().set(0, newValue);
             } else {
             } else {
                 container.getChildren().add(0, newValue);
                 container.getChildren().add(0, newValue);
             }
             }
+
+            newValue.addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         });
         });
 
 
         label.trailingIconProperty().addListener((observable, oldValue, newValue) -> {
         label.trailingIconProperty().addListener((observable, oldValue, newValue) -> {
@@ -139,11 +152,14 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
                 return;
                 return;
             }
             }
             if (oldValue != null) {
             if (oldValue != null) {
+                oldValue.removeEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
                 int index = container.getChildren().indexOf(oldValue);
                 int index = container.getChildren().indexOf(oldValue);
                 container.getChildren().set(index, newValue);
                 container.getChildren().set(index, newValue);
             } else {
             } else {
                 container.getChildren().add(newValue);
                 container.getChildren().add(newValue);
             }
             }
+
+            newValue.addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         });
         });
 
 
         label.focusedProperty().addListener((observable, oldValue, newValue) -> {
         label.focusedProperty().addListener((observable, oldValue, newValue) -> {
@@ -168,10 +184,9 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
             focusedLine.setScaleX(1.0);
             focusedLine.setScaleX(1.0);
         });
         });
 
 
-        label.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
+        container.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
             label.requestFocus();
             label.requestFocus();
-            if (event.getClickCount() >= 2 && label.isEditable() && !containsEditor() &&
-                    NodeUtils.inHierarchy(event.getPickResult().getIntersectedNode(), textNode)) {
+            if (event.getClickCount() >= 2 && label.isEditable() && !containsEditor()) {
                 showEditor();
                 showEditor();
             }
             }
             event.consume();
             event.consume();
@@ -198,7 +213,8 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
     /**
     /**
      * If {@link MFXLabel#editableProperty()} is set to true shows the editor,
      * If {@link MFXLabel#editableProperty()} is set to true shows the editor,
      * ESCAPE hides the editor canceling any change, ENTER hides the editor and confirms
      * ESCAPE hides the editor canceling any change, ENTER hides the editor and confirms
-     * the changes.
+     * the changes, if the editor looses focus (for example by clicking on another component that requests the focus)
+     * the editor is hidden and any changes are confirmed.
      */
      */
     private void showEditor() {
     private void showEditor() {
         MFXLabel label = getSkinnable();
         MFXLabel label = getSkinnable();
@@ -206,27 +222,58 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
         textNode.setVisible(false);
         textNode.setVisible(false);
         MFXTextField textField = new MFXTextField(textNode.getText());
         MFXTextField textField = new MFXTextField(textNode.getText());
         textField.setId("editor-node");
         textField.setId("editor-node");
+        textField.setManaged(false);
         textField.setUnfocusedLineColor(Color.TRANSPARENT);
         textField.setUnfocusedLineColor(Color.TRANSPARENT);
         textField.setLineColor(Color.TRANSPARENT);
         textField.setLineColor(Color.TRANSPARENT);
-        textField.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
-        textField.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
-        textField.prefWidthProperty().bind(textNode.widthProperty());
-        textField.prefHeightProperty().bind(textNode.heightProperty());
 
 
         textField.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
         textField.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
             if (event.getCode() == KeyCode.ENTER) {
             if (event.getCode() == KeyCode.ENTER) {
-                getSkinnable().setText(textField.getText());
-                getChildren().remove(textField);
+                label.setText(textField.getText());
+                container.getChildren().remove(textField);
                 textNode.setVisible(true);
                 textNode.setVisible(true);
+                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
                 label.requestFocus();
                 label.requestFocus();
             } else if (event.getCode() == KeyCode.ESCAPE) {
             } else if (event.getCode() == KeyCode.ESCAPE) {
-                getChildren().remove(textField);
+                container.getChildren().remove(textField);
+                textNode.setVisible(true);
+                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
+                label.requestFocus();
+            }
+        });
+
+        textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
+            if (!newValue) {
+                label.setText(textField.getText());
+                container.getChildren().remove(textField);
                 textNode.setVisible(true);
                 textNode.setVisible(true);
+                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
                 label.requestFocus();
                 label.requestFocus();
             }
             }
         });
         });
 
 
-        getChildren().add(textField);
+        container.getChildren().add(textField);
+        computeEditorPosition(textField);
+        textField.requestFocus();
+    }
+
+    /**
+     * Responsible for showing the editor correctly, handles its size and location.
+     * <p>
+     * Note that when the editor with is computed we set that same width as the textNode's prefWidth as well,
+     * this is done so the trailing icon position is automatically managed by the container. When the editor is removed
+     * the textNode's prefWidth is set to USE_COMPUTED_SIZE.
+     */
+    private void computeEditorPosition(MFXTextField textField) {
+        MFXLabel label = getSkinnable();
+
+        double posX = textNode.getBoundsInParent().getMinX();
+        double containerWidth = container.getWidth();
+        double containerHeight = container.getHeight();
+        double leadingWidth = label.getLeadingIcon() != null ? label.getLeadingIcon().getLayoutBounds().getWidth() : 0;
+        double trailingWidth = label.getTrailingIcon() != null ? label.getTrailingIcon().getLayoutBounds().getWidth() : 0;
+        double editorWidth = containerWidth - (lrInsets + leadingWidth + label.getGraphicTextGap() + trailingWidth + label.getGraphicTextGap() + lrInsets);
+        textNode.setPrefWidth(editorWidth);
+        textField.resizeRelocate(posX, 0, editorWidth, containerHeight);
     }
     }
 
 
     /**
     /**
@@ -263,6 +310,12 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
         return super.computePrefHeight(width, topInset, rightInset, bottomInset, leftInset);
         return super.computePrefHeight(width, topInset, rightInset, bottomInset, leftInset);
     }
     }
 
 
+    @Override
+    public void dispose() {
+        super.dispose();
+        iconEditorHandler = null;
+    }
+
     @Override
     @Override
     protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {
     protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) {
         super.layoutChildren(contentX, contentY, contentWidth, contentHeight);
         super.layoutChildren(contentX, contentY, contentWidth, contentHeight);

+ 28 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXTableColumnCellSkin.java

@@ -26,6 +26,7 @@ import javafx.geometry.Insets;
 import javafx.scene.Node;
 import javafx.scene.Node;
 import javafx.scene.control.ContentDisplay;
 import javafx.scene.control.ContentDisplay;
 import javafx.scene.control.Label;
 import javafx.scene.control.Label;
+import javafx.scene.control.Tooltip;
 import javafx.scene.control.skin.LabelSkin;
 import javafx.scene.control.skin.LabelSkin;
 import javafx.scene.layout.Region;
 import javafx.scene.layout.Region;
 
 
@@ -46,6 +47,24 @@ public class MFXTableColumnCellSkin<T> extends LabelSkin {
         column.setGraphic(createSortIcon());
         column.setGraphic(createSortIcon());
         column.setGraphicTextGap(5);
         column.setGraphicTextGap(5);
         addIcon();
         addIcon();
+
+        if (column.hasTooltip()) {
+            column.setTooltip(buildTooltip());
+        }
+        setListeners();
+    }
+
+    @SuppressWarnings("unchecked")
+    private void setListeners() {
+        MFXTableColumnCell<T> column = (MFXTableColumnCell<T>) getSkinnable();
+
+        column.hasTooltipProperty().addListener((observable, oldValue, newValue) -> {
+            if (!newValue) {
+                column.setTooltip(null);
+            } else {
+                column.setTooltip(buildTooltip());
+            }
+        });
     }
     }
 
 
     /**
     /**
@@ -77,4 +96,13 @@ public class MFXTableColumnCellSkin<T> extends LabelSkin {
             }
             }
         }
         }
     }
     }
+
+    @SuppressWarnings("unchecked")
+    private Tooltip buildTooltip() {
+        MFXTableColumnCell<T> column = (MFXTableColumnCell<T>) getSkinnable();
+
+        Tooltip tooltip = new Tooltip();
+        tooltip.textProperty().bind(column.tooltipTextProperty());
+        return tooltip;
+    }
 }
 }

+ 4 - 2
materialfx/src/main/resources/io/github/palexdev/materialfx/css/mfx-dialog.css

@@ -30,13 +30,15 @@
 }
 }
 
 
 .mfx-dialog .title-label {
 .mfx-dialog .title-label {
-    -fx-font-family: "Open Sans Bold";
-    -fx-font-size: 14;
+    -fx-font-family: "Open Sans SemiBold";
+    -fx-font-size: 15;
+    -fx-font-smoothing-type: grey;
 }
 }
 
 
 .mfx-dialog .content-label {
 .mfx-dialog .content-label {
     -fx-font-family: "Open Sans Regular";
     -fx-font-family: "Open Sans Regular";
     -fx-font-size: 11.5;
     -fx-font-size: 11.5;
+    -fx-font-smoothing-type: grey;
 }
 }
 
 
 .mfx-dialog .buttons-box .mfx-button {
 .mfx-dialog .buttons-box .mfx-button {

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