source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java@ 3855

Last change on this file since 3855 was 3855, checked in by bastiK, 13 years ago

Extended mappaint style dialog. No longer required to restart JOSM for changes in mappaint preferences.

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.IOException;
7import java.io.InputStream;
8import java.util.ArrayList;
9import java.util.Arrays;
10import java.util.Collection;
11import java.util.Collections;
12import java.util.LinkedList;
13import java.util.List;
14import java.util.concurrent.CopyOnWriteArrayList;
15
16import javax.swing.ImageIcon;
17import javax.swing.SwingUtilities;
18
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.gui.PleaseWaitRunnable;
21import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
22import org.openstreetmap.josm.gui.mappaint.xml.XmlStyleSource;
23import org.openstreetmap.josm.gui.preferences.SourceEntry;
24import org.openstreetmap.josm.gui.preferences.MapPaintPreference.MapPaintPrefMigration;
25import org.openstreetmap.josm.gui.progress.ProgressMonitor;
26import org.openstreetmap.josm.io.MirroredInputStream;
27import org.openstreetmap.josm.tools.ImageProvider;
28
29/**
30 * This class manages the ElemStyles instance. The object you get with
31 * getStyles() is read only, any manipulation happens via one of
32 * the wrapper methods here. (readFromPreferences, moveStyles, ...)
33 *
34 * On change, mapPaintSylesUpdated() is fired for all listeners.
35 */
36public class MapPaintStyles {
37
38 private static ElemStyles styles = new ElemStyles();
39 private static Collection<String> iconDirs;
40
41 public static ElemStyles getStyles()
42 {
43 return styles;
44 }
45
46 public static class IconReference {
47
48 public String iconName;
49 public XmlStyleSource source;
50
51 public IconReference(String iconName, XmlStyleSource source) {
52 this.iconName = iconName;
53 this.source = source;
54 }
55 }
56
57 public static ImageIcon getIcon(IconReference ref)
58 {
59 String styleName = ref.source.getPrefName();
60 List<String> dirs = new LinkedList<String>();
61 for(String fileset : iconDirs)
62 {
63 String[] a;
64 if(fileset.indexOf("=") >= 0) {
65 a = fileset.split("=", 2);
66 } else {
67 a = new String[] {"", fileset};
68 }
69
70 /* non-prefixed path is generic path, always take it */
71 if(a[0].length() == 0 || styleName.equals(a[0])) {
72 dirs.add(a[1]);
73 }
74 }
75 ImageIcon i = ImageProvider.getIfAvailable(dirs, "mappaint."+styleName, null, ref.iconName, ref.source.zipIcons);
76 if(i == null)
77 {
78 System.out.println("Mappaint style \""+styleName+"\" icon \"" + ref.iconName + "\" not found.");
79 i = ImageProvider.getIfAvailable(dirs, "mappaint."+styleName, null, "misc/no_icon.png");
80 }
81 return i;
82 }
83
84 public static void readFromPreferences() {
85 styles.clear();
86 iconDirs = Main.pref.getCollection("mappaint.icon.sources", Collections.<String>emptySet());
87 if(Main.pref.getBoolean("mappaint.icon.enable-defaults", true))
88 {
89 LinkedList<String> f = new LinkedList<String>(iconDirs);
90 /* don't prefix icon path, as it should be generic */
91 f.add("resource://images/styles/standard/");
92 f.add("resource://images/styles/");
93 iconDirs = f;
94 }
95
96 Collection<? extends SourceEntry> sourceEntries = MapPaintPrefMigration.INSTANCE.get();
97
98 for (SourceEntry entry : sourceEntries) {
99 StyleSource style = null;
100 try {
101 MirroredInputStream in = new MirroredInputStream(entry.url);
102 InputStream zip = in.getZipEntry("xml","style");
103 if (zip != null) {
104 style = new XmlStyleSource(entry);
105 styles.add(style);
106 continue;
107 }
108 zip = in.getZipEntry("mapcss","style");
109 if (zip != null) {
110 style = new MapCSSStyleSource(entry);
111 styles.add(style);
112 continue;
113 }
114 if (entry.url.toLowerCase().endsWith(".mapcss")) {
115 style = new MapCSSStyleSource(entry);
116 } else {
117 style = new XmlStyleSource(entry);
118 }
119 } catch(IOException e) {
120 System.err.println(tr("Warning: failed to load Mappaint styles from ''{0}''. Exception was: {1}", entry.url, e.toString()));
121 e.printStackTrace();
122 if (style != null) {
123 style.hasError = true;
124 }
125 }
126 if (style != null) {
127 styles.add(style);
128 }
129 }
130 for (StyleSource s : styles.getStyleSources()) {
131 s.loadStyleSource();
132 }
133 fireMapPaintSylesUpdated();
134 }
135
136 /**
137 * reload styles
138 * preferences are the same, but the file source may have changed
139 * @param sel the indices of styles to reload
140 */
141 public static void reloadStyles(final int... sel) {
142 List<StyleSource> toReload = new ArrayList<StyleSource>();
143 List<StyleSource> data = styles.getStyleSources();
144 for (int i : sel) {
145 toReload.add(data.get(i));
146 }
147 Main.worker.submit(new MapPaintStyleLoader(toReload));
148 }
149
150 public static class MapPaintStyleLoader extends PleaseWaitRunnable {
151 private boolean canceled;
152 private List<StyleSource> sources;
153
154 public MapPaintStyleLoader(List<StyleSource> sources) {
155 super(tr("Reloading style sources"));
156 this.sources = sources;
157 }
158
159 @Override
160 protected void cancel() {
161 canceled = true;
162 }
163
164 @Override
165 protected void finish() {
166 SwingUtilities.invokeLater(new Runnable() {
167 @Override
168 public void run() {
169 fireMapPaintSylesUpdated();
170 styles.clearCached();
171 Main.map.mapView.preferenceChanged(null);
172 Main.map.mapView.repaint();
173 }
174 });
175 }
176
177 @Override
178 protected void realRun() {
179 ProgressMonitor monitor = getProgressMonitor();
180 monitor.setTicksCount(sources.size());
181 for (StyleSource s : sources) {
182 if (canceled)
183 return;
184 monitor.subTask(tr("loading style ''{0}''...", s.getDisplayString()));
185 s.loadStyleSource();
186 monitor.worked(1);
187 }
188 }
189 }
190
191 /**
192 * Move position of entries in the current list of StyleSources
193 * @param sele The indices of styles to be moved.
194 * @param delta The number of lines it should move. positive int moves
195 * down and negative moves up.
196 */
197 public static void moveStyles(int[] sel, int delta) {
198 if (!canMoveStyles(sel, delta))
199 return;
200 int[] selSorted = Arrays.copyOf(sel, sel.length);
201 Arrays.sort(selSorted);
202 List<StyleSource> data = new ArrayList<StyleSource>(styles.getStyleSources());
203 for (int row: selSorted) {
204 StyleSource t1 = data.get(row);
205 StyleSource t2 = data.get(row + delta);
206 data.set(row, t2);
207 data.set(row + delta, t1);
208 }
209 styles.setStyleSources(data);
210 MapPaintPrefMigration.INSTANCE.put(data);
211 fireMapPaintSylesUpdated();
212 styles.clearCached();
213 Main.map.mapView.repaint();
214 }
215
216 public static boolean canMoveStyles(int[] sel, int i) {
217 if (sel.length == 0)
218 return false;
219 int[] selSorted = Arrays.copyOf(sel, sel.length);
220 Arrays.sort(selSorted);
221
222 if (i < 0) { // Up
223 return selSorted[0] >= -i;
224 } else
225 if (i > 0) { // Down
226 return selSorted[selSorted.length-1] <= styles.getStyleSources().size() - 1 - i;
227 } else
228 return true;
229 }
230
231 public static void toggleStyleActive(int... sel) {
232 List<StyleSource> data = styles.getStyleSources();
233 for (int p : sel) {
234 StyleSource s = data.get(p);
235 s.active = !s.active;
236 }
237 MapPaintPrefMigration.INSTANCE.put(data);
238 if (sel.length == 1) {
239 fireMapPaintStyleEntryUpdated(sel[0]);
240 } else {
241 fireMapPaintSylesUpdated();
242 }
243 styles.clearCached();
244 Main.map.mapView.repaint();
245 }
246
247 /***********************************
248 * MapPaintSylesUpdateListener & related code
249 * (get informed when the list of MapPaint StyleSources changes)
250 */
251
252 public interface MapPaintSylesUpdateListener {
253 public void mapPaintStylesUpdated();
254 public void mapPaintStyleEntryUpdated(int idx);
255 }
256
257 protected static final CopyOnWriteArrayList<MapPaintSylesUpdateListener> listeners
258 = new CopyOnWriteArrayList<MapPaintSylesUpdateListener>();
259
260 public static void addMapPaintSylesUpdateListener(MapPaintSylesUpdateListener listener) {
261 if (listener != null) {
262 listeners.addIfAbsent(listener);
263 }
264 }
265
266 public static void removeMapPaintSylesUpdateListener(MapPaintSylesUpdateListener listener) {
267 listeners.remove(listener);
268 }
269
270 public static void fireMapPaintSylesUpdated() {
271 for (MapPaintSylesUpdateListener l : listeners) {
272 l.mapPaintStylesUpdated();
273 }
274 }
275
276 public static void fireMapPaintStyleEntryUpdated(int idx) {
277 for (MapPaintSylesUpdateListener l : listeners) {
278 l.mapPaintStyleEntryUpdated(idx);
279 }
280 }
281}
Note: See TracBrowser for help on using the repository browser.