c57c443e302844ca6d9d657b61510e7a7ed71823
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / preferences / EclipsePreferences.java
1 package net.mograsim.plugin.preferences;
2
3 import java.util.HashMap;
4 import java.util.HashSet;
5 import java.util.Map;
6 import java.util.Set;
7 import java.util.function.Consumer;
8 import java.util.function.Function;
9
10 import org.eclipse.core.runtime.IStatus;
11 import org.eclipse.core.runtime.Status;
12 import org.eclipse.jface.preference.IPreferenceStore;
13 import org.eclipse.jface.resource.ColorRegistry;
14 import org.eclipse.jface.util.IPropertyChangeListener;
15 import org.eclipse.swt.graphics.Color;
16 import org.eclipse.swt.graphics.RGB;
17 import org.eclipse.ui.statushandlers.StatusManager;
18 import org.eclipse.ui.themes.ITheme;
19
20 import net.mograsim.plugin.MograsimActivator;
21 import net.mograsim.preferences.ColorDefinition;
22 import net.mograsim.preferences.Preferences;
23
24 public class EclipsePreferences implements Preferences
25 {
26         private final ITheme theme;
27         private final IPreferenceStore prefs;
28         private final Preferences defaultPrefs;
29
30         private final ListenerManager<Boolean> booleanListeners;
31         private final ListenerManager<Integer> intListeners;
32         private final ListenerManager<Double> doubleListeners;
33         private final ListenerManager<ColorDefinition> colorDefinitionListeners;
34
35         protected EclipsePreferences(ITheme theme, IPreferenceStore prefs, Preferences defaultPrefs)
36         {
37                 this.theme = theme;
38                 this.prefs = prefs;
39                 this.defaultPrefs = defaultPrefs;
40
41                 this.booleanListeners = new ListenerManager<>(this::getBoolean);
42                 this.intListeners = new ListenerManager<>(this::getInt);
43                 this.doubleListeners = new ListenerManager<>(this::getDouble);
44                 this.colorDefinitionListeners = new ListenerManager<>(this::getColorDefinition);
45         }
46
47         @Override
48         public boolean getBoolean(String name)
49         {
50                 prefs.setDefault(name, defaultPrefs.getBoolean(name));
51                 return prefs.getBoolean(name);
52         }
53
54         @Override
55         public int getInt(String name)
56         {
57                 prefs.setDefault(name, defaultPrefs.getInt(name));
58                 return prefs.getInt(name);
59         }
60
61         @Override
62         public double getDouble(String name)
63         {
64                 prefs.setDefault(name, defaultPrefs.getDouble(name));
65                 return prefs.getDouble(name);
66         }
67
68         @Override
69         public ColorDefinition getColorDefinition(String name)
70         {
71                 RGB rgb = getColorRegistry().getRGB(name);
72                 if (rgb == null)
73                 {
74                         StatusManager.getManager().handle(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "No color for name " + name));
75                         return null;
76                 }
77                 return new ColorDefinition(rgb.red, rgb.green, rgb.blue);
78         }
79
80         @Override
81         public Color getColor(String name)
82         {
83                 return getColorRegistry().get(name);
84         }
85
86         private ColorRegistry getColorRegistry()
87         {
88                 return theme.getColorRegistry();
89         }
90
91         @Override
92         public void addBooleanListener(String name, Consumer<Boolean> listener)
93         {
94                 booleanListeners.addListener(name, listener);
95         }
96
97         @Override
98         public void removeBooleanListener(String name, Consumer<Boolean> listener)
99         {
100                 booleanListeners.removeListener(name, listener);
101         }
102
103         @Override
104         public void addIntListener(String name, Consumer<Integer> listener)
105         {
106                 intListeners.addListener(name, listener);
107         }
108
109         @Override
110         public void removeIntListener(String name, Consumer<Integer> listener)
111         {
112                 intListeners.removeListener(name, listener);
113         }
114
115         @Override
116         public void addDoubleListener(String name, Consumer<Double> listener)
117         {
118                 doubleListeners.addListener(name, listener);
119         }
120
121         @Override
122         public void removeDoubleListener(String name, Consumer<Double> listener)
123         {
124                 doubleListeners.removeListener(name, listener);
125         }
126
127         @Override
128         public void addColorDefinitionListener(String name, Consumer<ColorDefinition> listener)
129         {
130                 colorDefinitionListeners.addListener(name, listener);
131         }
132
133         @Override
134         public void removeColorDefinitionListener(String name, Consumer<ColorDefinition> listener)
135         {
136                 colorDefinitionListeners.removeListener(name, listener);
137         }
138
139         private class ListenerManager<P>
140         {
141                 private final Map<String, Set<Consumer<P>>> listenersPerName;
142                 private final IPropertyChangeListener eclipseListener;
143
144                 public ListenerManager(Function<String, P> preferenceGetter)
145                 {
146                         this.listenersPerName = new HashMap<>();
147                         this.eclipseListener = e ->
148                         {
149                                 String name = e.getProperty();
150                                 synchronized (listenersPerName)
151                                 {
152                                         Set<Consumer<P>> listenersThisName = listenersPerName.get(name);
153                                         if (listenersThisName != null)
154                                         {
155                                                 P p = preferenceGetter.apply(name);
156                                                 listenersThisName.forEach(l -> l.accept(p));
157                                         }
158                                 }
159                         };
160                 }
161
162                 public void addListener(String name, Consumer<P> listener)
163                 {
164                         synchronized (listenersPerName)
165                         {
166                                 boolean wasEmpty = listenersPerName.isEmpty();
167                                 listenersPerName.computeIfAbsent(name, n -> new HashSet<>()).add(listener);
168                                 if (wasEmpty)
169                                         prefs.addPropertyChangeListener(eclipseListener);
170                         }
171                 }
172
173                 public void removeListener(String name, Consumer<P> listener)
174                 {
175                         synchronized (listenersPerName)
176                         {
177                                 Set<Consumer<P>> listenersThisName = listenersPerName.get(name);
178                                 if (listenersThisName != null)
179                                 {
180                                         listenersThisName.remove(listener);
181                                         if (listenersThisName.isEmpty())
182                                                 listenersPerName.remove(name);
183                                 }
184                                 if (listenersPerName.isEmpty())
185                                         prefs.addPropertyChangeListener(eclipseListener);
186                         }
187                 }
188         }
189 }