diff --git a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/util/EnumStringConverterDemo.java b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/util/EnumStringConverterDemo.java
new file mode 100644
index 00000000..b80243ae
--- /dev/null
+++ b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/util/EnumStringConverterDemo.java
@@ -0,0 +1,77 @@
+package com.dlsc.gemsfx.demo.util;
+
+import com.dlsc.gemsfx.util.EnumStringConverter;
+import javafx.application.Application;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.stage.Stage;
+
+
+/**
+ * This class demonstrates the usage of EnumStringConverter, which is a specialized StringConverter implementation
+ * for Enum types. It provides a default mechanism to format Enum values in title case, replaces underscores with spaces,
+ * and capitalizes the first letter of each word. If the Enum value is null, it returns an empty string.
+ *
+ * {@link EnumStringConverter}
+ */
+public class EnumStringConverterDemo extends Application {
+
+ public enum Status {
+ NOT_STARTED,
+ IN_PROGRESS,
+ COMPLETED,
+ CANCELLED
+ }
+
+ @Override
+ public void start(Stage primaryStage) {
+ // Create a ComboBox and populate it with Status objects
+ ComboBox comboBox = new ComboBox<>();
+ comboBox.getItems().addAll(Status.values());
+ comboBox.getSelectionModel().selectFirst();
+
+ // The traditional way to set a StringConverter on a ComboBox
+ // comboBox.setConverter(new StringConverter() {
+ // @Override
+ // public String toString(Status object) {
+ // if (object != null) {
+ // return Arrays.stream(object.name().split("_"))
+ // .filter(word -> !word.isEmpty())
+ // .map(word -> word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase())
+ // .collect(Collectors.joining(" "));
+ // }
+ // return "";
+ // }
+ //
+ // @Override
+ // public Status fromString(String string) {
+ // return null;
+ // }
+ // });
+
+ // Set the converter to use EnumStringConverter with the default title case formatting
+ comboBox.setConverter(new EnumStringConverter<>());
+
+ // Create a VBox layout and add the ComboBox to it
+ Label label = new Label("Select a status:");
+ label.setFont(Font.font(15));
+ VBox vbox = new VBox(15, label, comboBox);
+ vbox.setAlignment(Pos.CENTER);
+ vbox.setPadding(new Insets(20));
+ Scene scene = new Scene(vbox,300, 200);
+
+ // Configure and show the primary stage
+ primaryStage.setTitle("EnumStringConverter Demo");
+ primaryStage.setScene(scene);
+ primaryStage.show();
+ }
+
+ public static void main(String[] args) {
+ launch(args);
+ }
+}
diff --git a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/util/SimpleStringConverterDemo.java b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/util/SimpleStringConverterDemo.java
new file mode 100644
index 00000000..b97b25e6
--- /dev/null
+++ b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/util/SimpleStringConverterDemo.java
@@ -0,0 +1,74 @@
+package com.dlsc.gemsfx.demo.util;
+
+import com.dlsc.gemsfx.util.SimpleStringConverter;
+import javafx.application.Application;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.stage.Stage;
+
+import java.time.LocalDate;
+
+/**
+ * This class demonstrates the usage of SimpleStringConverter, which is a specialized StringConverter implementation
+ * that allows you to define a custom formatting function for the conversion of objects to strings. It also provides
+ * a default mechanism to handle null values and empty strings.
+ * {@link SimpleStringConverter}
+ */
+public class SimpleStringConverterDemo extends Application {
+
+ public record Task(String description, LocalDate dueDate) {
+ }
+
+ @Override
+ public void start(Stage primaryStage) {
+ // Create a ComboBox and populate it with Task objects
+ ComboBox comboBox = new ComboBox<>();
+ comboBox.getItems().addAll(
+ new Task("Task 1", LocalDate.now().plusWeeks(3)),
+ new Task("Task 2", LocalDate.now().plusWeeks(5)),
+ new Task("Task 3", LocalDate.now().plusWeeks(6))
+ );
+ comboBox.getSelectionModel().selectFirst();
+
+ // The traditional way to set a StringConverter on a ComboBox
+ // comboBox.setConverter(new StringConverter() {
+ // @Override
+ // public String toString(Task object) {
+ // if (object != null) {
+ // return object.description() + " [Due: " + object.dueDate() +"]";
+ // }
+ // return "";
+ // }
+ //
+ // @Override
+ // public Task fromString(String string) {
+ // return null;
+ // }
+ // });
+
+ // Set the converter to use SimpleStringConverter with the default title case formatting
+ comboBox.setConverter(new SimpleStringConverter<>(task -> task.description() + " [Due: " + task.dueDate() + "]", ""));
+
+ // Create a VBox layout and add the ComboBox to it
+ Label label = new Label("Select a status:");
+ label.setFont(new Font(16));
+ VBox vbox = new VBox(15, label, comboBox);
+ vbox.setPadding(new Insets(15));
+ vbox.setAlignment(Pos.CENTER);
+ Scene scene = new Scene(vbox, 300, 200);
+
+ // Configure and show the primary stage
+ primaryStage.setTitle("SimpleStringConverter Demo");
+ primaryStage.setScene(scene);
+ primaryStage.show();
+ }
+
+ public static void main(String[] args) {
+ launch(args);
+ }
+}
diff --git a/gemsfx-demo/src/main/java/module-info.java b/gemsfx-demo/src/main/java/module-info.java
index 67a6fd6f..1a712f5f 100644
--- a/gemsfx-demo/src/main/java/module-info.java
+++ b/gemsfx-demo/src/main/java/module-info.java
@@ -19,4 +19,5 @@
exports com.dlsc.gemsfx.demo;
exports com.dlsc.gemsfx.demo.binding;
+ exports com.dlsc.gemsfx.demo.util;
}
\ No newline at end of file
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/EnumStringConverter.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/EnumStringConverter.java
new file mode 100644
index 00000000..fa864e56
--- /dev/null
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/EnumStringConverter.java
@@ -0,0 +1,65 @@
+package com.dlsc.gemsfx.util;
+
+import javafx.util.Callback;
+
+/**
+ * A specialized StringConverter implementation for Enum types.
+ * This converter provides a default mechanism to format Enum values
+ * in a title case, replacing underscores with spaces and capitalizing
+ * the first letter of each word. If the enum value is null, it returns an empty string.
+ *
+ *
+ * This class extends SimpleStringConverter and leverages EnumUtil to provide
+ * a default formatting for enum values. It can also accept custom callbacks for
+ * more specific conversion requirements.
+ *
+ *
+ * Usage Example:
+ * Default usage with title case formatting:
+ * {@code
+ * ComboBox comboBox = new ComboBox<>();
+ * comboBox.setConverter(new EnumStringConverter<>());
+ * }
+ *
+ * Custom callback for specific formatting:
+ * {@code
+ * ComboBox comboBox = new ComboBox<>();
+ * comboBox.setConverter(new EnumStringConverter<>(myEnum -> "Custom format: " + myEnum.name()));
+ * }
+ *
+ * @param the type of the Enum to be converted.
+ */
+public class EnumStringConverter> extends SimpleStringConverter {
+
+ /**
+ * Converts an enum value to title case, replacing underscores with spaces and
+ * capitalizing the first letter of each word. If the enum value is null, returns an empty string.
+ * Example: 1. null -> ""
+ *
Example: 2. MY_ENUM_VALUE -> My Enum Value
+ */
+ public EnumStringConverter() {
+ this(EnumUtil::formatEnumNameAsTitleCase);
+ }
+
+ /**
+ * Constructor that accepts a custom callback for converting enum values to strings.
+ * The provided callback should handle conversion from enum value to String, including any necessary null handling.
+ *
+ * @param valueToStringCallback The callback to convert enum value to a String.
+ */
+ public EnumStringConverter(Callback valueToStringCallback) {
+ super(valueToStringCallback);
+ }
+
+ /**
+ * Constructor that accepts a custom callback for converting non-null enum values to strings and a default string
+ * to return if the enum value is null.
+ *
+ * @param nonNullValueCallback The callback to convert non-null enum value to a String.
+ * @param nullDefaultValue The default String value to return if the enum value is null.
+ */
+ public EnumStringConverter(Callback nonNullValueCallback, String nullDefaultValue) {
+ super(nonNullValueCallback, nullDefaultValue);
+ }
+
+}
\ No newline at end of file
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/EnumUtil.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/EnumUtil.java
new file mode 100644
index 00000000..9e997223
--- /dev/null
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/EnumUtil.java
@@ -0,0 +1,185 @@
+package com.dlsc.gemsfx.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Utility class for working with enums.
+ * formatEnumNameAsCapitalized: MY_ENUM_VALUE -> My enum value
+ *
formatEnumNameAsTitleCase: MY_ENUM_VALUE -> My Enum Value
+ *
formatEnumNameAsSpacedWords: MY_ENUM_VALUE -> MY ENUM VALUE
+ *
convertToStyleClassName: MY_ENUM_VALUE -> my-enum-value
+ */
+public class EnumUtil {
+
+ private EnumUtil() {
+ }
+
+ /**
+ * Converts a string representation of an enum name to a capitalized format,
+ * replacing underscores with spaces and making the rest lowercase.
+ * If the input string is null, returns an empty string.
+ *
+ * @param enumValue The enum value to convert.
+ * @return A capitalized string representation of the enum name.
+ *
Example: 1. null -> ""
+ *
Example: 2. MY_ENUM_VALUE -> My enum value
+ */
+ public static > String formatEnumNameAsCapitalized(T enumValue) {
+ return formatEnumNameAsCapitalized(enumValue, "");
+ }
+
+ /**
+ * Converts a string representation of an enum name to a capitalized format,
+ * replacing underscores with spaces and making the rest lowercase.
+ * If the input string is null, returns the specified default value.
+ *
+ * @param enumValue The enum value to convert.
+ * @param nullDefaultValue The default value to return if the input is null.
+ * @return A capitalized string representation of the enum name.
+ * Example: 1. null -> nullDefaultValue
+ *
Example: 2. Example: MY_ENUM_VALUE -> My enum value
+ */
+ public static > String formatEnumNameAsCapitalized(T enumValue, String nullDefaultValue) {
+ return enumValue == null ? nullDefaultValue : formatEnumNameAsCapitalized(enumValue.name());
+ }
+
+ /**
+ * Converts a string representation of an enum name to a capitalized format,
+ * replacing underscores with spaces and making the rest lowercase.
+ * If the input string is null, returns an empty string.
+ *
+ * @param enumName The enum name to convert.
+ * @return A capitalized string representation of the enum name.
+ * Example: 1. null -> ""
+ *
Example: 2. Example: MY_ENUM_VALUE -> My enum value
+ */
+ public static > String formatEnumNameAsCapitalized(String enumName) {
+ return enumName == null ? "" : StringUtils.capitalize(enumName.replace("_", " ").toLowerCase());
+ }
+
+ /**
+ * Converts an enum value to title case, replacing underscores with spaces and
+ * capitalizing the first letter of each word. If the enum value is null, returns an empty string.
+ *
+ * @param enumValue The enum value to be formatted.
+ * @return A title-cased string representation of the enum value.
+ * Example: 1. null -> ""
+ *
Example: 2. MY_ENUM_VALUE -> My Enum Value
+ */
+ public static > String formatEnumNameAsTitleCase(T enumValue) {
+ return formatEnumNameAsTitleCase(enumValue, "");
+ }
+
+ /**
+ * Converts an enum value to title case, replacing underscores with spaces and
+ * capitalizing the first letter of each word. If the enum value is null, returns the specified default value.
+ *
+ * @param enumValue The enum value to be formatted.
+ * @param nullDefaultValue The default value to return if the input is null.
+ * @return A title-cased string representation of the enum value.
+ * Example: 1. null -> nullDefaultValue
+ *
Example: 2. MY_ENUM_VALUE -> My Enum Value
+ */
+ public static > String formatEnumNameAsTitleCase(T enumValue, String nullDefaultValue) {
+ return formatEnumNameAsTitleCase(enumValue == null ? null : enumValue.name(), nullDefaultValue);
+ }
+
+ /**
+ * Converts an enum value to title case, replacing underscores with spaces and
+ * capitalizing the first letter of each word. If the enum value is null, returns an empty string.
+ *
+ * @param enumName The string representation of the enum value to be formatted.
+ * @return A title-cased string representation of the enum value.
+ * Example: 1. null -> ""
+ *
Example: 2. MY_ENUM_VALUE -> My Enum Value
+ */
+ public static > String formatEnumNameAsTitleCase(String enumName) {
+ return formatEnumNameAsTitleCase(enumName, "");
+ }
+
+ /**
+ * Converts an enum value to title case, replacing underscores with spaces and
+ * capitalizing the first letter of each word. If the enum value is null, returns the specified default value.
+ *
+ * @param enumName The string representation of the enum value to be formatted.
+ * @param nullDefaultValue The default value to return if the input is null.
+ * @return A title-cased string representation of the enum value.
+ * Example: 1. null -> nullDefaultValue
+ *
Example: 2. MY_ENUM_VALUE -> My Enum Value
+ */
+ public static > String formatEnumNameAsTitleCase(String enumName, String nullDefaultValue) {
+ if (enumName == null) {
+ return nullDefaultValue;
+ }
+
+ // Replace underscores with spaces and convert to lower case
+ String lowerCased = enumName.replace("_", " ").toLowerCase();
+
+ // Split the string into words
+ String[] words = StringUtils.split(lowerCased);
+
+ // Use StringBuilder to build the final string
+ StringBuilder result = new StringBuilder();
+ for (String word : words) {
+ if (!result.isEmpty()) {
+ result.append(" ");
+ }
+ // Capitalize the first letter of each word and append to result
+ result.append(StringUtils.capitalize(word));
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Replaces underscores in the string representation of an enum name with spaces.
+ * Does not change letter case. If the input string is null, returns an empty string.
+ *
+ * @param enumValue The enum value to be formatted.
+ * @return A string representation of the enum name with underscores replaced by spaces.
+ * Example: 1. null -> ""
+ *
Example: 2. MY_ENUM_VALUE -> MY ENUM VALUE
+ */
+ public static > String formatEnumNameAsSpacedWords(T enumValue) {
+ return enumValue == null ? "" : enumValue.name().replace("_", " ");
+ }
+
+ /**
+ * Replaces underscores in the string representation of an enum name with spaces.
+ * Does not change letter case. If the input string is null, returns an empty string.
+ *
+ * @param enumName The string representation of the enum name to be formatted.
+ * @return A string representation of the enum name with underscores replaced by spaces.
+ * Example: 1. null -> ""
+ *
Example: 2. MY_ENUM_VALUE -> MY ENUM VALUE
+ */
+ public static > String formatEnumNameAsSpacedWords(String enumName) {
+ return enumName == null ? "" : enumName.replace("_", " ");
+ }
+
+ /**
+ * Converts the enum name to a lower case string, replacing underscores with hyphens,
+ * suitable for use as a CSS class name. This method does not accept null values for enumValue.
+ *
+ * @param enumValue The enum value to be converted. Must not be null.
+ * @return A string suitable for use as a CSS class name.
+ * Example: MY_ENUM_VALUE -> my-enum-value
+ */
+ public static > String convertToStyleClassName(T enumValue) {
+ return enumValue.name().toLowerCase().replace("_", "-");
+ }
+
+ public static > String[] convertAllToStylesClassName(Class enumClass) {
+ T[] enumConstants = enumClass.getEnumConstants();
+ return convertAllToStylesClassName(enumConstants);
+ }
+
+ public static > String[] convertAllToStylesClassName(T[] enumValues) {
+ String[] styles = new String[enumValues.length];
+ for (int i = 0; i < enumValues.length; i++) {
+ styles[i] = convertToStyleClassName(enumValues[i]);
+ }
+ return styles;
+ }
+
+}
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/SimpleStringConverter.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/SimpleStringConverter.java
new file mode 100644
index 00000000..338858e2
--- /dev/null
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/SimpleStringConverter.java
@@ -0,0 +1,99 @@
+package com.dlsc.gemsfx.util;
+
+import javafx.util.Callback;
+import javafx.util.StringConverter;
+
+import java.util.Optional;
+
+/**
+ * A generic StringConverter implementation primarily used for displaying objects in the UI.
+ * This class provides flexible mechanisms for converting objects to Strings using custom callbacks.
+ * It also supports handling null values by returning a default string for null values.
+ *
+ *
+ * This converter is typically used to format objects as strings for display purposes, with optional
+ * handling for null values. The conversion from string back to object is not usually required,
+ * hence the {@link #fromString(String)} method returns null.
+ *
+ *
+ * Usage Example:
+ * Before using SimpleStringConverter:
+ * {@code
+ * comboBox.setConverter(new StringConverter<>() {
+ * @Override
+ * public String toString(Status status) {
+ * if (status != null) {
+ * return status.getDescription();
+ * }
+ * return "";
+ * }
+ *
+ * @Override
+ * public Status fromString(String string) {
+ * return null;
+ * }
+ * });
+ * }
+ *
+ * After using SimpleStringConverter:
+ * {@code
+ * comboBox.setConverter(new SimpleStringConverter<>(Status::getDescription, ""));
+ * }
+ *
+ * @param the type of the object to be converted.
+ */
+public class SimpleStringConverter extends StringConverter {
+ private final Callback valueToStringCallback;
+
+ public SimpleStringConverter() {
+ this(Object::toString, "");
+ }
+
+ /**
+ * Constructor that requires callers to handle null values themselves.
+ * The provided callback should handle conversion from value to String,
+ * including any necessary null handling.
+ *
+ * @param valueToStringCallback The callback to convert value to a String.
+ */
+ public SimpleStringConverter(Callback valueToStringCallback) {
+ this.valueToStringCallback = valueToStringCallback;
+ }
+
+ /**
+ * Constructor that automatically handles null values by returning a default null value string.
+ * If the value is null, the specified nullDefaultValue is returned instead of throwing an error or returning null.
+ *
+ * @param nonNullValueCallback The callback to convert non-null value to a String.
+ * @param nullDefaultValue The default String value to return if the value is null.
+ */
+ public SimpleStringConverter(Callback nonNullValueCallback, String nullDefaultValue) {
+ this.valueToStringCallback = value -> Optional.ofNullable(value)
+ .map(nonNullValueCallback::call)
+ .orElse(nullDefaultValue);
+ }
+
+ @Override
+ public String toString(T object) {
+ if (this.valueToStringCallback != null && object != null) {
+ return this.valueToStringCallback.call(object);
+ }
+ return "";
+ }
+
+ /**
+ * This method is not implemented and always returns null.
+ *
+ *
+ * Since the primary use of this converter is to display objects as strings in the UI,
+ * converting strings back to objects is not required. Therefore, this method simply returns null.
+ *
+ *
+ * @param s the string to be converted to an object.
+ * @return always returns null.
+ */
+ @Override
+ public T fromString(String s) {
+ return null;
+ }
+}
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/UIUtil.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/UIUtil.java
new file mode 100644
index 00000000..f4247575
--- /dev/null
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/UIUtil.java
@@ -0,0 +1,202 @@
+package com.dlsc.gemsfx.util;
+
+
+import javafx.geometry.Insets;
+import javafx.scene.Node;
+import javafx.scene.input.Clipboard;
+import javafx.scene.input.ClipboardContent;
+import javafx.scene.input.MouseButton;
+import javafx.scene.input.MouseEvent;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+public class UIUtil {
+
+ private UIUtil() {
+ }
+
+ /**
+ * Adds a style class to a node if it is not already present.
+ *
+ * @param node The node to add the style class to.
+ * @param styleClass The style class to add.
+ */
+ public static void addClassIfAbsent(Node node, String styleClass) {
+ Optional.ofNullable(node).ifPresent(n -> {
+ if (!n.getStyleClass().contains(styleClass)) {
+ n.getStyleClass().add(styleClass);
+ }
+ });
+ }
+
+ /**
+ * Adds a list of style classes to a node if they are not already present.
+ *
+ * @param node The node to add the style classes to.
+ * @param styleClasses The style classes to add.
+ */
+ public static void addClassesIfAbsent(Node node, String... styleClasses) {
+ List list = Arrays.stream(styleClasses)
+ .filter(styleClass -> !node.getStyleClass().contains(styleClass))
+ .toList();
+ node.getStyleClass().addAll(list);
+ }
+
+ /**
+ * Toggles a style class on a node.
+ * If the style class is present, it is removed.
+ * If it is not present, it is added.
+ *
+ * @param node The node to toggle the style on.
+ * @param styleClass The style class to add or remove.
+ */
+ public static void toggleClass(Node node, String styleClass) {
+ if (node.getStyleClass().contains(styleClass)) {
+ node.getStyleClass().remove(styleClass);
+ } else {
+ node.getStyleClass().add(styleClass);
+ }
+ }
+
+ /**
+ * Toggles a style class on a node based on a condition.
+ * If the condition is true, the style class is added.
+ * If the condition is false, the style class is removed.
+ *
+ * @param node The node to toggle the style on.
+ * @param styleClass The style class to add or remove.
+ * @param condition The condition that determines whether to add or remove the style.
+ */
+ public static void toggleClassOnCondition(Node node, String styleClass, boolean condition) {
+ if (condition) {
+ addClassIfAbsent(node, styleClass);
+ } else {
+ node.getStyleClass().remove(styleClass);
+ }
+ }
+
+
+ /**
+ * Optimizes style updates for a given node by first adding a specified style to ensure it's present,
+ * and then removing other specified styles, except the newly added one. This approach helps in preventing
+ * unnecessary UI flicker by avoiding the removal of a style that needs to be present.
+ *
+ * @param node The node whose styles are to be updated.
+ * @param stylesToRemove A list of styles to be removed from the node, except for the styleToAdd.
+ * @param styleToAdd The style to be added to the node, if it's not already present.
+ */
+ public static void updateStyles(Node node, List stylesToRemove, String styleToAdd) {
+ // Add the style if it's not already present
+ addClassIfAbsent(node, styleToAdd);
+
+ // Remove the specified styles except the style to be added
+ node.getStyleClass().removeAll(stylesToRemove.stream()
+ .filter(style -> !style.equals(styleToAdd))
+ .toList());
+ }
+
+ /**
+ * Optimizes style updates for a given node by first adding a specified style to ensure it's present,
+ * and then removing other specified styles, except the newly added one. This approach helps in preventing
+ * unnecessary UI flicker by avoiding the removal of a style that needs to be present.
+ *
+ * @param node The node whose styles are to be updated.
+ * @param stylesToRemove An array of styles to be removed from the node, except for the styleToAdd.
+ * @param styleToAdd The style to be added to the node, if it's not already present.
+ */
+ public static void updateStyles(Node node, String[] stylesToRemove, String styleToAdd) {
+ updateStyles(node, Arrays.asList(stylesToRemove), styleToAdd);
+ }
+
+ /**
+ * Applies a style derived from an enum value to a Node, removing other styles from the same enum class.
+ *
+ * @param node The Node to update.
+ * @param enumValue The enum value determining the style to apply.
+ * Example If Dir.UP is passed, add "up" style and removes {"down", "left", "right"} styles.
+ */
+ public static > void updateStyleFromEnum(Node node, T enumValue) {
+ updateStyles(node, EnumUtil.convertAllToStylesClassName(enumValue.getClass()), EnumUtil.convertToStyleClassName(enumValue));
+ }
+
+ /**
+ * Removes all styles associated with a given enum class from a Node.
+ *
+ * @param node The Node to clear styles from.
+ * @param enumClass The enum class whose associated styles will be removed.
+ * Example If Dir.class is passed, removes all styles {"up","down","left", "right"}.
+ */
+ public static > void clearStylesByEnum(Node node, Class enumClass) {
+ node.getStyleClass().removeAll(EnumUtil.convertAllToStylesClassName(enumClass));
+ }
+
+ /**
+ * Returns the height of the top and bottom insets combined.
+ */
+ public static double getInsetsHeight(Insets insets) {
+ return insets == null ? 0 : insets.getTop() + insets.getBottom();
+ }
+
+ /**
+ * Returns the width of the left and right insets combined.
+ */
+ public static double getInsetsWidth(Insets insets) {
+ return insets == null ? 0 : insets.getLeft() + insets.getRight();
+ }
+
+ /**
+ * Converts a camelCase string to a natural language expression.
+ *
+ * This method is designed to transform strings formatted in camelCase,
+ * commonly used in programming, into a more readable format that is
+ * suitable for display in user interfaces. It inserts spaces between
+ * words and ensures that acronyms remain capitalized while the first
+ * letter of the resulting string is also capitalized.
+ *
+ *
+ * Example:
+ * "ONSCode" becomes "ONS Code"
+ * "customerServiceOrder" becomes "Customer Service Order"
+ *
+ *
+ * @param camelCaseString The camelCase string to be converted.
+ * @return A string in natural language format, with appropriate spaces and capitalization.
+ */
+ public static String camelCaseToNaturalCase(String camelCaseString) {
+ return StringUtils.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(camelCaseString), " "));
+ }
+
+ /**
+ * Copies the specified content to the clipboard.
+ *
+ * @param copyContent The content to be copied to the clipboard.
+ */
+ public static void copyToClipboard(String copyContent) {
+ ClipboardContent content = new ClipboardContent();
+ content.putString(copyContent);
+ Clipboard.getSystemClipboard().setContent(content);
+ }
+
+ /**
+ * Determines if the given mouse event is a single primary button click
+ * that hasn't moved since it was pressed.
+ *
+ * This method checks if the mouse event satisfies the following conditions:
+ *
+ * - The mouse button is the primary button (usually the left button).
+ * - The click count is exactly one.
+ * - The mouse has not moved since it was pressed.
+ *
+ *
+ * @param event The mouse event to check. Must not be null.
+ * @return {@code true} if the event is a single stable primary button click, {@code false} otherwise.
+ * @throws NullPointerException if the event is null.
+ */
+ public static boolean clickOnNode(MouseEvent event) {
+ return event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 1 && event.isStillSincePress();
+ }
+
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 511abe14..64a2f564 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,7 @@
+
org.controlsfx
controlsfx