source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java@ 8509

Last change on this file since 8509 was 8509, checked in by Don-vip, 9 years ago

fix many checkstyle violations

  • Property svn:eol-style set to native
File size: 14.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import java.awt.BasicStroke;
5import java.awt.Color;
6import java.util.Arrays;
7import java.util.Objects;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.data.osm.Node;
11import org.openstreetmap.josm.data.osm.OsmPrimitive;
12import org.openstreetmap.josm.data.osm.Way;
13import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
14import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
15import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
16import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
17import org.openstreetmap.josm.tools.Utils;
18
19public class LineElemStyle extends ElemStyle {
20
21 public static LineElemStyle createSimpleLineStyle(Color color, boolean isAreaEdge) {
22 MultiCascade mc = new MultiCascade();
23 Cascade c = mc.getOrCreateCascade("default");
24 c.put(WIDTH, Keyword.DEFAULT);
25 c.put(COLOR, color != null ? color : PaintColors.UNTAGGED.get());
26 c.put(OPACITY, 1f);
27 if (isAreaEdge) {
28 c.put(Z_INDEX, -3f);
29 }
30 return createLine(new Environment(null, mc, "default", null));
31 }
32 public static final LineElemStyle UNTAGGED_WAY = createSimpleLineStyle(null, false);
33
34 private BasicStroke line;
35 public Color color;
36 public Color dashesBackground;
37 public float offset;
38 public float realWidth; // the real width of this line in meter
39
40 private BasicStroke dashesLine;
41
42 public enum LineType {
43 NORMAL("", 3f),
44 CASING("casing-", 2f),
45 LEFT_CASING("left-casing-", 2.1f),
46 RIGHT_CASING("right-casing-", 2.1f);
47
48 public final String prefix;
49 public final float defaultMajorZIndex;
50
51 LineType(String prefix, float default_major_z_index) {
52 this.prefix = prefix;
53 this.defaultMajorZIndex = default_major_z_index;
54 }
55 }
56
57 protected LineElemStyle(Cascade c, float default_major_z_index, BasicStroke line, Color color, BasicStroke dashesLine,
58 Color dashesBackground, float offset, float realWidth) {
59 super(c, default_major_z_index);
60 this.line = line;
61 this.color = color;
62 this.dashesLine = dashesLine;
63 this.dashesBackground = dashesBackground;
64 this.offset = offset;
65 this.realWidth = realWidth;
66 }
67
68 public static LineElemStyle createLine(Environment env) {
69 return createImpl(env, LineType.NORMAL);
70 }
71
72 public static LineElemStyle createLeftCasing(Environment env) {
73 LineElemStyle leftCasing = createImpl(env, LineType.LEFT_CASING);
74 if (leftCasing != null) {
75 leftCasing.isModifier = true;
76 }
77 return leftCasing;
78 }
79
80 public static LineElemStyle createRightCasing(Environment env) {
81 LineElemStyle rightCasing = createImpl(env, LineType.RIGHT_CASING);
82 if (rightCasing != null) {
83 rightCasing.isModifier = true;
84 }
85 return rightCasing;
86 }
87
88 public static LineElemStyle createCasing(Environment env) {
89 LineElemStyle casing = createImpl(env, LineType.CASING);
90 if (casing != null) {
91 casing.isModifier = true;
92 }
93 return casing;
94 }
95
96 private static LineElemStyle createImpl(Environment env, LineType type) {
97 Cascade c = env.mc.getCascade(env.layer);
98 Cascade c_def = env.mc.getCascade("default");
99 Float width;
100 switch (type) {
101 case NORMAL:
102 width = getWidth(c, WIDTH, getWidth(c_def, WIDTH, null));
103 break;
104 case CASING:
105 Float casingWidth = c.get(type.prefix + WIDTH, null, Float.class, true);
106 if (casingWidth == null) {
107 RelativeFloat rel_casingWidth = c.get(type.prefix + WIDTH, null, RelativeFloat.class, true);
108 if (rel_casingWidth != null) {
109 casingWidth = rel_casingWidth.val / 2;
110 }
111 }
112 if (casingWidth == null)
113 return null;
114 width = getWidth(c, WIDTH, getWidth(c_def, WIDTH, null));
115 if (width == null) {
116 width = 0f;
117 }
118 width += 2 * casingWidth;
119 break;
120 case LEFT_CASING:
121 case RIGHT_CASING:
122 width = getWidth(c, type.prefix + WIDTH, null);
123 break;
124 default:
125 throw new AssertionError();
126 }
127 if (width == null)
128 return null;
129
130 float realWidth = c.get(type.prefix + REAL_WIDTH, 0f, Float.class);
131 if (realWidth > 0 && MapPaintSettings.INSTANCE.isUseRealWidth()) {
132
133 /* if we have a "width" tag, try use it */
134 String widthTag = env.osm.get("width");
135 if (widthTag == null) {
136 widthTag = env.osm.get("est_width");
137 }
138 if (widthTag != null) {
139 try {
140 realWidth = Float.valueOf(widthTag);
141 } catch(NumberFormatException nfe) {
142 Main.warn(nfe);
143 }
144 }
145 }
146
147 Float offset = c.get(OFFSET, 0f, Float.class);
148 switch (type) {
149 case NORMAL:
150 break;
151 case CASING:
152 offset += c.get(type.prefix + OFFSET, 0f, Float.class);
153 break;
154 case LEFT_CASING:
155 case RIGHT_CASING:
156 Float baseWidthOnDefault = getWidth(c_def, WIDTH, null);
157 Float baseWidth = getWidth(c, WIDTH, baseWidthOnDefault);
158 if (baseWidth == null || baseWidth < 2f) {
159 baseWidth = 2f;
160 }
161 float casingOffset = c.get(type.prefix + OFFSET, 0f, Float.class);
162 casingOffset += baseWidth / 2 + width / 2;
163 /* flip sign for the right-casing-offset */
164 if (type == LineType.RIGHT_CASING) {
165 casingOffset *= -1f;
166 }
167 offset += casingOffset;
168 break;
169 }
170
171 int alpha = 255;
172 Color color = c.get(type.prefix + COLOR, null, Color.class);
173 if (color != null) {
174 alpha = color.getAlpha();
175 }
176 if (type == LineType.NORMAL && color == null) {
177 color = c.get(FILL_COLOR, null, Color.class);
178 }
179 if (color == null) {
180 color = PaintColors.UNTAGGED.get();
181 }
182
183 Integer pAlpha = Utils.color_float2int(c.get(type.prefix + OPACITY, null, Float.class));
184 if (pAlpha != null) {
185 alpha = pAlpha;
186 }
187 color = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
188
189 float[] dashes = c.get(type.prefix + DASHES, null, float[].class, true);
190 if (dashes != null) {
191 boolean hasPositive = false;
192 for (float f : dashes) {
193 if (f > 0) {
194 hasPositive = true;
195 }
196 if (f < 0) {
197 dashes = null;
198 break;
199 }
200 }
201 if (!hasPositive || (dashes != null && dashes.length == 0)) {
202 dashes = null;
203 }
204 }
205 float dashesOffset = c.get(type.prefix + DASHES_OFFSET, 0f, Float.class);
206 Color dashesBackground = c.get(type.prefix + DASHES_BACKGROUND_COLOR, null, Color.class);
207 if (dashesBackground != null) {
208 pAlpha = Utils.color_float2int(c.get(type.prefix + DASHES_BACKGROUND_OPACITY, null, Float.class));
209 if (pAlpha != null) {
210 alpha = pAlpha;
211 }
212 dashesBackground = new Color(dashesBackground.getRed(), dashesBackground.getGreen(),
213 dashesBackground.getBlue(), alpha);
214 }
215
216 Integer cap = null;
217 Keyword capKW = c.get(type.prefix + LINECAP, null, Keyword.class);
218 if (capKW != null) {
219 if ("none".equals(capKW.val)) {
220 cap = BasicStroke.CAP_BUTT;
221 } else if ("round".equals(capKW.val)) {
222 cap = BasicStroke.CAP_ROUND;
223 } else if ("square".equals(capKW.val)) {
224 cap = BasicStroke.CAP_SQUARE;
225 }
226 }
227 if (cap == null) {
228 cap = dashes != null ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
229 }
230
231 Integer join = null;
232 Keyword joinKW = c.get(type.prefix + LINEJOIN, null, Keyword.class);
233 if (joinKW != null) {
234 if ("round".equals(joinKW.val)) {
235 join = BasicStroke.JOIN_ROUND;
236 } else if ("miter".equals(joinKW.val)) {
237 join = BasicStroke.JOIN_MITER;
238 } else if ("bevel".equals(joinKW.val)) {
239 join = BasicStroke.JOIN_BEVEL;
240 }
241 }
242 if (join == null) {
243 join = BasicStroke.JOIN_ROUND;
244 }
245
246 float miterlimit = c.get(type.prefix + MITERLIMIT, 10f, Float.class);
247 if (miterlimit < 1f) {
248 miterlimit = 10f;
249 }
250
251 BasicStroke line = new BasicStroke(width, cap, join, miterlimit, dashes, dashesOffset);
252 BasicStroke dashesLine = null;
253
254 if (dashes != null && dashesBackground != null) {
255 float[] dashes2 = new float[dashes.length];
256 System.arraycopy(dashes, 0, dashes2, 1, dashes.length - 1);
257 dashes2[0] = dashes[dashes.length-1];
258 dashesLine = new BasicStroke(width, cap, join, miterlimit, dashes2, dashes2[0] + dashesOffset);
259 }
260
261 return new LineElemStyle(c, type.defaultMajorZIndex, line, color, dashesLine, dashesBackground, offset, realWidth);
262 }
263
264 @Override
265 public void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter,
266 boolean selected, boolean outermember, boolean member) {
267 Way w = (Way)primitive;
268 /* show direction arrows, if draw.segment.relevant_directions_only is not set,
269 the way is tagged with a direction key
270 (even if the tag is negated as in oneway=false) or the way is selected */
271 boolean showOrientation = !isModifier && (selected || paintSettings.isShowDirectionArrow()) && !paintSettings.isUseRealWidth();
272 boolean showOneway = !isModifier && !selected &&
273 !paintSettings.isUseRealWidth() &&
274 paintSettings.isShowOnewayArrow() && w.hasDirectionKeys();
275 boolean onewayReversed = w.reversedDirection();
276 /* head only takes over control if the option is true,
277 the direction should be shown at all and not only because it's selected */
278 boolean showOnlyHeadArrowOnly = showOrientation && !selected && paintSettings.isShowHeadArrowOnly();
279 Node lastN;
280
281 Color myDashedColor = dashesBackground;
282 BasicStroke myLine = line, myDashLine = dashesLine;
283 if (realWidth > 0 && paintSettings.isUseRealWidth() && !showOrientation) {
284 float myWidth = (int) (100 / (float) (painter.getCircum() / realWidth));
285 if (myWidth < line.getLineWidth()) {
286 myWidth = line.getLineWidth();
287 }
288 myLine = new BasicStroke(myWidth, line.getEndCap(), line.getLineJoin(),
289 line.getMiterLimit(), line.getDashArray(), line.getDashPhase());
290 if (dashesLine != null) {
291 myDashLine = new BasicStroke(myWidth, dashesLine.getEndCap(), dashesLine.getLineJoin(),
292 dashesLine.getMiterLimit(), dashesLine.getDashArray(), dashesLine.getDashPhase());
293 }
294 }
295
296 Color myColor = color;
297 if (selected) {
298 myColor = paintSettings.getSelectedColor(color.getAlpha());
299 } else if (member || outermember) {
300 myColor = paintSettings.getRelationSelectedColor(color.getAlpha());
301 } else if(w.isDisabled()) {
302 myColor = paintSettings.getInactiveColor();
303 myDashedColor = paintSettings.getInactiveColor();
304 }
305
306 painter.drawWay(w, myColor, myLine, myDashLine, myDashedColor, offset, showOrientation,
307 showOnlyHeadArrowOnly, showOneway, onewayReversed);
308
309 if(paintSettings.isShowOrderNumber() && !painter.isInactiveMode()) {
310 int orderNumber = 0;
311 lastN = null;
312 for(Node n : w.getNodes()) {
313 if(lastN != null) {
314 orderNumber++;
315 painter.drawOrderNumber(lastN, n, orderNumber, myColor);
316 }
317 lastN = n;
318 }
319 }
320 }
321
322 @Override
323 public boolean isProperLineStyle() {
324 return !isModifier;
325 }
326
327 @Override
328 public boolean equals(Object obj) {
329 if (obj == null || getClass() != obj.getClass())
330 return false;
331 if (!super.equals(obj))
332 return false;
333 final LineElemStyle other = (LineElemStyle) obj;
334 return Objects.equals(line, other.line) &&
335 Objects.equals(color, other.color) &&
336 Objects.equals(dashesLine, other.dashesLine) &&
337 Objects.equals(dashesBackground, other.dashesBackground) &&
338 offset == other.offset &&
339 realWidth == other.realWidth;
340 }
341
342 @Override
343 public int hashCode() {
344 int hash = super.hashCode();
345 hash = 29 * hash + line.hashCode();
346 hash = 29 * hash + color.hashCode();
347 hash = 29 * hash + (dashesLine != null ? dashesLine.hashCode() : 0);
348 hash = 29 * hash + (dashesBackground != null ? dashesBackground.hashCode() : 0);
349 hash = 29 * hash + Float.floatToIntBits(offset);
350 hash = 29 * hash + Float.floatToIntBits(realWidth);
351 return hash;
352 }
353
354 @Override
355 public String toString() {
356 return "LineElemStyle{" + super.toString() + "width=" + line.getLineWidth() +
357 " realWidth=" + realWidth + " color=" + Utils.toString(color) +
358 " dashed=" + Arrays.toString(line.getDashArray()) +
359 (line.getDashPhase() == 0 ? "" : " dashesOffses=" + line.getDashPhase()) +
360 " dashedColor=" + Utils.toString(dashesBackground) +
361 " linejoin=" + linejoinToString(line.getLineJoin()) +
362 " linecap=" + linecapToString(line.getEndCap()) +
363 (offset == 0 ? "" : " offset=" + offset) +
364 '}';
365 }
366
367 public String linejoinToString(int linejoin) {
368 switch (linejoin) {
369 case BasicStroke.JOIN_BEVEL: return "bevel";
370 case BasicStroke.JOIN_ROUND: return "round";
371 case BasicStroke.JOIN_MITER: return "miter";
372 default: return null;
373 }
374 }
375
376 public String linecapToString(int linecap) {
377 switch (linecap) {
378 case BasicStroke.CAP_BUTT: return "none";
379 case BasicStroke.CAP_ROUND: return "round";
380 case BasicStroke.CAP_SQUARE: return "square";
381 default: return null;
382 }
383 }
384}
Note: See TracBrowser for help on using the repository browser.