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

+ 1 - 1
build.gradle

@@ -4,7 +4,7 @@ plugins {
 }
 
 group 'io.github.palexdev'
-version '11.7.0'
+version '11.7.1'
 
 repositories {
     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.base.AbstractMFXTreeItem;
 import io.github.palexdev.materialfx.utils.TreeItemStream;
+import javafx.collections.FXCollections;
 import javafx.scene.Scene;
 import javafx.scene.layout.StackPane;
 import javafx.stage.Stage;
 import org.junit.Test;
+import org.testfx.api.FxRobot;
 import org.testfx.framework.junit.ApplicationTest;
 
 import java.io.File;
@@ -21,6 +23,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
 public class TreeViewTests extends ApplicationTest {
+    private final FxRobot robot = new FxRobot();
     private final String desktopPath = System.getProperty("user.home") + "/Desktop";
     private MFXTreeView<String> treeView;
     private MFXTreeView<String> expandedTreeView;
@@ -269,6 +272,22 @@ public class TreeViewTests extends ApplicationTest {
         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
     //================================================================================

+ 1 - 1
materialfx/gradle.properties

@@ -1,6 +1,6 @@
 GROUP=io.github.palexdev
 POM_ARTIFACT_ID=materialfx
-VERSION_NAME=11.7.0
+VERSION_NAME=11.7.1
 
 POM_NAME=materialfx
 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.
      */
     public void setIcon(Node node) {
+        if (getChildren().isEmpty()) {
+            super.getChildren().add(node);
+            return;
+        }
+
         if (getChildren().size() > 1) {
             super.getChildren().set(1, node);
-        } else if (!getChildren().isEmpty() && (getChildren().get(0) instanceof RippleGenerator)){
-            super.getChildren().add(0, node);
         } 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 promptText = new SimpleStringProperty("Label");
     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<Node> leadingIcon = new SimpleObjectProperty<>();
     private final ObjectProperty<Node> trailingIcon = new SimpleObjectProperty<>();
@@ -147,6 +148,21 @@ public class MFXLabel extends Control {
         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() {
         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
      * 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.beans.property.*;
 import javafx.event.EventHandler;
+import javafx.scene.Node;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.BorderPane;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Region;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Base class for a material dialog.
  * <p>
@@ -47,7 +51,7 @@ public abstract class AbstractMFXDialog extends BorderPane {
 
     protected final StringProperty title = new SimpleStringProperty("");
     protected final StringProperty content = new SimpleStringProperty("");
-    protected MFXButton closeButton;
+    protected final List<Node> closeButtons = new ArrayList<>();
     protected boolean centerBeforeShow = true;
 
     protected final MFXScrimEffect scrimEffect = new MFXScrimEffect();
@@ -171,8 +175,9 @@ public abstract class AbstractMFXDialog extends BorderPane {
         setPrefSize(400, 300);
         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;
     }
 
-    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.
-     * @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
      */
     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.closeButton.addEventHandler(MouseEvent.MOUSE_PRESSED, closeHandler);
     }
 
     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;
     }
 
+    public void setItems(ObservableList<AbstractMFXTreeItem<T>> items) {
+        this.items.setAll(items);
+    }
+
     /**
      * @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.controls.enums.SortState;
 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.Skin;
 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 StringProperty columnName = new SimpleStringProperty("");
+    private final BooleanProperty hasTooltip = new SimpleBooleanProperty(true);
+    private final StringProperty tooltipText = new SimpleStringProperty();
 
     private SortState sortState = SortState.UNSORTED;
     private Comparator<T> comparator;
@@ -74,6 +73,7 @@ public class MFXTableColumnCell<T> extends Label {
     //================================================================================
     private void initialize() {
         getStyleClass().add(STYLE_CLASS);
+        setTooltipText(getColumnName());
     }
 
     public Callback<T, ? extends MFXTableRowCell> getRowCellFactory() {
@@ -92,6 +92,9 @@ public class MFXTableColumnCell<T> extends Label {
         return columnName.get();
     }
 
+    /**
+     * Specifies the name of the column.
+     */
     public StringProperty columnNameProperty() {
         return columnName;
     }
@@ -100,6 +103,38 @@ public class MFXTableColumnCell<T> extends Label {
         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() {
         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);
 
         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.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
         closeButton.setGraphic(closeIcon);
@@ -175,6 +175,7 @@ public class MFXDialogFactory {
         closeButton.setRippleColor(Color.rgb(255, 0, 0, 0.1));
         closeButton.setRippleInDuration(Duration.millis(500));
         closeButton.setButtonType(ButtonType.FLAT);
+        dialog.setCloseButtons(closeButton);
 
         NodeUtils.makeRegionCircular(closeButton);
 
@@ -271,13 +272,14 @@ public class MFXDialogFactory {
         buttonsBox.setPadding(new Insets(0, 15, 10, 0));
         buttonsBox.getStyleClass().add("buttons-box");
 
-        MFXButton closeButton = dialog.getCloseButton();
+        MFXButton closeButton = new MFXButton("");
         closeButton.setText("OK");
         closeButton.setPrefSize(55, 20);
         closeButton.setTextFill(Color.rgb(120, 66, 245));
         closeButton.setRippleRadius(30);
         closeButton.setRippleInDuration(Duration.millis(500));
         closeButton.setRippleColor(Color.rgb(120, 66, 245, 0.3));
+        dialog.setCloseButtons(closeButton);
 
         HBox.setMargin(closeButton, new Insets(5, 10, 0, 0));
         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'),
     STEP_BACKWARD("mfx-step-backward", '\uE923'),
     STEP_FORWARD("mfx-step-forward", '\uE924'),
+    USER("mfx-user", '\uE92c'),
+    USERS("mfx-users", '\uE92d'),
     VARIANT3_MARK("mfx-variant3-mark", '\uE90e'),
     VARIANT4_MARK("mfx-variant4-mark", '\uE90f'),
     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.enums.Styles;
 import io.github.palexdev.materialfx.controls.factories.MFXAnimationFactory;
-import io.github.palexdev.materialfx.utils.NodeUtils;
 import javafx.animation.ScaleTransition;
 import javafx.beans.binding.Bindings;
+import javafx.event.EventHandler;
 import javafx.geometry.Insets;
 import javafx.scene.Node;
 import javafx.scene.control.Label;
@@ -44,10 +44,17 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
     //================================================================================
     private final HBox container;
     private final Label textNode;
+    private final double lrInsets = 10;
 
     private final Line unfocusedLine;
     private final Line focusedLine;
 
+    private EventHandler<MouseEvent> iconEditorHandler = event -> {
+        if (event.getClickCount() > 1) {
+            event.consume();
+        }
+    };
+
     //================================================================================
     // Constructors
     //================================================================================
@@ -78,18 +85,21 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
             return label.getText();
         }, label.textProperty(), label.promptTextProperty()));
         textNode.fontProperty().bind(label.fontProperty());
+        textNode.textFillProperty().bind(label.textFillProperty());
         textNode.alignmentProperty().bind(label.labelAlignmentProperty());
 
         container = new HBox(textNode);
         container.alignmentProperty().bind(label.alignmentProperty());
         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) {
             container.getChildren().add(0, label.getLeadingIcon());
+            label.getLeadingIcon().addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         }
         if (label.getTrailingIcon() != null) {
             container.getChildren().add(label.getTrailingIcon());
+            label.getTrailingIcon().addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         }
 
         if (label.getLabelStyle() == Styles.LabelStyles.STYLE1) {
@@ -127,10 +137,13 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
                 return;
             }
             if (oldValue != null) {
+                oldValue.removeEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
                 container.getChildren().set(0, newValue);
             } else {
                 container.getChildren().add(0, newValue);
             }
+
+            newValue.addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         });
 
         label.trailingIconProperty().addListener((observable, oldValue, newValue) -> {
@@ -139,11 +152,14 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
                 return;
             }
             if (oldValue != null) {
+                oldValue.removeEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
                 int index = container.getChildren().indexOf(oldValue);
                 container.getChildren().set(index, newValue);
             } else {
                 container.getChildren().add(newValue);
             }
+
+            newValue.addEventFilter(MouseEvent.MOUSE_PRESSED, iconEditorHandler);
         });
 
         label.focusedProperty().addListener((observable, oldValue, newValue) -> {
@@ -168,10 +184,9 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
             focusedLine.setScaleX(1.0);
         });
 
-        label.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
+        container.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
             label.requestFocus();
-            if (event.getClickCount() >= 2 && label.isEditable() && !containsEditor() &&
-                    NodeUtils.inHierarchy(event.getPickResult().getIntersectedNode(), textNode)) {
+            if (event.getClickCount() >= 2 && label.isEditable() && !containsEditor()) {
                 showEditor();
             }
             event.consume();
@@ -198,7 +213,8 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
     /**
      * If {@link MFXLabel#editableProperty()} is set to true shows the editor,
      * 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() {
         MFXLabel label = getSkinnable();
@@ -206,27 +222,58 @@ public class MFXLabelSkin extends SkinBase<MFXLabel> {
         textNode.setVisible(false);
         MFXTextField textField = new MFXTextField(textNode.getText());
         textField.setId("editor-node");
+        textField.setManaged(false);
         textField.setUnfocusedLineColor(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 -> {
             if (event.getCode() == KeyCode.ENTER) {
-                getSkinnable().setText(textField.getText());
-                getChildren().remove(textField);
+                label.setText(textField.getText());
+                container.getChildren().remove(textField);
                 textNode.setVisible(true);
+                textNode.setPrefWidth(Region.USE_COMPUTED_SIZE);
                 label.requestFocus();
             } 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.setPrefWidth(Region.USE_COMPUTED_SIZE);
                 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);
     }
 
+    @Override
+    public void dispose() {
+        super.dispose();
+        iconEditorHandler = null;
+    }
+
     @Override
     protected void layoutChildren(double contentX, double contentY, double contentWidth, double 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.control.ContentDisplay;
 import javafx.scene.control.Label;
+import javafx.scene.control.Tooltip;
 import javafx.scene.control.skin.LabelSkin;
 import javafx.scene.layout.Region;
 
@@ -46,6 +47,24 @@ public class MFXTableColumnCellSkin<T> extends LabelSkin {
         column.setGraphic(createSortIcon());
         column.setGraphicTextGap(5);
         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 {
-    -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 {
     -fx-font-family: "Open Sans Regular";
     -fx-font-size: 11.5;
+    -fx-font-smoothing-type: grey;
 }
 
 .mfx-dialog .buttons-box .mfx-button {

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