source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/TagEditorModel.java@ 1916

Last change on this file since 1916 was 1843, checked in by jttt, 15 years ago

Use OsmPrimitive methods instead of direct access to keys field when possible

File size: 12.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import static org.openstreetmap.josm.tools.I18n.trn;
5
6import java.beans.PropertyChangeListener;
7import java.beans.PropertyChangeSupport;
8import java.util.ArrayList;
9import java.util.Collection;
10import java.util.Comparator;
11import java.util.List;
12import java.util.logging.Logger;
13
14import javax.swing.table.AbstractTableModel;
15
16import org.openstreetmap.josm.command.ChangePropertyCommand;
17import org.openstreetmap.josm.command.Command;
18import org.openstreetmap.josm.command.SequenceCommand;
19import org.openstreetmap.josm.data.osm.OsmPrimitive;
20
21
22/**
23 * TagEditorModel is a table model.
24 *
25 *
26 * @author gubaer
27 *
28 */
29@SuppressWarnings("serial")
30public class TagEditorModel extends AbstractTableModel {
31 static private final Logger logger = Logger.getLogger(TagEditorModel.class.getName());
32
33 static public final String PROP_DIRTY = TagEditorModel.class.getName() + ".dirty";
34
35 /** the list holding the tags */
36 private ArrayList<TagModel> tags = null;
37
38 /** indicates whether the model is dirty */
39 private boolean dirty = false;
40 private PropertyChangeSupport propChangeSupport = null;
41
42 /**
43 * constructor
44 */
45 public TagEditorModel(){
46 tags = new ArrayList<TagModel>();
47 propChangeSupport = new PropertyChangeSupport(this);
48 }
49
50 public void addPropertyChangeListener(PropertyChangeListener listener) {
51 propChangeSupport.addPropertyChangeListener(listener);
52 }
53
54 public void removeProperyChangeListener(PropertyChangeListener listener) {
55 propChangeSupport.removePropertyChangeListener(listener);
56 }
57
58 protected void fireDirtyStateChanged(final boolean oldValue, final boolean newValue) {
59 propChangeSupport.firePropertyChange(PROP_DIRTY, oldValue, newValue);
60 }
61
62 protected void setDirty(boolean newValue) {
63 boolean oldValue = dirty;
64 dirty = newValue;
65 if (oldValue != newValue) {
66 fireDirtyStateChanged(oldValue, newValue);
67 }
68 }
69
70 public int getColumnCount() {
71 return 2;
72 }
73
74 public int getRowCount() {
75 return tags.size();
76 }
77
78 public Object getValueAt(int rowIndex, int columnIndex) {
79 if (rowIndex >= getRowCount())
80 throw new IndexOutOfBoundsException("unexpected rowIndex: rowIndex=" + rowIndex);
81
82 TagModel tag = tags.get(rowIndex);
83 switch(columnIndex) {
84 case 0:
85 case 1: return tag;
86
87 default:
88 throw new IndexOutOfBoundsException("unexpected columnIndex: columnIndex=" + columnIndex);
89 }
90 }
91
92
93 /**
94 * removes all tags in the model
95 */
96 public void clear() {
97 tags.clear();
98 setDirty(true);
99 fireTableDataChanged();
100 }
101
102 /**
103 * adds a tag to the model
104 *
105 * @param tag the tag. Must not be null.
106 *
107 * @exception IllegalArgumentException thrown, if tag is null
108 */
109 public void add(TagModel tag) {
110 if (tag == null)
111 throw new IllegalArgumentException("argument 'tag' must not be null");
112 tags.add(tag);
113 setDirty(true);
114 fireTableDataChanged();
115 }
116
117
118 public void prepend(TagModel tag) {
119 if (tag == null)
120 throw new IllegalArgumentException("argument 'tag' must not be null");
121 tags.add(0, tag);
122 setDirty(true);
123 fireTableDataChanged();
124 }
125
126
127 /**
128 * adds a tag given by a name/value pair to the tag editor model.
129 *
130 * If there is no tag with name <code>name</name> yet, a new {@link TagModel} is created
131 * and append to this model.
132 *
133 * If there is a tag with name <code>name</name>, <code>value</code> is merged to the list
134 * of values for this tag.
135 *
136 * @param name the name; converted to "" if null
137 * @param value the value; converted to "" if null
138 */
139 public void add(String name, String value) {
140 name = (name == null) ? "" : name;
141 value = (value == null) ? "" : value;
142
143 TagModel tag = get(name);
144 if (tag == null) {
145 tag = new TagModel(name, value);
146 add(tag);
147 } else {
148 tag.addValue(value);
149 }
150 setDirty(true);
151 }
152
153
154 /**
155 * replies the tag with name <code>name</code>; null, if no such tag exists
156 * @param name the tag name
157 * @return the tag with name <code>name</code>; null, if no such tag exists
158 */
159 public TagModel get(String name) {
160 name = (name == null) ? "" : name;
161 for (TagModel tag : tags) {
162 if (tag.getName().equals(name))
163 return tag;
164 }
165 return null;
166 }
167
168 public TagModel get(int idx) {
169 TagModel tagModel = tags.get(idx);
170 return tagModel;
171 }
172
173
174
175 @Override public boolean isCellEditable(int row, int col) {
176 // all cells are editable
177 return true;
178 }
179
180
181 /**
182 * deletes the names of the tags given by tagIndices
183 *
184 * @param tagIndices a list of tag indices
185 */
186 public void deleteTagNames(int [] tagIndices) {
187 if (tags == null)
188 return;
189 for (int tagIdx : tagIndices) {
190 TagModel tag = tags.get(tagIdx);
191 if (tag != null) {
192 tag.setName("");
193 }
194 }
195 fireTableDataChanged();
196 setDirty(true);
197 }
198
199 /**
200 * deletes the values of the tags given by tagIndices
201 *
202 * @param tagIndices the lit of tag indices
203 */
204 public void deleteTagValues(int [] tagIndices) {
205 if (tags == null)
206 return;
207 for (int tagIdx : tagIndices) {
208 TagModel tag = tags.get(tagIdx);
209 if (tag != null) {
210 tag.setValue("");
211 }
212 }
213 fireTableDataChanged();
214 setDirty(true);
215 }
216
217 /**
218 * deletes the tags given by tagIndices
219 *
220 * @param tagIndices the list of tag indices
221 */
222 public void deleteTags(int [] tagIndices) {
223 if (tags == null)
224 return;
225 ArrayList<TagModel> toDelete = new ArrayList<TagModel>();
226 for (int tagIdx : tagIndices) {
227 TagModel tag = tags.get(tagIdx);
228 if (tag != null) {
229 toDelete.add(tag);
230 }
231 }
232 for (TagModel tag : toDelete) {
233 tags.remove(tag);
234 }
235 fireTableDataChanged();
236 setDirty(true);
237 }
238
239
240 /**
241 * creates a new tag and appends it to the model
242 */
243 public void appendNewTag() {
244 TagModel tag = new TagModel();
245 tags.add(tag);
246 fireTableDataChanged();
247 setDirty(true);
248 }
249
250 /**
251 * makes sure the model includes at least one (empty) tag
252 */
253 public void ensureOneTag() {
254 if (tags.size() == 0) {
255 appendNewTag();
256 }
257 }
258
259 /**
260 * initializes the model with the tags of an OSM primitive
261 *
262 * @param primitive the OSM primitive
263 */
264 public void initFromPrimitive(OsmPrimitive primitive) {
265 clear();
266 for (String key : primitive.keySet()) {
267 String value = primitive.get(key);
268 add(key,value);
269 }
270 TagModel tag = new TagModel();
271 sort();
272 tags.add(tag);
273 setDirty(false);
274 }
275
276 /**
277 * applies the current state of the tag editor model to a primitive
278 *
279 * @param primitive the primitive
280 *
281 */
282 public void applyToPrimitive(OsmPrimitive primitive) {
283 primitive.removeAll();
284 for (TagModel tag: tags) {
285 // tag still holds an unchanged list of different values for the same key.
286 // no property change command required
287 if (tag.getValueCount() > 1) {
288 continue;
289 }
290
291 // tag name holds an empty key. Don't apply it to the selection.
292 //
293 if (tag.getName().trim().equals("")) {
294 continue;
295 }
296 primitive.put(tag.getName(), tag.getValue());
297 }
298 }
299
300 /**
301 * checks whether the tag model includes a tag with a given key
302 *
303 * @param key the key
304 * @return true, if the tag model includes the tag; false, otherwise
305 */
306 public boolean includesTag(String key) {
307 if (key == null) return false;
308 for (TagModel tag : tags) {
309 if (tag.getName().equals(key))
310 return true;
311 }
312 return false;
313 }
314
315
316 protected Command createUpdateTagCommand(Collection<OsmPrimitive> primitives, TagModel tag) {
317
318 // tag still holds an unchanged list of different values for the same key.
319 // no property change command required
320 if (tag.getValueCount() > 1)
321 return null;
322
323 // tag name holds an empty key. Don't apply it to the selection.
324 //
325 if (tag.getName().trim().equals(""))
326 return null;
327
328 String newkey = tag.getName();
329 String newvalue = tag.getValue();
330
331 ChangePropertyCommand command = new ChangePropertyCommand(primitives,newkey, newvalue);
332 return command;
333 }
334
335 protected Command createDeleteTagsCommand(Collection<OsmPrimitive> primitives) {
336
337 List<String> currentkeys = getKeys();
338 ArrayList<Command> commands = new ArrayList<Command>();
339
340 for (OsmPrimitive primitive : primitives) {
341 for (String oldkey : primitive.keySet()) {
342 if (!currentkeys.contains(oldkey)) {
343 ChangePropertyCommand deleteCommand =
344 new ChangePropertyCommand(primitive,oldkey,null);
345 commands.add(deleteCommand);
346 }
347 }
348 }
349
350 SequenceCommand command = new SequenceCommand(
351 trn("Remove old keys from up to {0} object", "Remove old keys from up to {0} objects", primitives.size(), primitives.size()),
352 commands
353 );
354
355 return command;
356 }
357
358 /**
359 * replies the list of keys of the tags managed by this model
360 *
361 * @return the list of keys managed by this model
362 */
363 public List<String> getKeys() {
364 ArrayList<String> keys = new ArrayList<String>();
365 for (TagModel tag: tags) {
366 if (!tag.getName().trim().equals("")) {
367 keys.add(tag.getName());
368 }
369 }
370 return keys;
371 }
372
373 /**
374 * sorts the current tags according alphabetical order of names
375 */
376 protected void sort() {
377 java.util.Collections.sort(
378 tags,
379 new Comparator<TagModel>() {
380 public int compare(TagModel self, TagModel other) {
381 return self.getName().compareTo(other.getName());
382 }
383 }
384 );
385 }
386
387 /**
388 * updates the name of a tag and sets the dirty state to true if
389 * the new name is different from the old name.
390 *
391 * @param tag the tag
392 * @param newName the new name
393 */
394 public void updateTagName(TagModel tag, String newName) {
395 String oldName = tag.getName();
396 tag.setName(newName);
397 if (! newName.equals(oldName)) {
398 setDirty(true);
399 }
400 }
401
402 /**
403 * updates the value value of a tag and sets the dirty state to true if the
404 * new name is different from the old name
405 *
406 * @param tag the tag
407 * @param newValue the new value
408 */
409 public void updateTagValue(TagModel tag, String newValue) {
410 String oldValue = tag.getValue();
411 tag.setValue(newValue);
412 if (! newValue.equals(oldValue)) {
413 setDirty(true);
414 }
415 }
416
417 /**
418 * replies true, if this model has been updated
419 *
420 * @return true, if this model has been updated
421 */
422 public boolean isDirty() {
423 return dirty;
424 }
425}
Note: See TracBrowser for help on using the repository browser.