1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.mappaint;
|
---|
3 |
|
---|
4 | import java.util.Collection;
|
---|
5 | import java.util.Collections;
|
---|
6 | import java.util.HashMap;
|
---|
7 | import java.util.Iterator;
|
---|
8 | import java.util.LinkedList;
|
---|
9 | import java.util.List;
|
---|
10 | import java.util.regex.Matcher;
|
---|
11 | import java.util.regex.Pattern;
|
---|
12 |
|
---|
13 | import org.openstreetmap.josm.data.osm.Node;
|
---|
14 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
15 | import org.openstreetmap.josm.data.osm.OsmUtils;
|
---|
16 | import org.openstreetmap.josm.data.osm.Way;
|
---|
17 | import org.openstreetmap.josm.gui.mappaint.xml.XmlCondition;
|
---|
18 | import org.openstreetmap.josm.gui.preferences.SourceEntry;
|
---|
19 |
|
---|
20 | public class StyleSource extends SourceEntry {
|
---|
21 |
|
---|
22 | public final HashMap<String, IconElemStyle> icons = new HashMap<String, IconElemStyle>();
|
---|
23 | public final HashMap<String, LineElemStyle> lines = new HashMap<String, LineElemStyle>();
|
---|
24 | public final HashMap<String, LineElemStyle> modifiers = new HashMap<String, LineElemStyle>();
|
---|
25 | public final HashMap<String, AreaElemStyle> areas = new HashMap<String, AreaElemStyle>();
|
---|
26 | public final LinkedList<IconElemStyle> iconsList = new LinkedList<IconElemStyle>();
|
---|
27 | public final LinkedList<LineElemStyle> linesList = new LinkedList<LineElemStyle>();
|
---|
28 | public final LinkedList<LineElemStyle> modifiersList = new LinkedList<LineElemStyle>();
|
---|
29 | public final LinkedList<AreaElemStyle> areasList = new LinkedList<AreaElemStyle>();
|
---|
30 |
|
---|
31 | public boolean hasError = false;
|
---|
32 |
|
---|
33 | public StyleSource(String url, String name, String shortdescription) {
|
---|
34 | super(url, name, shortdescription, true);
|
---|
35 | }
|
---|
36 |
|
---|
37 | public StyleSource(SourceEntry entry) {
|
---|
38 | super(entry.url, entry.name, entry.shortdescription, entry.active);
|
---|
39 | }
|
---|
40 |
|
---|
41 | public IconElemStyle getNode(OsmPrimitive primitive, IconElemStyle icon) {
|
---|
42 | for (String key : primitive.keySet()) {
|
---|
43 | String val = primitive.get(key);
|
---|
44 | IconElemStyle style;
|
---|
45 | if ((style = icons.get("n" + key + "=" + val)) != null) {
|
---|
46 | if (icon == null || style.priority > icon.priority) {
|
---|
47 | icon = style;
|
---|
48 | }
|
---|
49 | }
|
---|
50 | if ((style = icons.get("b" + key + "=" + OsmUtils.getNamedOsmBoolean(val))) != null) {
|
---|
51 | if (icon == null || style.priority > icon.priority) {
|
---|
52 | icon = style;
|
---|
53 | }
|
---|
54 | }
|
---|
55 | if ((style = icons.get("x" + key)) != null) {
|
---|
56 | if (icon == null || style.priority > icon.priority) {
|
---|
57 | icon = style;
|
---|
58 | }
|
---|
59 | }
|
---|
60 | }
|
---|
61 | for (IconElemStyle s : iconsList) {
|
---|
62 | if ((icon == null || s.priority > icon.priority) && s.check(primitive)) {
|
---|
63 | icon = s;
|
---|
64 | }
|
---|
65 | }
|
---|
66 | return icon;
|
---|
67 | }
|
---|
68 |
|
---|
69 | public ElemStyle get(OsmPrimitive primitive, boolean noclosed, AreaElemStyle area, LineElemStyle line) {
|
---|
70 | String lineIdx = null;
|
---|
71 | HashMap<String, LineElemStyle> overlayMap = new HashMap<String, LineElemStyle>();
|
---|
72 | for (String key : primitive.keySet()) {
|
---|
73 | String val = primitive.get(key);
|
---|
74 | AreaElemStyle styleArea;
|
---|
75 | LineElemStyle styleLine;
|
---|
76 | String idx = "n" + key + "=" + val;
|
---|
77 | if ((styleArea = areas.get(idx)) != null && (area == null || styleArea.priority > area.priority) && (!noclosed || !styleArea.closed)) {
|
---|
78 | area = styleArea;
|
---|
79 | }
|
---|
80 | if ((styleLine = lines.get(idx)) != null && (line == null || styleLine.priority > line.priority)) {
|
---|
81 | line = styleLine;
|
---|
82 | lineIdx = idx;
|
---|
83 | }
|
---|
84 | if ((styleLine = modifiers.get(idx)) != null) {
|
---|
85 | overlayMap.put(idx, styleLine);
|
---|
86 | }
|
---|
87 | idx = "b" + key + "=" + OsmUtils.getNamedOsmBoolean(val);
|
---|
88 | if ((styleArea = areas.get(idx)) != null && (area == null || styleArea.priority > area.priority) && (!noclosed || !styleArea.closed)) {
|
---|
89 | area = styleArea;
|
---|
90 | }
|
---|
91 | if ((styleLine = lines.get(idx)) != null && (line == null || styleLine.priority > line.priority)) {
|
---|
92 | line = styleLine;
|
---|
93 | lineIdx = idx;
|
---|
94 | }
|
---|
95 | if ((styleLine = modifiers.get(idx)) != null) {
|
---|
96 | overlayMap.put(idx, styleLine);
|
---|
97 | }
|
---|
98 | idx = "x" + key;
|
---|
99 | if ((styleArea = areas.get(idx)) != null && (area == null || styleArea.priority > area.priority) && (!noclosed || !styleArea.closed)) {
|
---|
100 | area = styleArea;
|
---|
101 | }
|
---|
102 | if ((styleLine = lines.get(idx)) != null && (line == null || styleLine.priority > line.priority)) {
|
---|
103 | line = styleLine;
|
---|
104 | lineIdx = idx;
|
---|
105 | }
|
---|
106 | if ((styleLine = modifiers.get(idx)) != null) {
|
---|
107 | overlayMap.put(idx, styleLine);
|
---|
108 | }
|
---|
109 | }
|
---|
110 | for (AreaElemStyle s : areasList) {
|
---|
111 | if ((area == null || s.priority > area.priority) && (!noclosed || !s.closed) && s.check(primitive)) {
|
---|
112 | area = s;
|
---|
113 | }
|
---|
114 | }
|
---|
115 | for (LineElemStyle s : linesList) {
|
---|
116 | if ((line == null || s.priority > line.priority) && s.check(primitive)) {
|
---|
117 | line = s;
|
---|
118 | }
|
---|
119 | }
|
---|
120 | for (LineElemStyle s : modifiersList) {
|
---|
121 | if (s.check(primitive)) {
|
---|
122 | overlayMap.put(s.getCode(), s);
|
---|
123 | }
|
---|
124 | }
|
---|
125 | overlayMap.remove(lineIdx); // do not use overlay if linestyle is from the same rule (example: railway=tram)
|
---|
126 | if (!overlayMap.isEmpty() && line != null) {
|
---|
127 | List<LineElemStyle> tmp = new LinkedList<LineElemStyle>();
|
---|
128 | if (line.overlays != null) {
|
---|
129 | tmp.addAll(line.overlays);
|
---|
130 | }
|
---|
131 | tmp.addAll(overlayMap.values());
|
---|
132 | Collections.sort(tmp);
|
---|
133 | line = new LineElemStyle(line, tmp);
|
---|
134 | }
|
---|
135 | if (area != null) {
|
---|
136 | if (line != null) {
|
---|
137 | return new AreaElemStyle(area, line);
|
---|
138 | } else {
|
---|
139 | return area;
|
---|
140 | }
|
---|
141 | }
|
---|
142 | return line;
|
---|
143 | }
|
---|
144 |
|
---|
145 | public boolean isArea(OsmPrimitive o) {
|
---|
146 | if (o.hasKeys() && !(o instanceof Node)) {
|
---|
147 | boolean noclosed = o instanceof Way && !((Way) o).isClosed();
|
---|
148 | Iterator<String> iterator = o.keySet().iterator();
|
---|
149 | while (iterator.hasNext()) {
|
---|
150 | String key = iterator.next();
|
---|
151 | String val = o.get(key);
|
---|
152 | AreaElemStyle s = areas.get("n" + key + "=" + val);
|
---|
153 | if (s == null || (s.closed && noclosed)) {
|
---|
154 | s = areas.get("b" + key + "=" + OsmUtils.getNamedOsmBoolean(val));
|
---|
155 | }
|
---|
156 | if (s == null || (s.closed && noclosed)) {
|
---|
157 | s = areas.get("x" + key);
|
---|
158 | }
|
---|
159 | if (s != null && !(s.closed && noclosed)) {
|
---|
160 | return true;
|
---|
161 | }
|
---|
162 | }
|
---|
163 | for (AreaElemStyle s : areasList) {
|
---|
164 | if (!(s.closed && noclosed) && s.check(o)) {
|
---|
165 | return true;
|
---|
166 | }
|
---|
167 | }
|
---|
168 | }
|
---|
169 | return false;
|
---|
170 | }
|
---|
171 |
|
---|
172 | public boolean hasAreas() {
|
---|
173 | return areas.size() > 0;
|
---|
174 | }
|
---|
175 |
|
---|
176 | public void add(XmlCondition c, Collection<XmlCondition> conditions, LineElemStyle style) {
|
---|
177 | if(conditions != null)
|
---|
178 | {
|
---|
179 | style.conditions = conditions;
|
---|
180 | linesList.add(style);
|
---|
181 | }
|
---|
182 | else {
|
---|
183 | String key = c.getKey();
|
---|
184 | style.code = key;
|
---|
185 | lines.put(key, style);
|
---|
186 | }
|
---|
187 | }
|
---|
188 |
|
---|
189 | public void addModifier(XmlCondition c, Collection<XmlCondition> conditions, LineElemStyle style) {
|
---|
190 | if(conditions != null)
|
---|
191 | {
|
---|
192 | style.conditions = conditions;
|
---|
193 | modifiersList.add(style);
|
---|
194 | }
|
---|
195 | else
|
---|
196 | {
|
---|
197 | String key = c.getKey();
|
---|
198 | style.code = key;
|
---|
199 | modifiers.put(key, style);
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 | public void add(XmlCondition c, Collection<XmlCondition> conditions, AreaElemStyle style) {
|
---|
204 | if(conditions != null)
|
---|
205 | {
|
---|
206 | style.conditions = conditions;
|
---|
207 | areasList.add(style);
|
---|
208 | }
|
---|
209 | else
|
---|
210 | {
|
---|
211 | String key = c.getKey();
|
---|
212 | style.code = key;
|
---|
213 | areas.put(key, style);
|
---|
214 | }
|
---|
215 | }
|
---|
216 |
|
---|
217 | public void add(XmlCondition c, Collection<XmlCondition> conditions, IconElemStyle style) {
|
---|
218 | if(conditions != null)
|
---|
219 | {
|
---|
220 | style.conditions = conditions;
|
---|
221 | iconsList.add(style);
|
---|
222 | }
|
---|
223 | else
|
---|
224 | {
|
---|
225 | String key = c.getKey();
|
---|
226 | style.code = key;
|
---|
227 | icons.put(key, style);
|
---|
228 | }
|
---|
229 | }
|
---|
230 |
|
---|
231 | /**
|
---|
232 | * the name / identifier that should be used to save custom color values
|
---|
233 | * and similar stuff to the preference file
|
---|
234 | * @return the identifier; never null. Usually the result is "standard"
|
---|
235 | */
|
---|
236 | public String getPrefName() {
|
---|
237 | return name == null ? "standard" : name;
|
---|
238 | }
|
---|
239 |
|
---|
240 | /**
|
---|
241 | * String to show in menus and error messages.
|
---|
242 | * @return Usually the shortdescription, but can be the file name
|
---|
243 | * if no shortdescription is available.
|
---|
244 | */
|
---|
245 | public String getDisplayString() {
|
---|
246 | if (shortdescription != null)
|
---|
247 | return shortdescription;
|
---|
248 | /**
|
---|
249 | * extract file part from url, e.g.:
|
---|
250 | * http://www.test.com/file.xml?format=text --> file.xml
|
---|
251 | */
|
---|
252 | Pattern p = Pattern.compile("([^/\\\\]*?)([?].*)?$");
|
---|
253 | Matcher m = p.matcher(url);
|
---|
254 | if (m.find()) {
|
---|
255 | return m.group(1);
|
---|
256 | } else {
|
---|
257 | System.err.println("Warning: Unexpected URL format: "+url);
|
---|
258 | return url;
|
---|
259 | }
|
---|
260 | }
|
---|
261 | }
|
---|