Added String preferences
[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<String> stringListeners;
34         private final ListenerManager<ColorDefinition> colorDefinitionListeners;
35
36         protected EclipsePreferences(ITheme theme, IPreferenceStore prefs, Preferences defaultPrefs)
37         {
38                 this.theme = theme;
39                 this.prefs = prefs;
40                 this.defaultPrefs = defaultPrefs;
41
42                 this.booleanListeners = new ListenerManager<>(this::getBoolean);
43                 this.intListeners = new ListenerManager<>(this::getInt);
44                 this.doubleListeners = new ListenerManager<>(this::getDouble);
45                 this.stringListeners = new ListenerManager<>(this::getString);
46                 this.colorDefinitionListeners = new ListenerManager<>(this::getColorDefinition);
47         }
48
49         @Override
50         public boolean getBoolean(String name)
51         {
52                 prefs.setDefault(name, defaultPrefs.getBoolean(name));
53                 return prefs.getBoolean(name);
54         }
55
56         @Override
57         public int getInt(String name)
58         {
59                 prefs.setDefault(name, defaultPrefs.getInt(name));
60                 return prefs.getInt(name);
61         }
62
63         @Override
64         public double getDouble(String name)
65         {
66                 prefs.setDefault(name, defaultPrefs.getDouble(name));
67                 return prefs.getDouble(name);
68         }
69
70         @Override
71         public String getString(String name)
72         {
73                 prefs.setDefault(name, defaultPrefs.getString(name));
74                 return prefs.getString(name);
75         }
76
77         @Override
78         public ColorDefinition getColorDefinition(String name)
79         {
80                 RGB rgb = getColorRegistry().getRGB(name);
81                 if (rgb == null)
82                 {
83                         StatusManager.getManager().handle(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, "No color for name " + name));
84                         return null;
85                 }
86                 return new ColorDefinition(rgb.red, rgb.green, rgb.blue);
87         }
88
89         @Override
90         public Color getColor(String name)
91         {
92                 return getColorRegistry().get(name);
93         }
94
95         private ColorRegistry getColorRegistry()
96         {
97                 return theme.getColorRegistry();
98         }
99
100         @Override
101         public void addBooleanListener(String name, Consumer<Boolean> listener)
102         {
103                 booleanListeners.addListener(name, listener);
104         }
105
106         @Override
107         public void removeBooleanListener(String name, Consumer<Boolean> listener)
108         {
109                 booleanListeners.removeListener(name, listener);
110         }
111
112         @Override
113         public void addIntListener(String name, Consumer<Integer> listener)
114         {
115                 intListeners.addListener(name, listener);
116         }
117
118         @Override
119         public void removeIntListener(String name, Consumer<Integer> listener)
120         {
121                 intListeners.removeListener(name, listener);
122         }
123
124         @Override
125         public void addDoubleListener(String name, Consumer<Double> listener)
126         {
127                 doubleListeners.addListener(name, listener);
128         }
129
130         @Override
131         public void removeDoubleListener(String name, Consumer<Double> listener)
132         {
133                 doubleListeners.removeListener(name, listener);
134         }
135
136         @Override
137         public void addStringListener(String name, Consumer<String> listener)
138         {
139                 stringListeners.addListener(name, listener);
140         }
141
142         @Override
143         public void removeStringListener(String name, Consumer<String> listener)
144         {
145                 stringListeners.removeListener(name, listener);
146         }
147
148         @Override
149         public void addColorDefinitionListener(String name, Consumer<ColorDefinition> listener)
150         {
151                 colorDefinitionListeners.addListener(name, listener);
152         }
153
154         @Override
155         public void removeColorDefinitionListener(String name, Consumer<ColorDefinition> listener)
156         {
157                 colorDefinitionListeners.removeListener(name, listener);
158         }
159
160         private class ListenerManager<P>
161         {
162                 private final Map<String, Set<Consumer<P>>> listenersPerName;
163                 private final IPropertyChangeListener eclipseListener;
164
165                 public ListenerManager(Function<String, P> preferenceGetter)
166                 {
167                         this.listenersPerName = new HashMap<>();
168                         this.eclipseListener = e ->
169                         {
170                                 String name = e.getProperty();
171                                 synchronized (listenersPerName)
172                                 {
173                                         Set<Consumer<P>> listenersThisName = listenersPerName.get(name);
174                                         if (listenersThisName != null)
175                                         {
176                                                 P p = preferenceGetter.apply(name);
177                                                 listenersThisName.forEach(l -> l.accept(p));
178                                         }
179                                 }
180                         };
181                 }
182
183                 public void addListener(String name, Consumer<P> listener)
184                 {
185                         synchronized (listenersPerName)
186                         {
187                                 boolean wasEmpty = listenersPerName.isEmpty();
188                                 listenersPerName.computeIfAbsent(name, n -> new HashSet<>()).add(listener);
189                                 if (wasEmpty)
190                                         prefs.addPropertyChangeListener(eclipseListener);
191                         }
192                 }
193
194                 public void removeListener(String name, Consumer<P> listener)
195                 {
196                         synchronized (listenersPerName)
197                         {
198                                 Set<Consumer<P>> listenersThisName = listenersPerName.get(name);
199                                 if (listenersThisName != null)
200                                 {
201                                         listenersThisName.remove(listener);
202                                         if (listenersThisName.isEmpty())
203                                                 listenersPerName.remove(name);
204                                 }
205                                 if (listenersPerName.isEmpty())
206                                         prefs.addPropertyChangeListener(eclipseListener);
207                         }
208                 }
209         }
210 }