1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.tagging.presets.items;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.awt.GridBagLayout;
|
---|
7 | import java.util.ArrayList;
|
---|
8 | import java.util.Collection;
|
---|
9 | import java.util.List;
|
---|
10 | import java.util.Set;
|
---|
11 |
|
---|
12 | import javax.swing.JLabel;
|
---|
13 | import javax.swing.JPanel;
|
---|
14 |
|
---|
15 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
16 | import org.openstreetmap.josm.data.osm.Tag;
|
---|
17 | import org.openstreetmap.josm.data.osm.search.SearchCompiler;
|
---|
18 | import org.openstreetmap.josm.data.osm.search.SearchParseError;
|
---|
19 | import org.openstreetmap.josm.data.osm.search.SearchSetting;
|
---|
20 | import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;
|
---|
21 | import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetType;
|
---|
22 | import org.openstreetmap.josm.tools.GBC;
|
---|
23 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
24 | import org.xml.sax.SAXException;
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * The <code>roles</code> element in tagging presets definition.
|
---|
28 | * <p>
|
---|
29 | * A list of {@link Role} elements. Describes the roles that are expected for
|
---|
30 | * the members of a relation.
|
---|
31 | * <p>
|
---|
32 | * Used for data validation, auto completion, among others.
|
---|
33 | */
|
---|
34 | public class Roles extends TaggingPresetItem {
|
---|
35 |
|
---|
36 | /**
|
---|
37 | * The <code>role</code> element in tagging preset definition.
|
---|
38 | *
|
---|
39 | * Information on a certain role, which is expected for the relation members.
|
---|
40 | */
|
---|
41 | public static class Role {
|
---|
42 | /** Presets types expected for this role */
|
---|
43 | public Set<TaggingPresetType> types; // NOSONAR
|
---|
44 | /** Role name used in a relation */
|
---|
45 | public String key; // NOSONAR
|
---|
46 | /** Is the role name a regular expression */
|
---|
47 | public boolean regexp; // NOSONAR
|
---|
48 | /** The text to display */
|
---|
49 | public String text; // NOSONAR
|
---|
50 | /** The context used for translating {@link #text} */
|
---|
51 | public String text_context; // NOSONAR
|
---|
52 | /** The localized version of {@link #text}. */
|
---|
53 | public String locale_text; // NOSONAR
|
---|
54 | /** An expression (cf. search dialog) for objects of this role */
|
---|
55 | public SearchCompiler.Match memberExpression; // NOSONAR
|
---|
56 | /** Is this role required at least once in the relation? */
|
---|
57 | public boolean required; // NOSONAR
|
---|
58 | /** How often must the element appear */
|
---|
59 | private short count;
|
---|
60 |
|
---|
61 | /**
|
---|
62 | * Sets the presets types expected for this role.
|
---|
63 | * @param types comma-separated set of expected types
|
---|
64 | * @throws SAXException if an unknown type is detected
|
---|
65 | */
|
---|
66 | public void setType(String types) throws SAXException {
|
---|
67 | this.types = getType(types);
|
---|
68 | }
|
---|
69 |
|
---|
70 | /**
|
---|
71 | * Sets whether this role is required at least once in the relation.
|
---|
72 | * @param str "required" or "optional"
|
---|
73 | * @throws SAXException if str is neither "required" or "optional"
|
---|
74 | */
|
---|
75 | public void setRequisite(String str) throws SAXException {
|
---|
76 | if ("required".equals(str)) {
|
---|
77 | required = true;
|
---|
78 | } else if (!"optional".equals(str))
|
---|
79 | throw new SAXException(tr("Unknown requisite: {0}", str));
|
---|
80 | }
|
---|
81 |
|
---|
82 | /**
|
---|
83 | * Sets whether the role name is a regular expression.
|
---|
84 | * @param str "true" or "false"
|
---|
85 | * @throws SAXException if str is neither "true" or "false"
|
---|
86 | */
|
---|
87 | public void setRegexp(String str) throws SAXException {
|
---|
88 | if ("true".equals(str)) {
|
---|
89 | regexp = true;
|
---|
90 | } else if (!"false".equals(str))
|
---|
91 | throw new SAXException(tr("Unknown regexp value: {0}", str));
|
---|
92 | }
|
---|
93 |
|
---|
94 | /**
|
---|
95 | * Sets an expression (cf. search dialog) for objects of this role
|
---|
96 | * @param memberExpression an expression (cf. search dialog) for objects of this role
|
---|
97 | * @throws SAXException in case of parsing error
|
---|
98 | */
|
---|
99 | public void setMember_expression(String memberExpression) throws SAXException {
|
---|
100 | try {
|
---|
101 | final SearchSetting searchSetting = new SearchSetting();
|
---|
102 | searchSetting.text = memberExpression;
|
---|
103 | searchSetting.caseSensitive = true;
|
---|
104 | searchSetting.regexSearch = true;
|
---|
105 | this.memberExpression = SearchCompiler.compile(searchSetting);
|
---|
106 | } catch (SearchParseError ex) {
|
---|
107 | throw new SAXException(tr("Illegal member expression: {0}", ex.getMessage()), ex);
|
---|
108 | }
|
---|
109 | }
|
---|
110 |
|
---|
111 | /**
|
---|
112 | * Sets how often must the element appear.
|
---|
113 | * @param count how often must the element appear
|
---|
114 | */
|
---|
115 | public void setCount(String count) {
|
---|
116 | this.count = Short.parseShort(count);
|
---|
117 | }
|
---|
118 |
|
---|
119 | /**
|
---|
120 | * Return either argument, the highest possible value or the lowest allowed value
|
---|
121 | * @param c count
|
---|
122 | * @return the highest possible value or the lowest allowed value
|
---|
123 | * @see #required
|
---|
124 | */
|
---|
125 | public long getValidCount(long c) {
|
---|
126 | if (count > 0 && !required)
|
---|
127 | return c != 0 ? count : 0;
|
---|
128 | else if (count > 0)
|
---|
129 | return count;
|
---|
130 | else if (!required)
|
---|
131 | return c != 0 ? c : 0;
|
---|
132 | else
|
---|
133 | return c != 0 ? c : 1;
|
---|
134 | }
|
---|
135 |
|
---|
136 | /**
|
---|
137 | * Check if the given role matches this class (required to check regexp role types)
|
---|
138 | * @param role role to check
|
---|
139 | * @return <code>true</code> if role matches
|
---|
140 | * @since 11989
|
---|
141 | */
|
---|
142 | public boolean isRole(String role) {
|
---|
143 | if (regexp && role != null) { // pass null through, it will anyway fail
|
---|
144 | return role.matches(this.key);
|
---|
145 | }
|
---|
146 | return this.key.equals(role);
|
---|
147 | }
|
---|
148 |
|
---|
149 | /**
|
---|
150 | * Adds this role to the given panel.
|
---|
151 | * @param p panel where to add this role
|
---|
152 | * @return {@code true}
|
---|
153 | */
|
---|
154 | public boolean addToPanel(JPanel p) {
|
---|
155 | String cstring;
|
---|
156 | if (count > 0 && !required) {
|
---|
157 | cstring = "0,"+count;
|
---|
158 | } else if (count > 0) {
|
---|
159 | cstring = String.valueOf(count);
|
---|
160 | } else if (!required) {
|
---|
161 | cstring = "0-...";
|
---|
162 | } else {
|
---|
163 | cstring = "1-...";
|
---|
164 | }
|
---|
165 | if (locale_text == null) {
|
---|
166 | locale_text = getLocaleText(text, text_context, null);
|
---|
167 | }
|
---|
168 | p.add(new JLabel(locale_text+':'), GBC.std().insets(0, 0, 10, 0));
|
---|
169 | p.add(new JLabel(key), GBC.std().insets(0, 0, 10, 0));
|
---|
170 | p.add(new JLabel(cstring), types == null ? GBC.eol() : GBC.std().insets(0, 0, 10, 0));
|
---|
171 | if (types != null) {
|
---|
172 | JPanel pp = new JPanel();
|
---|
173 | for (TaggingPresetType t : types) {
|
---|
174 | pp.add(new JLabel(ImageProvider.get(t.getIconName())));
|
---|
175 | }
|
---|
176 | p.add(pp, GBC.eol());
|
---|
177 | }
|
---|
178 | return true;
|
---|
179 | }
|
---|
180 |
|
---|
181 | @Override
|
---|
182 | public String toString() {
|
---|
183 | return "Role [key=" + key + ", text=" + text + ']';
|
---|
184 | }
|
---|
185 | }
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * List of {@link Role} elements.
|
---|
189 | */
|
---|
190 | public final List<Role> roles = new ArrayList<>(2);
|
---|
191 |
|
---|
192 | @Override
|
---|
193 | public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel, boolean presetInitiallyMatches) {
|
---|
194 | p.add(new JLabel(" "), GBC.eol()); // space
|
---|
195 | if (!roles.isEmpty()) {
|
---|
196 | JPanel proles = new JPanel(new GridBagLayout());
|
---|
197 | proles.add(new JLabel(tr("Available roles")), GBC.std().insets(0, 0, 10, 0));
|
---|
198 | proles.add(new JLabel(tr("role")), GBC.std().insets(0, 0, 10, 0));
|
---|
199 | proles.add(new JLabel(tr("count")), GBC.std().insets(0, 0, 10, 0));
|
---|
200 | proles.add(new JLabel(tr("elements")), GBC.eol());
|
---|
201 | for (Role i : roles) {
|
---|
202 | i.addToPanel(proles);
|
---|
203 | }
|
---|
204 | p.add(proles, GBC.eol());
|
---|
205 | }
|
---|
206 | return false;
|
---|
207 | }
|
---|
208 |
|
---|
209 | @Override
|
---|
210 | public void addCommands(List<Tag> changedTags) {
|
---|
211 | // Do nothing
|
---|
212 | }
|
---|
213 |
|
---|
214 | @Override
|
---|
215 | public String toString() {
|
---|
216 | return "Roles [roles=" + roles + ']';
|
---|
217 | }
|
---|
218 | }
|
---|