source: josm/trunk/src/org/openstreetmap/josm/data/Preferences.java@ 1121

Last change on this file since 1121 was 1121, checked in by stoecker, 15 years ago

add bookmark sorting. closes #1787

  • Property svn:eol-style set to native
File size: 14.5 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data;
3
4import java.awt.Color;
5import java.io.BufferedReader;
6import java.io.File;
7import java.io.FileReader;
8import java.io.FileWriter;
9import java.io.IOException;
10import java.io.PrintWriter;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.LinkedList;
16import java.util.Map;
17import java.util.Properties;
18import java.util.SortedMap;
19import java.util.TreeMap;
20import java.util.Map.Entry;
21import java.util.regex.Matcher;
22import java.util.regex.Pattern;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
26import org.openstreetmap.josm.tools.ColorHelper;
27
28/**
29 * This class holds all preferences for JOSM.
30 *
31 * Other classes can register their beloved properties here. All properties will be
32 * saved upon set-access.
33 *
34 * @author imi
35 */
36public class Preferences {
37
38 /**
39 * Internal storage for the preferenced directory.
40 * Do not access this variable directly!
41 * @see #getPreferencesDirFile()
42 */
43 private File preferencesDirFile = null;
44
45 public static interface PreferenceChangedListener {
46 void preferenceChanged(String key, String newValue);
47 }
48
49 /**
50 * Class holding one bookmarkentry.
51 * @author imi
52 */
53 public static class Bookmark implements Comparable<Bookmark> {
54 public String name;
55 public double[] latlon = new double[4]; // minlat, minlon, maxlat, maxlon
56 @Override public String toString() {
57 return name;
58 }
59 public int compareTo(Bookmark b) {
60 return name.toLowerCase().compareTo(b.name.toLowerCase());
61 }
62 }
63
64 public final ArrayList<PreferenceChangedListener> listener = new ArrayList<PreferenceChangedListener>();
65
66 /**
67 * Map the property name to the property object.
68 */
69 protected final SortedMap<String, String> properties = new TreeMap<String, String>();
70 protected final SortedMap<String, String> defaults = new TreeMap<String, String>();
71
72 /**
73 * Override some values on read. This is intended to be used for technology previews
74 * where we want to temporarily modify things without changing the user's preferences
75 * file.
76 */
77 protected static final SortedMap<String, String> override = new TreeMap<String, String>();
78 static {
79 //override.put("osm-server.version", "0.5");
80 //override.put("osm-server.additional-versions", "");
81 //override.put("osm-server.url", "http://openstreetmap.gryph.de/api");
82 //override.put("plugins", null);
83 }
84
85 /**
86 * Return the location of the user defined preferences file
87 */
88 public String getPreferencesDir() {
89 final String path = getPreferencesDirFile().getPath();
90 if (path.endsWith(File.separator))
91 return path;
92 return path + File.separator;
93 }
94
95 public File getPreferencesDirFile() {
96 if (preferencesDirFile != null)
97 return preferencesDirFile;
98 String path;
99 path = System.getProperty("josm.home");
100 if (path != null) {
101 preferencesDirFile = new File(path);
102 } else {
103 path = System.getenv("APPDATA");
104 if (path != null) {
105 preferencesDirFile = new File(path, "JOSM");
106 } else {
107 preferencesDirFile = new File(System.getProperty("user.home"), ".josm");
108 }
109 }
110 return preferencesDirFile;
111 }
112
113 public File getPluginsDirFile() {
114 return new File(getPreferencesDirFile(), "plugins");
115 }
116
117 /**
118 * @return A list of all existing directories where resources could be stored.
119 */
120 public Collection<String> getAllPossiblePreferenceDirs() {
121 LinkedList<String> locations = new LinkedList<String>();
122 locations.add(Main.pref.getPreferencesDir());
123 String s;
124 if ((s = System.getenv("JOSM_RESOURCES")) != null) {
125 if (!s.endsWith(File.separator))
126 s = s + File.separator;
127 locations.add(s);
128 }
129 if ((s = System.getProperty("josm.resources")) != null) {
130 if (!s.endsWith(File.separator))
131 s = s + File.separator;
132 locations.add(s);
133 }
134 String appdata = System.getenv("APPDATA");
135 if (System.getenv("ALLUSERSPROFILE") != null && appdata != null
136 && appdata.lastIndexOf(File.separator) != -1) {
137 appdata = appdata.substring(appdata.lastIndexOf(File.separator));
138 locations.add(new File(new File(System.getenv("ALLUSERSPROFILE"),
139 appdata), "JOSM").getPath());
140 }
141 locations.add("/usr/local/share/josm/");
142 locations.add("/usr/local/lib/josm/");
143 locations.add("/usr/share/josm/");
144 locations.add("/usr/lib/josm/");
145 return locations;
146 }
147
148 synchronized public boolean hasKey(final String key) {
149 return override.containsKey(key) ? override.get(key) != null : properties.containsKey(key);
150 }
151
152 synchronized public String get(final String key) {
153 putDefault(key, null);
154 if (override.containsKey(key))
155 return override.get(key);
156 if (!properties.containsKey(key))
157 return "";
158 return properties.get(key);
159 }
160
161 synchronized public String get(final String key, final String def) {
162 putDefault(key, def);
163 if (override.containsKey(key))
164 return override.get(key);
165 final String prop = properties.get(key);
166 if (prop == null || prop.equals(""))
167 return def;
168 return prop;
169 }
170
171 synchronized public Map<String, String> getAllPrefix(final String prefix) {
172 final Map<String,String> all = new TreeMap<String,String>();
173 for (final Entry<String,String> e : properties.entrySet())
174 if (e.getKey().startsWith(prefix))
175 all.put(e.getKey(), e.getValue());
176 for (final Entry<String,String> e : override.entrySet())
177 if (e.getKey().startsWith(prefix))
178 if (e.getValue() == null)
179 all.remove(e.getKey());
180 else
181 all.put(e.getKey(), e.getValue());
182 return all;
183 }
184
185 synchronized public Map<String, String> getDefaults() {
186 return defaults;
187 }
188
189 synchronized public void putDefault(final String key, final String def) {
190 if(!defaults.containsKey(key) || defaults.get(key) == null)
191 defaults.put(key, def);
192 else if(def != null && !defaults.get(key).equals(def))
193 System.out.println("Defaults for " + key + " differ: " + def + " != " + defaults.get(key));
194 }
195
196 synchronized public boolean getBoolean(final String key) {
197 putDefault(key, null);
198 if (override.containsKey(key))
199 return override.get(key) == null ? false : Boolean.parseBoolean(override.get(key));
200 return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : false;
201 }
202
203 synchronized public boolean getBoolean(final String key, final boolean def) {
204 putDefault(key, Boolean.toString(def));
205 if (override.containsKey(key))
206 return override.get(key) == null ? def : Boolean.parseBoolean(override.get(key));
207 return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : def;
208 }
209
210 synchronized public void put(final String key, String value) {
211 String oldvalue = properties.get(key);
212 if(value != null && value.length() == 0)
213 value = null;
214 if(!((oldvalue == null && value == null) || (value != null
215 && oldvalue != null && oldvalue.equals(value))))
216 {
217 if (value == null)
218 properties.remove(key);
219 else
220 properties.put(key, value);
221 save();
222 firePreferenceChanged(key, value);
223 }
224 }
225
226 synchronized public void put(final String key, final boolean value) {
227 put(key, Boolean.toString(value));
228 }
229
230 private final void firePreferenceChanged(final String key, final String value) {
231 for (final PreferenceChangedListener l : listener)
232 l.preferenceChanged(key, value);
233 }
234
235 /**
236 * Called after every put. In case of a problem, do nothing but output the error
237 * in log.
238 */
239 public void save() {
240 try {
241 setSystemProperties();
242 final PrintWriter out = new PrintWriter(new FileWriter(getPreferencesDir() + "preferences"), false);
243 for (final Entry<String, String> e : properties.entrySet()) {
244 out.println(e.getKey() + "=" + e.getValue());
245 }
246 out.close();
247 } catch (final IOException e) {
248 e.printStackTrace();
249 // do not message anything, since this can be called from strange
250 // places.
251 }
252 }
253
254 public void load() throws IOException {
255 properties.clear();
256 final BufferedReader in = new BufferedReader(new FileReader(getPreferencesDir()+"preferences"));
257 int lineNumber = 0;
258 ArrayList<Integer> errLines = new ArrayList<Integer>();
259 for (String line = in.readLine(); line != null; line = in.readLine(), lineNumber++) {
260 final int i = line.indexOf('=');
261 if (i == -1 || i == 0) {
262 errLines.add(lineNumber);
263 continue;
264 }
265 properties.put(line.substring(0,i), line.substring(i+1));
266 }
267 if (!errLines.isEmpty()) {
268 throw new IOException("Malformed config file at lines " + errLines);
269 }
270 setSystemProperties();
271 }
272
273 public final void resetToDefault() {
274 properties.clear();
275 properties.put("projection", "org.openstreetmap.josm.data.projection.Epsg4326");
276 properties.put("draw.segment.direction", "true");
277 properties.put("draw.wireframe", "false");
278 properties.put("layerlist.visible", "true");
279 properties.put("propertiesdialog.visible", "true");
280 properties.put("selectionlist.visible", "true");
281 properties.put("commandstack.visible", "true");
282 properties.put("osm-server.url", "http://www.openstreetmap.org/api");
283 if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") == -1) {
284 properties.put("laf", "javax.swing.plaf.metal.MetalLookAndFeel");
285 } else {
286 properties.put("laf", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
287 }
288 save();
289 }
290
291 public Collection<Bookmark> loadBookmarks() throws IOException {
292 File bookmarkFile = new File(getPreferencesDir()+"bookmarks");
293 if (!bookmarkFile.exists())
294 bookmarkFile.createNewFile();
295 BufferedReader in = new BufferedReader(new FileReader(bookmarkFile));
296
297 LinkedList<Bookmark> bookmarks = new LinkedList<Bookmark>();
298 // use pattern matches to scan text, as text may contain a "," itself
299 for (String line = in.readLine(); line != null; line = in.readLine()) {
300 Matcher m = Pattern.compile("^(.+),(-?\\d+.\\d+),(-?\\d+.\\d+),(-?\\d+.\\d+),(-?\\d+.\\d+)$").matcher(line);
301 if(m.matches())
302 {
303 Bookmark b = new Bookmark();
304 b.name = m.group(1);
305 for (int i = 0; i < b.latlon.length; ++i)
306 b.latlon[i] = Double.parseDouble(m.group(i+2));
307 bookmarks.add(b);
308 }
309 }
310 in.close();
311 Collections.sort(bookmarks);
312 return bookmarks;
313 }
314
315 public void saveBookmarks(Collection<Bookmark> bookmarks) throws IOException {
316 File bookmarkFile = new File(Main.pref.getPreferencesDir()+"bookmarks");
317 if (!bookmarkFile.exists())
318 bookmarkFile.createNewFile();
319 PrintWriter out = new PrintWriter(new FileWriter(bookmarkFile));
320 for (Bookmark b : bookmarks) {
321 out.print(b.name+",");
322 for (int i = 0; i < b.latlon.length; ++i)
323 out.print(b.latlon[i]+(i<b.latlon.length-1?",":""));
324 out.println();
325 }
326 out.close();
327 }
328
329 /**
330 * Convenience method for accessing colour preferences.
331 *
332 * @param colName name of the colour
333 * @param def default value
334 * @return a Color object for the configured colour, or the default value if none configured.
335 */
336 synchronized public Color getColor(String colName, Color def) {
337 String colStr = get("color."+colName);
338 if (colStr.equals("")) {
339 put("color."+colName, ColorHelper.color2html(def));
340 return def;
341 }
342 return ColorHelper.html2color(colStr);
343 }
344
345 // only for compatibility. Don't use any more.
346 @Deprecated
347 public static Color getPreferencesColor(String colName, Color def)
348 {
349 return Main.pref.getColor(colName, def);
350 }
351
352 /**
353 * Convenience method for accessing colour preferences.
354 *
355 * @param colName name of the colour
356 * @param specName name of the special colour settings
357 * @param def default value
358 * @return a Color object for the configured colour, or the default value if none configured.
359 */
360 synchronized public Color getColor(String colName, String specName, Color def) {
361 String colStr = get("color."+specName);
362 if(colStr.equals(""))
363 {
364 colStr = get("color."+colName);
365 if (colStr.equals("")) {
366 put("color."+colName, ColorHelper.color2html(def));
367 return def;
368 }
369 }
370 putDefault("color."+colName, ColorHelper.color2html(def));
371 return ColorHelper.html2color(colStr);
372 }
373
374 synchronized public void putColor(String colName, Color val) {
375 put("color."+colName, val != null ? ColorHelper.color2html(val) : null);
376 }
377
378 synchronized public int getInteger(String key, int def) {
379 putDefault(key, Integer.toString(def));
380 String v = get(key);
381 if(null == v)
382 return def;
383
384 try {
385 return Integer.parseInt(v);
386 } catch(NumberFormatException e) {
387 // fall out
388 }
389 return def;
390 }
391
392 synchronized public long getLong(String key, long def) {
393 putDefault(key, Long.toString(def));
394 String v = get(key);
395 if(null == v)
396 return def;
397
398 try {
399 return Long.parseLong(v);
400 } catch(NumberFormatException e) {
401 // fall out
402 }
403 return def;
404 }
405
406 synchronized public double getDouble(String key, double def) {
407 putDefault(key, Double.toString(def));
408 String v = get(key);
409 if(null == v)
410 return def;
411
412 try {
413 return Double.parseDouble(v);
414 } catch(NumberFormatException e) {
415 // fall out
416 }
417 return def;
418 }
419
420 synchronized public Collection<String> getCollection(String key, Collection<String> def) {
421 String s = get(key);
422 if(s != null && s.length() != 0)
423 {
424 /* handle old comma separated stuff - remove in future */
425 if(s.indexOf(',') >= 0)
426 return Arrays.asList(s.split(","));
427 /* handle space separated stuff - remove in future */
428 else if(s.indexOf(' ') >= 0)
429 return Arrays.asList(s.split(","));
430 else
431 return Arrays.asList(s.split(";"));
432 }
433 else if(def != null)
434 return def;
435 return null;
436 }
437 synchronized public void removeFromCollection(String key, String value) {
438 ArrayList<String> a = new ArrayList<String>(getCollection(key, null));
439 if(a != null)
440 {
441 a.remove(value);
442 putCollection(key, a);
443 }
444 }
445 synchronized public void putCollection(String key, Collection<String> val) {
446 String s = null;
447 if(val != null)
448 {
449 for(String a : val)
450 {
451 if(s != null)
452 s += ";" + a;
453 else
454 s = a;
455 }
456 }
457
458 put(key, s);
459 }
460
461 private void setSystemProperties() {
462 Properties sysProp = System.getProperties();
463 if (getBoolean(ProxyPreferences.PROXY_ENABLE)) {
464 sysProp.put("proxySet", "true");
465 sysProp.put("http.proxyHost", get(ProxyPreferences.PROXY_HOST));
466 sysProp.put("proxyPort", get(ProxyPreferences.PROXY_PORT));
467 if (!getBoolean(ProxyPreferences.PROXY_ANONYMOUS)) {
468 sysProp.put("proxyUser", get(ProxyPreferences.PROXY_USER));
469 sysProp.put("proxyPassword", get(ProxyPreferences.PROXY_PASS));
470 }
471 } else {
472 sysProp.put("proxySet", "false");
473 sysProp.remove("http.proxyHost");
474 sysProp.remove("proxyPort");
475 sysProp.remove("proxyUser");
476 sysProp.remove("proxyPassword");
477 }
478 System.setProperties(sysProp);
479 }
480}
Note: See TracBrowser for help on using the repository browser.