|
33 | 33 | import java.nio.charset.StandardCharsets; |
34 | 34 | import java.util.Arrays; |
35 | 35 | import java.util.HashMap; |
| 36 | +import java.util.List; |
36 | 37 | import java.util.Map; |
| 38 | +import java.util.Objects; |
| 39 | +import java.util.concurrent.CopyOnWriteArrayList; |
37 | 40 |
|
38 | 41 |
|
39 | 42 | /** |
@@ -76,6 +79,45 @@ public class Preferences { |
76 | 79 | static File preferencesFile; |
77 | 80 | static private boolean initialized = false; |
78 | 81 |
|
| 82 | + static private final List<ChangeListener> listeners = |
| 83 | + new CopyOnWriteArrayList<>(); |
| 84 | + |
| 85 | + |
| 86 | + /** |
| 87 | + * Callback for preference changes made through set() or unset(). |
| 88 | + * Loading (init or otherwise) does not fire events: listeners are for |
| 89 | + * reacting to changes, not for observing startup. |
| 90 | + */ |
| 91 | + public interface ChangeListener { |
| 92 | + /** |
| 93 | + * @param key the preference that changed |
| 94 | + * @param value the new value, or null if the key was removed |
| 95 | + */ |
| 96 | + void preferenceChanged(String key, String value); |
| 97 | + } |
| 98 | + |
| 99 | + |
| 100 | + static public void addChangeListener(ChangeListener listener) { |
| 101 | + listeners.add(listener); |
| 102 | + } |
| 103 | + |
| 104 | + |
| 105 | + static public void removeChangeListener(ChangeListener listener) { |
| 106 | + listeners.remove(listener); |
| 107 | + } |
| 108 | + |
| 109 | + |
| 110 | + static private void fireChange(String key, String value) { |
| 111 | + for (ChangeListener listener : listeners) { |
| 112 | + try { |
| 113 | + listener.preferenceChanged(key, value); |
| 114 | + } catch (Exception e) { |
| 115 | + // one broken listener shouldn't prevent the change (or the others) |
| 116 | + e.printStackTrace(); |
| 117 | + } |
| 118 | + } |
| 119 | + } |
| 120 | + |
79 | 121 |
|
80 | 122 | /** |
81 | 123 | * Load the bundled defaults followed by the user's preferences.txt from |
@@ -323,12 +365,17 @@ static public String getDefault(String attribute) { |
323 | 365 |
|
324 | 366 |
|
325 | 367 | static public void set(String attribute, String value) { |
326 | | - table.put(attribute, value); |
| 368 | + String previous = table.put(attribute, value); |
| 369 | + if (!Objects.equals(previous, value)) { |
| 370 | + fireChange(attribute, value); |
| 371 | + } |
327 | 372 | } |
328 | 373 |
|
329 | 374 |
|
330 | 375 | static public void unset(String attribute) { |
331 | | - table.remove(attribute); |
| 376 | + if (table.remove(attribute) != null) { |
| 377 | + fireChange(attribute, null); |
| 378 | + } |
332 | 379 | } |
333 | 380 |
|
334 | 381 |
|
|
0 commit comments