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

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

mapcss: fill-image

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