From 9d4ed88e3d64065630c3e645c2b7b8c56b94128b Mon Sep 17 00:00:00 2001
From: Dirk Lemmermann
Date: Thu, 30 May 2024 17:26:18 +0200
Subject: [PATCH] Various changes, especially related to the history manager.
---
.../dlsc/gemsfx/demo/HistoryManagerApp.java | 70 +++--
.../com/dlsc/gemsfx/demo/SearchFieldApp.java | 4 +-
.../dlsc/gemsfx/demo/SearchTextFieldApp.java | 6 +-
.../java/com/dlsc/gemsfx/HistoryButton.java | 7 +-
.../com/dlsc/gemsfx/util/HistoryManager.java | 175 +++++++++----
.../gemsfx/util/InMemoryHistoryManager.java | 18 ++
.../util/PreferencesHistoryManager.java | 246 ++----------------
.../gemsfx/util/StringHistoryManager.java | 26 +-
.../com/dlsc/gemsfx/history-button.css | 6 +-
9 files changed, 208 insertions(+), 350 deletions(-)
create mode 100644 gemsfx/src/main/java/com/dlsc/gemsfx/util/InMemoryHistoryManager.java
diff --git a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/HistoryManagerApp.java b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/HistoryManagerApp.java
index 2ce292d4..73c43375 100644
--- a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/HistoryManagerApp.java
+++ b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/HistoryManagerApp.java
@@ -3,6 +3,7 @@
import com.dlsc.gemsfx.HistoryButton;
import com.dlsc.gemsfx.Spacer;
import com.dlsc.gemsfx.util.HistoryManager;
+import com.dlsc.gemsfx.util.InMemoryHistoryManager;
import com.dlsc.gemsfx.util.PreferencesHistoryManager;
import com.dlsc.gemsfx.util.StringHistoryManager;
import javafx.application.Application;
@@ -36,9 +37,9 @@ public void start(Stage primaryStage) throws Exception {
TabPane tabPane = new TabPane();
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
tabPane.getTabs().addAll(
- new Tab("Basic", basicDemo()),
- new Tab("Advanced", advancedDemo()),
- new Tab("Other", otherDemo())
+ new Tab("In-Memory History Manager", inMemoryDemmo()),
+ new Tab("String History Manager", stringHistoryDemo()),
+ new Tab("Preferences History Manager)", prefsDemo())
);
primaryStage.setScene(new Scene(tabPane, 800, 600));
@@ -46,22 +47,14 @@ public void start(Stage primaryStage) throws Exception {
primaryStage.show();
}
- private Node basicDemo() {
+ private Node inMemoryDemmo() {
TextField textField = new TextField();
HistoryButton historyButton = new HistoryButton<>(textField);
- // Tips: We can set the delimiter and preferencesKey when creating, otherwise use the default value.
- // StringHistoryManager historyManager = new StringHistoryManager(";", "history-records",
- // Preferences.userNodeForPackage(HistoryManagerApp.class).node("simpleTextField"));
-
- StringHistoryManager historyManager = new StringHistoryManager();
-
- // Tips: If we want to persist the history after the application restarts, we need to set the preferences.
- // historyManager.setPreferences(Preferences.userNodeForPackage(HistoryManagerApp.class).node("simpleTextField"));
-
- // Tips: If we want to enable the history function, we need to set the history manager.
+ InMemoryHistoryManager historyManager = new InMemoryHistoryManager<>();
historyButton.setHistoryManager(historyManager);
+
historyButton.setOnItemSelected(item -> {
historyButton.hidePopup();
textField.setText(item);
@@ -92,19 +85,14 @@ private Node basicDemo() {
/**
* Creates a text field with a history button.
*/
- private Node advancedDemo() {
+ private Node stringHistoryDemo() {
TextField textField = new TextField();
- StringHistoryManager historyManager = new StringHistoryManager();
- // Tips: You can set the delimiter and preferencesKey when creating, otherwise use the default value.
- // PreferencesHistoryManager historyManager = new PreferencesHistoryManager(";", "save-items");
-
- // Tips: If you want to persist the history after the application restarts, Please set the preferences.
- historyManager.setPreferences(Preferences.userNodeForPackage(HistoryManagerApp.class).node("textField"));
- // Optional: Set the maximum history size.default is 30.
+ StringHistoryManager historyManager = new StringHistoryManager(Preferences.userNodeForPackage(HistoryManagerApp.class), "advanced-demo");
historyManager.setMaxHistorySize(10);
+
// Optional: if the history is empty, set some default values
- if (historyManager.getAll().isEmpty()) {
+ if (historyManager.getAllUnmodifiable().isEmpty()) {
historyManager.set(List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"));
}
@@ -128,7 +116,7 @@ private Node advancedDemo() {
historyButton.hidePopup();
});
clearAll.managedProperty().bind(clearAll.visibleProperty());
- clearAll.visibleProperty().bind(Bindings.isNotEmpty(historyManager.getAll()));
+ clearAll.visibleProperty().bind(Bindings.isNotEmpty(historyManager.getAllUnmodifiable()));
leftBox.getChildren().addAll(group, new Spacer(), clearAll);
leftBox.setAlignment(Pos.CENTER);
@@ -162,7 +150,7 @@ private Node advancedDemo() {
/**
* Creates a list view with a history button.
*/
- private Node otherDemo() {
+ private Node prefsDemo() {
ListView listView = new ListView<>();
listView.getItems().addAll(
new Student("John", 90),
@@ -177,20 +165,22 @@ private Node otherDemo() {
new Student("David", 83)
);
- PreferencesHistoryManager historyManager = new PreferencesHistoryManager<>(
- new StringConverter<>() {
- @Override
- public String toString(Student object) {
- return object.name() + " : " + object.score();
- }
-
- @Override
- public Student fromString(String string) {
- String[] parts = string.split(" : ");
- return new Student(parts[0], Integer.parseInt(parts[1]));
- }
- }
- );
+ StringConverter converter = new StringConverter<>() {
+ @Override
+ public String toString(Student object) {
+ return object.name() + " : " + object.score();
+ }
+
+ @Override
+ public Student fromString(String string) {
+ String[] parts = string.split(" : ");
+ return new Student(parts[0], Integer.parseInt(parts[1]));
+ }
+ };
+
+ Preferences preferences = Preferences.userNodeForPackage(HistoryManagerApp.class);
+
+ PreferencesHistoryManager historyManager = new PreferencesHistoryManager<>(preferences, "list", converter);
listView.setOnMouseClicked(e -> {
if (e.getClickCount() == 2) {
@@ -198,8 +188,6 @@ public Student fromString(String string) {
}
});
- historyManager.setPreferences(Preferences.userNodeForPackage(HistoryManagerApp.class).node("list"));
-
HistoryButton historyButton = new HistoryButton<>();
historyButton.setHistoryManager(historyManager);
historyButton.setText("History");
diff --git a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchFieldApp.java b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchFieldApp.java
index aae33573..b91a7e9c 100644
--- a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchFieldApp.java
+++ b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchFieldApp.java
@@ -95,11 +95,11 @@ public void start(Stage primaryStage) throws Exception {
enableHistoryBox.selectedProperty().addListener((obs, oldVal, newVal) -> {
if (newVal) {
if (field.getHistoryManager() == null) {
- historyManager = new StringHistoryManager(Preferences.userNodeForPackage(SearchFieldApp.class).node("field"));
+ historyManager = new StringHistoryManager(Preferences.userNodeForPackage(SearchFieldApp.class), "search-field-id");
// Optional: Set the maximum history size. default is 30.
historyManager.setMaxHistorySize(20);
// Optional: If the history items is empty, we can set a default history list.
- if (historyManager.getAll().isEmpty()) {
+ if (historyManager.getAllUnmodifiable().isEmpty()) {
historyManager.set(List.of("United Kingdom", "Switzerland"));
}
}
diff --git a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchTextFieldApp.java b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchTextFieldApp.java
index c57bac2c..761eff6f 100644
--- a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchTextFieldApp.java
+++ b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/SearchTextFieldApp.java
@@ -38,8 +38,8 @@ public void start(Stage primaryStage) throws Exception {
enableHistoryBox.selectedProperty().addListener((obs, oldVal, newVal) -> {
if (newVal) {
if (stringHistoryManager == null) {
- Preferences preferences = Preferences.userNodeForPackage(SearchTextFieldApp.class).node("field1");
- stringHistoryManager = new StringHistoryManager(preferences);
+ Preferences preferences = Preferences.userNodeForPackage(SearchTextFieldApp.class);
+ stringHistoryManager = new StringHistoryManager(preferences, "search-text-field-id");
}
field.setHistoryManager(stringHistoryManager);
} else {
@@ -86,7 +86,7 @@ public void start(Stage primaryStage) throws Exception {
Button removeHistoryButton = new Button("Remove First History Item");
removeHistoryButton.setMaxWidth(Double.MAX_VALUE);
- removeHistoryButton.setOnAction(e -> Optional.ofNullable(field.getHistoryManager()).ifPresent(historyManager -> historyManager.remove(historyManager.getAll().get(0))));
+ removeHistoryButton.setOnAction(e -> Optional.ofNullable(field.getHistoryManager()).ifPresent(historyManager -> historyManager.remove(historyManager.getAllUnmodifiable().get(0))));
Button clearButton = new Button("Clear History");
clearButton.setMaxWidth(Double.MAX_VALUE);
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/HistoryButton.java b/gemsfx/src/main/java/com/dlsc/gemsfx/HistoryButton.java
index 5e4f74fb..ee7f747c 100644
--- a/gemsfx/src/main/java/com/dlsc/gemsfx/HistoryButton.java
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/HistoryButton.java
@@ -1,6 +1,7 @@
package com.dlsc.gemsfx;
import com.dlsc.gemsfx.util.HistoryManager;
+import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.css.PseudoClass;
@@ -392,15 +393,15 @@ private ListView createListView() {
HistoryManager historyManager = getHistoryManager();
if (historyManager != null) {
- Bindings.bindContent(listView.getItems(), historyManager.getAll());
+ Bindings.bindContent(listView.getItems(), historyManager.getAllUnmodifiable());
}
historyManagerProperty().addListener((observable, oldManager, newManager) -> {
if (oldManager != null) {
- Bindings.unbindContent(listView.getItems(), oldManager.getAll());
+ Bindings.unbindContent(listView.getItems(), oldManager.getAllUnmodifiable());
}
if (newManager != null) {
- Bindings.bindContent(listView.getItems(), newManager.getAll());
+ Bindings.bindContent(listView.getItems(), newManager.getAllUnmodifiable());
}
});
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/HistoryManager.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/HistoryManager.java
index 37a622ad..f9eda503 100644
--- a/gemsfx/src/main/java/com/dlsc/gemsfx/util/HistoryManager.java
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/HistoryManager.java
@@ -1,114 +1,179 @@
package com.dlsc.gemsfx.util;
+import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleIntegerProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
+import java.util.Objects;
import java.util.function.Predicate;
+import java.util.logging.Logger;
/**
- * The HistoryManager interface defines the standard operations to manage history storage
+ * The HistoryManager class defines the standard operations to manage history storage
* for any type of items, allowing for implementation of various data storage mechanisms.
*
* @param the type of items stored in the history
*/
-public interface HistoryManager {
+public abstract class HistoryManager {
- /**
- * Adds a single item to the history storage.
- * If the item already exists, its position is updated.
- *
- * @param item The history item to be added.
- */
- void add(T item);
+ private static final Logger LOG = Logger.getLogger(HistoryManager.class.getName());
- /**
- * Adds multiple items to the history storage.
- * Duplicates in the input list are not added twice.
- *
- * @param items The list of history items to be added.
- */
- void add(List items);
+ private static final int DEFAULT_MAX_HISTORY_SIZE = 30;
+
+ private final ObservableList history = FXCollections.observableArrayList();
+
+ public HistoryManager() {
+ maxHistorySizeProperty().addListener(it -> {
+ // Check if the max history size is negative. If so, log a warning.
+ if (getMaxHistorySize() < 0) {
+ LOG.warning("Max history size must be greater than or equal to 0. ");
+ }
+ trimHistory();
+ });
+
+ unmodifiableHistory.addListener((Observable it) -> storeHistory());
+ }
+
+ protected abstract void loadHistory();
+
+ protected abstract void storeHistory();
/**
- * Sets the history of the HistoryManager with the provided list of items.
+ * Sets the history of the HistoryManager with the provided list of strings.
* The method ensures that duplicates are removed from the list.
*
- * @param items the list of items representing the history
+ * @param history the list of strings representing the history
*/
- void set(List items);
+ public final void set(List history) {
+ this.history.setAll(convertToUniqueList(history));
+ }
/**
- * Removes a single item from the history storage.
+ * Adds the given item to the history. The method ensures that duplicates will not be added.
*
- * @param item The history item to be removed.
- * @return true if the item was successfully removed, false if the item was not found.
+ * @param item the item to add
*/
- boolean remove(T item);
+ public final void add(T item) {
+ if (item != null && getFilter().test(item)) {
+ history.remove(item);
+ history.add(0, item);
+ trimHistory();
+ }
+ }
/**
- * Removes multiple items from the history storage.
+ * Adds the given items to the history.
*
- * @param items The list of history items to be removed.
+ * @param items the items to add
*/
- void remove(List items);
+ public final void add(List items) {
+ List uniqueItems = convertToUniqueList(items);
+ if (!uniqueItems.isEmpty()) {
+ history.removeAll(uniqueItems);
+ history.addAll(0, uniqueItems);
+ trimHistory();
+ }
+ }
/**
- * Clears all items from the history storage.
+ * Removes the given item from the history.
+ *
+ * @param item the item to remove
+ * @return true if the item was removed, false otherwise
*/
- void clear();
+ public final boolean remove(T item) {
+ return history.remove(item);
+ }
/**
- * Retrieves all stored history items.
+ * Removes the given items from the history.
*
- * @return A list of all history items.
+ * @param items the items to remove
*/
- ObservableList getAll();
+ public final void remove(List items) {
+ history.removeAll(items);
+ }
/**
- * Returns the property object for the maximum history size. This property can be
- * used to bind the history size limit to UI components or to observe changes.
- *
- * @return The IntegerProperty representing the maximum number of history items allowed.
+ * Clears the history.
*/
- IntegerProperty maxHistorySizeProperty();
+ public final void clear() {
+ history.clear();
+ }
+
+ private final ObservableList unmodifiableHistory = FXCollections.unmodifiableObservableList(history);
/**
- * Gets the current maximum size of the history list.
- *
- * @return The current maximum number of items that can be stored in the history.
+ * Returns an unmodifiable list of the history.
*/
- int getMaxHistorySize();
+ public final ObservableList getAllUnmodifiable() {
+ return unmodifiableHistory;
+ }
+
+ private final IntegerProperty maxHistorySize = new SimpleIntegerProperty(this, "maxHistorySize", DEFAULT_MAX_HISTORY_SIZE);
/**
- * Sets the maximum size of the history list. If the current number of items
- * exceeds the specified size, items will be removed from the end of the list.
+ * The maximum number of items that the history will store. If the number of items exceeds this value, the oldest
+ * items will be removed.
*
- * @param maxHistorySize The maximum number of items to retain in the history.
+ * @return the maximum number of items in the history
*/
- void setMaxHistorySize(int maxHistorySize);
+ public final IntegerProperty maxHistorySizeProperty() {
+ return maxHistorySize;
+ }
+
+ public final int getMaxHistorySize() {
+ return maxHistorySize.get();
+ }
+
+ public final void setMaxHistorySize(int maxHistorySize) {
+ maxHistorySizeProperty().set(maxHistorySize);
+ }
+
+ private final ObjectProperty> filter = new SimpleObjectProperty<>(this, "filter", it -> true);
/**
- * Returns the property that holds the filter used when adding items to the history.
+ * Returns the property object for the filter used when adding items to the history.
* Only items that pass the filter will be added to the history.
*
- * @return the property containing the filter
+ * @return the property object for the filter
*/
- ObjectProperty> filterProperty();
+ public final ObjectProperty> filterProperty() {
+ return filter;
+ }
+
+ public final Predicate getFilter() {
+ return filter.get();
+ }
+
+ public final void setFilter(Predicate filter) {
+ this.filter.set(filter);
+ }
/**
- * Sets a filter to be used when adding items to the history. Only items that pass the
- * filter will be added to the history.
- *
- * @param filter The filter to apply.
+ * Trims the history list to ensure it does not exceed the maximum allowed size.
+ * If the current history size is greater than the maximum size, the method removes
+ * the extra elements from the history list.
*/
- void setFilter(Predicate filter);
+ private void trimHistory() {
+ int max = Math.max(0, getMaxHistorySize());
+ if (history.size() > max) {
+ history.remove(max, history.size());
+ }
+ }
/**
- * Gets the current filter used for adding items to the history.
+ * Converts a given list of strings to a unique list of strings. Filters out empty strings.
*
- * @return The current filter.
+ * @param history the list of strings to convert
+ * @return the converted unique list of strings
*/
- Predicate getFilter();
+ private List convertToUniqueList(List history) {
+ return history.stream().distinct().filter(Objects::nonNull).filter(getFilter()).limit(Math.max(0, getMaxHistorySize())).toList();
+ }
}
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/InMemoryHistoryManager.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/InMemoryHistoryManager.java
new file mode 100644
index 00000000..981638ab
--- /dev/null
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/InMemoryHistoryManager.java
@@ -0,0 +1,18 @@
+package com.dlsc.gemsfx.util;
+
+/**
+ * A simple history manager that does not persist its items anywhere. The history will
+ * always be clear after an application restart.
+ *
+ * @param the type of objects to store in the history list
+ */
+public class InMemoryHistoryManager extends HistoryManager {
+
+ @Override
+ protected void loadHistory() {
+ }
+
+ @Override
+ protected void storeHistory() {
+ }
+}
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/PreferencesHistoryManager.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/PreferencesHistoryManager.java
index 4ae465b0..cb11ec44 100644
--- a/gemsfx/src/main/java/com/dlsc/gemsfx/util/PreferencesHistoryManager.java
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/PreferencesHistoryManager.java
@@ -1,19 +1,13 @@
package com.dlsc.gemsfx.util;
-import javafx.beans.Observable;
-import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
import javafx.util.StringConverter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
-import java.util.function.Predicate;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
@@ -37,247 +31,51 @@
* @see HistoryManager
* @see StringConverter
*/
-public class PreferencesHistoryManager implements HistoryManager {
+public class PreferencesHistoryManager extends HistoryManager {
private static final Logger LOG = Logger.getLogger(PreferencesHistoryManager.class.getName());
- private static final int DEFAULT_MAX_HISTORY_SIZE = 30;
-
/**
* Using Unicode Record Separator as delimiter.
* This character is not likely to be used in the history items.
*/
- public static final String DEFAULT_DELIMITER = "␞";
+ public static String DELIMITER = "␞";
- /**
- * Default preferences key used to store history items.
- */
- public static final String DEFAULT_PREFERENCES_KEY = "history-items";
+ private final Preferences preferences;
- private final String delimiter;
- private final String preferencesKey;
- private final StringConverter converter;
+ private final String key;
- public PreferencesHistoryManager(StringConverter converter) {
- this(DEFAULT_DELIMITER, DEFAULT_PREFERENCES_KEY, converter);
- }
+ private final StringConverter converter;
- public PreferencesHistoryManager(String delimiter, String preferencesKey, StringConverter converter) {
- this.delimiter = Objects.requireNonNull(delimiter);
- this.preferencesKey = Objects.requireNonNull(preferencesKey);
+ public PreferencesHistoryManager(Preferences preferences, String key, StringConverter converter) {
+ this.preferences = Objects.requireNonNull(preferences);
+ this.key = Objects.requireNonNull(key);
this.converter = Objects.requireNonNull(converter);
-
loadHistory();
-
- maxHistorySizeProperty().addListener(it -> {
- // Check if the max history size is negative. If so, log a warning.
- if (getMaxHistorySize() < 0) {
- LOG.warning("Max history size must be greater than or equal to 0. ");
- }
- trimHistory();
- });
-
- unmodifiableHistory.addListener((Observable it) -> storeHistory());
- preferencesProperty().addListener(it -> loadHistory());
}
/**
* Stores the history items in the preferences.
*/
- private void storeHistory() {
- Preferences preferences = getPreferences();
- if (preferences != null) {
- String result = unmodifiableHistory.stream()
- .map(converter::toString)
- .collect(Collectors.joining(delimiter));
- preferences.put(preferencesKey, result);
- }
+ @Override
+ protected void storeHistory() {
+ String result = getAllUnmodifiable().stream()
+ .map(converter::toString)
+ .collect(Collectors.joining(DELIMITER));
+ preferences.put(key, result);
}
/**
* Loads the history items from the preferences.
*/
- private void loadHistory() {
- Preferences preferences = getPreferences();
- if (preferences != null) {
- String items = preferences.get(preferencesKey, "");
- if (StringUtils.isNotEmpty(items)) {
- String[] ary = items.split(delimiter);
- Arrays.stream(ary)
- .map(converter::fromString)
- .forEach(history::add);
- }
- }
- }
-
- private final ObservableList history = FXCollections.observableArrayList();
-
- /**
- * Sets the history of the HistoryManager with the provided list of strings.
- * The method ensures that duplicates are removed from the list.
- *
- * @param history the list of strings representing the history
- */
- public final void set(List history) {
- this.history.setAll(convertToUniqueList(history));
- }
-
- /**
- * Adds the given item to the history. The method ensures that duplicates will not be added.
- *
- * @param item the item to add
- */
- public final void add(T item) {
- if (item != null && getFilter().test(item)) {
- history.remove(item);
- history.add(0, item);
- trimHistory();
- }
- }
-
- /**
- * Adds the given items to the history.
- *
- * @param items the items to add
- */
- public final void add(List items) {
- List uniqueItems = convertToUniqueList(items);
- if (!uniqueItems.isEmpty()) {
- history.removeAll(uniqueItems);
- history.addAll(0, uniqueItems);
- trimHistory();
+ @Override
+ protected void loadHistory() {
+ String items = preferences.get(key, "");
+ if (StringUtils.isNotEmpty(items)) {
+ String[] ary = items.split(DELIMITER);
+ set(Arrays.stream(ary)
+ .map(converter::fromString)
+ .toList());
}
}
-
- /**
- * Removes the given item from the history.
- *
- * @param item the item to remove
- * @return true if the item was removed, false otherwise
- */
- public final boolean remove(T item) {
- return history.remove(item);
- }
-
- /**
- * Removes the given items from the history.
- *
- * @param items the items to remove
- */
- public final void remove(List items) {
- history.removeAll(items);
- }
-
- /**
- * Clears the history.
- */
- public final void clear() {
- history.clear();
- }
-
- private final ObservableList unmodifiableHistory = FXCollections.unmodifiableObservableList(history);
-
- /**
- * Returns an unmodifiable list of the history.
- */
- public final ObservableList getAll() {
- return unmodifiableHistory;
- }
-
- private final IntegerProperty maxHistorySize = new SimpleIntegerProperty(this, "maxHistorySize", DEFAULT_MAX_HISTORY_SIZE);
-
- /**
- * The maximum number of items that the history will store. If the number of items exceeds this value, the oldest
- * items will be removed.
- *
- * @return the maximum number of items in the history
- */
- public final IntegerProperty maxHistorySizeProperty() {
- return maxHistorySize;
- }
-
- public final int getMaxHistorySize() {
- return maxHistorySize.get();
- }
-
- public final void setMaxHistorySize(int maxHistorySize) {
- maxHistorySizeProperty().set(maxHistorySize);
- }
-
- private final ObjectProperty> filter = new SimpleObjectProperty<>(this, "filter", it -> true);
-
- /**
- * Returns the property object for the filter used when adding items to the history.
- * Only items that pass the filter will be added to the history.
- *
- * @return the property object for the filter
- */
- public final ObjectProperty> filterProperty() {
- return filter;
- }
-
- public final Predicate getFilter() {
- return filter.get();
- }
-
- public final void setFilter(Predicate filter) {
- this.filter.set(filter);
- }
-
- private final ObjectProperty preferences = new SimpleObjectProperty<>(this, "preferences");
-
- /**
- * Returns the property object representing the preferences used for persisting history records.
- * This property can be used to set or get the `Preferences` instance for storing history items.
- *
- * @return the property object representing the preferences
- */
- public final ObjectProperty preferencesProperty() {
- return preferences;
- }
-
- public final Preferences getPreferences() {
- return preferences.get();
- }
-
- public final void setPreferences(Preferences preferences) {
- this.preferences.set(preferences);
- }
-
- /**
- * Trims the history list to ensure it does not exceed the maximum allowed size.
- * If the current history size is greater than the maximum size, the method removes
- * the extra elements from the history list.
- */
- private void trimHistory() {
- int max = Math.max(0, getMaxHistorySize());
- if (history.size() > max) {
- history.remove(max, history.size());
- }
- }
-
- /**
- * Converts a given list of strings to a unique list of strings. Filters out empty strings.
- *
- * @param history the list of strings to convert
- * @return the converted unique list of strings
- */
- private List convertToUniqueList(List history) {
- return history.stream().distinct().filter(Objects::nonNull).filter(getFilter()).limit(Math.max(0, getMaxHistorySize())).toList();
- }
-
- /**
- * @return the delimiter used to separate history items
- */
- public final String getDelimiter() {
- return delimiter;
- }
-
- /**
- * @return the preferences key used to store history items
- */
- public final String getPreferencesKey() {
- return preferencesKey;
- }
-
}
diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/util/StringHistoryManager.java b/gemsfx/src/main/java/com/dlsc/gemsfx/util/StringHistoryManager.java
index eae92523..84f5f676 100644
--- a/gemsfx/src/main/java/com/dlsc/gemsfx/util/StringHistoryManager.java
+++ b/gemsfx/src/main/java/com/dlsc/gemsfx/util/StringHistoryManager.java
@@ -19,11 +19,11 @@
* Due to the limitations of the {@code Preferences} API, this manager is not suitable for
* scenarios involving large-scale data or complex data structures. It is optimized for
* lightweight history management tasks where history items are stored and retrieved
- * straightforwardly without transformation.
+ * in a straight forward fashion without transformation.
*
*
* Key features include:
- * - Persisting history in a simple, local manner using {@code Preferences}
+ * - Persisting history locally in a simple approach using the {@code Preferences} API
* - Adding items while ensuring uniqueness
* - Removing specific history items or clearing all history
* - Providing a read-only view of history items to external components
@@ -32,7 +32,7 @@
*/
public class StringHistoryManager extends PreferencesHistoryManager {
- private static final StringConverter DEFAULT_STRING_CONVERTER = new StringConverter<>() {
+ private static final StringConverter CONVERTER = new StringConverter<>() {
@Override
public String toString(String object) {
return object;
@@ -44,24 +44,8 @@ public String fromString(String string) {
}
};
- public StringHistoryManager() {
- super(DEFAULT_STRING_CONVERTER);
+ public StringHistoryManager(Preferences preferences, String key) {
+ super(preferences, key, CONVERTER);
setFilter(StringUtils::isNotEmpty);
}
-
- public StringHistoryManager(Preferences preferences) {
- this();
- setPreferences(preferences);
- }
-
- public StringHistoryManager(String delimiter, String preferencesKey) {
- super(delimiter, preferencesKey, DEFAULT_STRING_CONVERTER);
- setFilter(StringUtils::isNotEmpty);
- }
-
- public StringHistoryManager(String delimiter, String preferencesKey, Preferences preferences) {
- this(delimiter, preferencesKey);
- setPreferences(preferences);
- }
-
}
diff --git a/gemsfx/src/main/resources/com/dlsc/gemsfx/history-button.css b/gemsfx/src/main/resources/com/dlsc/gemsfx/history-button.css
index 423d2875..3bebd052 100644
--- a/gemsfx/src/main/resources/com/dlsc/gemsfx/history-button.css
+++ b/gemsfx/src/main/resources/com/dlsc/gemsfx/history-button.css
@@ -46,7 +46,7 @@
}
.history-popup > .content-pane > .history-list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:focused {
- -fx-background-color: transparent;
+ -fx-background: -fx-accent;
}
.history-popup > .content-pane > .history-list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected,
@@ -73,4 +73,8 @@
.history-popup > .content-pane > .history-list-view > .virtual-flow > .clipped-container > .sheet > .removable-list-cell:selected .remove-button .ikonli-font-icon,
.history-popup > .content-pane > .history-list-view > .virtual-flow > .clipped-container > .sheet > .removable-list-cell .remove-button:pressed .ikonli-font-icon {
-fx-icon-color: -fx-text-background-color;
+}
+
+.history-popup > .content-pane > .history-list-view > .virtual-flow > .clipped-container > .sheet > .removable-list-cell:focused .remove-button .ikonli-font-icon {
+ -fx-icon-color: -fx-selection-bar-text;
}
\ No newline at end of file