source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/StyleElement.java@ 10238

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

sonar - squid:S1873 - "static final" arrays should be "private"

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint.styleelement;
3
4import java.awt.Font;
5import java.util.HashMap;
6import java.util.Map;
7import java.util.Objects;
8
9import org.openstreetmap.josm.Main;
10import org.openstreetmap.josm.data.osm.OsmPrimitive;
11import org.openstreetmap.josm.data.osm.visitor.paint.MapPaintSettings;
12import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer;
13import org.openstreetmap.josm.gui.mappaint.Cascade;
14import org.openstreetmap.josm.gui.mappaint.Keyword;
15import org.openstreetmap.josm.gui.mappaint.StyleKeys;
16import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.RelativeFloat;
17
18public abstract class StyleElement implements StyleKeys {
19
20 protected static final int ICON_IMAGE_IDX = 0;
21 protected static final int ICON_WIDTH_IDX = 1;
22 protected static final int ICON_HEIGHT_IDX = 2;
23 protected static final int ICON_OPACITY_IDX = 3;
24 protected static final int ICON_OFFSET_X_IDX = 4;
25 protected static final int ICON_OFFSET_Y_IDX = 5;
26
27 public float majorZIndex;
28 public float zIndex;
29 public float objectZIndex;
30 public boolean isModifier; // false, if style can serve as main style for the
31 // primitive; true, if it is a highlight or modifier
32 public boolean defaultSelectedHandling;
33
34 public StyleElement(float majorZindex, float zIndex, float objectZindex, boolean isModifier, boolean defaultSelectedHandling) {
35 this.majorZIndex = majorZindex;
36 this.zIndex = zIndex;
37 this.objectZIndex = objectZindex;
38 this.isModifier = isModifier;
39 this.defaultSelectedHandling = defaultSelectedHandling;
40 }
41
42 protected StyleElement(Cascade c, float defaultMajorZindex) {
43 majorZIndex = c.get(MAJOR_Z_INDEX, defaultMajorZindex, Float.class);
44 zIndex = c.get(Z_INDEX, 0f, Float.class);
45 objectZIndex = c.get(OBJECT_Z_INDEX, 0f, Float.class);
46 isModifier = c.get(MODIFIER, Boolean.FALSE, Boolean.class);
47 defaultSelectedHandling = c.isDefaultSelectedHandling();
48 }
49
50 /**
51 * draws a primitive
52 * @param primitive primitive to draw
53 * @param paintSettings paint settings
54 * @param painter painter
55 * @param selected true, if primitive is selected
56 * @param outermember true, if primitive is not selected and outer member of a selected multipolygon relation
57 * @param member true, if primitive is not selected and member of a selected relation
58 */
59 public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, StyledMapRenderer painter,
60 boolean selected, boolean outermember, boolean member);
61
62 public boolean isProperLineStyle() {
63 return false;
64 }
65
66 /**
67 * Get a property value of type Width
68 * @param c the cascade
69 * @param key property key for the width value
70 * @param relativeTo reference width. Only needed, when relative width syntax is used, e.g. "+4".
71 * @return width
72 */
73 protected static Float getWidth(Cascade c, String key, Float relativeTo) {
74 Float width = c.get(key, null, Float.class, true);
75 if (width != null) {
76 if (width > 0)
77 return width;
78 } else {
79 Keyword widthKW = c.get(key, null, Keyword.class, true);
80 if (Keyword.THINNEST.equals(widthKW))
81 return 0f;
82 if (Keyword.DEFAULT.equals(widthKW))
83 return (float) MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
84 if (relativeTo != null) {
85 RelativeFloat widthRel = c.get(key, null, RelativeFloat.class, true);
86 if (widthRel != null)
87 return relativeTo + widthRel.val;
88 }
89 }
90 return null;
91 }
92
93 /* ------------------------------------------------------------------------------- */
94 /* cached values */
95 /* ------------------------------------------------------------------------------- */
96 /*
97 * Two preference values and the set of created fonts are cached in order to avoid
98 * expensive lookups and to avoid too many font objects
99 *
100 * FIXME: cached preference values are not updated if the user changes them during
101 * a JOSM session. Should have a listener listening to preference changes.
102 */
103 private static volatile String DEFAULT_FONT_NAME;
104 private static volatile Float DEFAULT_FONT_SIZE;
105 private static final Object lock = new Object();
106
107 // thread save access (double-checked locking)
108 private static Float getDefaultFontSize() {
109 Float s = DEFAULT_FONT_SIZE;
110 if (s == null) {
111 synchronized (lock) {
112 s = DEFAULT_FONT_SIZE;
113 if (s == null) {
114 DEFAULT_FONT_SIZE = s = (float) Main.pref.getInteger("mappaint.fontsize", 8);
115 }
116 }
117 }
118 return s;
119 }
120
121 private static String getDefaultFontName() {
122 String n = DEFAULT_FONT_NAME;
123 if (n == null) {
124 synchronized (lock) {
125 n = DEFAULT_FONT_NAME;
126 if (n == null) {
127 DEFAULT_FONT_NAME = n = Main.pref.get("mappaint.font", "Droid Sans");
128 }
129 }
130 }
131 return n;
132 }
133
134 private static class FontDescriptor {
135 public String name;
136 public int style;
137 public int size;
138
139 FontDescriptor(String name, int style, int size) {
140 this.name = name;
141 this.style = style;
142 this.size = size;
143 }
144
145 @Override
146 public int hashCode() {
147 return Objects.hash(name, style, size);
148 }
149
150 @Override
151 public boolean equals(Object obj) {
152 if (this == obj) return true;
153 if (obj == null || getClass() != obj.getClass()) return false;
154 FontDescriptor that = (FontDescriptor) obj;
155 return style == that.style &&
156 size == that.size &&
157 Objects.equals(name, that.name);
158 }
159 }
160
161 private static final Map<FontDescriptor, Font> FONT_MAP = new HashMap<>();
162
163 private static Font getCachedFont(FontDescriptor fd) {
164 Font f = FONT_MAP.get(fd);
165 if (f != null) return f;
166 f = new Font(fd.name, fd.style, fd.size);
167 FONT_MAP.put(fd, f);
168 return f;
169 }
170
171 private static Font getCachedFont(String name, int style, int size) {
172 return getCachedFont(new FontDescriptor(name, style, size));
173 }
174
175 protected static Font getFont(Cascade c, String s) {
176 String name = c.get(FONT_FAMILY, getDefaultFontName(), String.class);
177 float size = c.get(FONT_SIZE, getDefaultFontSize(), Float.class);
178 int weight = Font.PLAIN;
179 if ("bold".equalsIgnoreCase(c.get(FONT_WEIGHT, null, String.class))) {
180 weight = Font.BOLD;
181 }
182 int style = Font.PLAIN;
183 if ("italic".equalsIgnoreCase(c.get(FONT_STYLE, null, String.class))) {
184 style = Font.ITALIC;
185 }
186 Font f = getCachedFont(name, style | weight, Math.round(size));
187 if (f.canDisplayUpTo(s) == -1)
188 return f;
189 else {
190 // fallback if the string contains characters that cannot be
191 // rendered by the selected font
192 return getCachedFont("SansSerif", style | weight, Math.round(size));
193 }
194 }
195
196 @Override
197 public boolean equals(Object o) {
198 if (this == o) return true;
199 if (o == null || getClass() != o.getClass()) return false;
200 StyleElement that = (StyleElement) o;
201 return Float.compare(that.majorZIndex, majorZIndex) == 0 &&
202 Float.compare(that.zIndex, zIndex) == 0 &&
203 Float.compare(that.objectZIndex, objectZIndex) == 0 &&
204 isModifier == that.isModifier;
205 }
206
207 @Override
208 public int hashCode() {
209 return Objects.hash(majorZIndex, zIndex, objectZIndex, isModifier);
210 }
211
212 @Override
213 public String toString() {
214 return String.format("z_idx=[%s/%s/%s] ", majorZIndex, zIndex, objectZIndex) + (isModifier ? "modifier " : "");
215 }
216}
Note: See TracBrowser for help on using the repository browser.