source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java@ 3083

Last change on this file since 3083 was 3083, checked in by bastiK, 14 years ago

added svn:eol-style=native to source files

  • Property svn:eol-style set to native
File size: 8.3 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.tr;
5
6import java.beans.PropertyChangeListener;
7import java.beans.PropertyChangeSupport;
8import java.lang.reflect.Constructor;
9import java.lang.reflect.Method;
10import java.util.ArrayList;
11import java.util.Collection;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.data.osm.Relation;
15import org.openstreetmap.josm.data.osm.RelationMember;
16import org.openstreetmap.josm.gui.ExtendedDialog;
17import org.openstreetmap.josm.gui.layer.OsmDataLayer;
18import org.openstreetmap.josm.tools.CheckParameterUtil;
19
20public abstract class RelationEditor extends ExtendedDialog {
21 /** the property name for the current relation.
22 * @see #setRelation(Relation)
23 * @see #getRelation()
24 */
25 static public final String RELATION_PROP = RelationEditor.class.getName() + ".relation";
26
27 /** the property name for the current relation snapshot
28 * @see #getRelationSnapshot()
29 */
30 static public final String RELATION_SNAPSHOT_PROP = RelationEditor.class.getName() + ".relationSnapshot";
31
32 /** the list of registered relation editor classes */
33 private static ArrayList<Class<RelationEditor>> editors = new ArrayList<Class<RelationEditor>>();
34
35 /**
36 * Registers a relation editor class. Depending on the type of relation to be edited
37 * {@see #getEditor(OsmDataLayer, Relation, Collection)} will create an instance of
38 * this class.
39 *
40 * @param clazz the class
41 */
42 public void registerRelationEditor(Class<RelationEditor> clazz) {
43 if (clazz == null) return;
44 if (!editors.contains(clazz)) {
45 editors.add(clazz);
46 }
47 }
48
49 /**
50 * The relation that this editor is working on.
51 */
52 private Relation relation;
53
54 /**
55 * The version of the relation when editing is started. This is
56 * null if a new relation is created. */
57 private Relation relationSnapshot;
58
59 /** the data layer the relation belongs to */
60 private OsmDataLayer layer;
61
62 /**
63 * This is a factory method that creates an appropriate RelationEditor
64 * instance suitable for editing the relation that was passed in as an
65 * argument.
66 *
67 * This method is guaranteed to return a working RelationEditor. If no
68 * specific editor has been registered for the type of relation, then
69 * a generic editor will be returned.
70 *
71 * Editors can be registered by adding their class to the static list "editors"
72 * in the RelationEditor class. When it comes to editing a relation, all
73 * registered editors are queried via their static "canEdit" method whether they
74 * feel responsible for that kind of relation, and if they return true
75 * then an instance of that class will be used.
76 *
77 * @param layer the data layer the relation is a member of
78 * @param r the relation to be edited
79 * @param selectedMembers a collection of relation members which shall be selected when the
80 * editor is first launched
81 * @return an instance of RelationEditor suitable for editing that kind of relation
82 */
83 public static RelationEditor getEditor(OsmDataLayer layer, Relation r, Collection<RelationMember> selectedMembers) {
84 for (Class<RelationEditor> e : editors) {
85 try {
86 Method m = e.getMethod("canEdit", Relation.class);
87 Boolean canEdit = (Boolean) m.invoke(null, r);
88 if (canEdit) {
89 Constructor<RelationEditor> con = e.getConstructor(Relation.class, Collection.class);
90 RelationEditor editor = con.newInstance(layer, r, selectedMembers);
91 return editor;
92 }
93 } catch (Exception ex) {
94 // plod on
95 }
96 }
97 if (RelationDialogManager.getRelationDialogManager().isOpenInEditor(layer, r))
98 return RelationDialogManager.getRelationDialogManager().getEditorForRelation(layer, r);
99 else {
100 RelationEditor editor = new GenericRelationEditor(layer, r, selectedMembers);
101 RelationDialogManager.getRelationDialogManager().positionOnScreen(editor);
102 RelationDialogManager.getRelationDialogManager().register(layer, r, editor);
103 return editor;
104 }
105 }
106
107 /**
108 * Creates a new relation editor
109 *
110 * @param layer the {@see OsmDataLayer} in whose context a relation is edited. Must not be null.
111 * @param relation the relation. Can be null if a new relation is to be edited.
112 * @param selectedMembers a collection of members in <code>relation</code> which the editor
113 * should display selected when the editor is first displayed on screen
114 * @throws IllegalArgumentException thrown if layer is null
115 */
116 protected RelationEditor(OsmDataLayer layer, Relation relation, Collection<RelationMember> selectedMembers) throws IllegalArgumentException{
117 // Initalizes ExtendedDialog
118 super(Main.parent,
119 "",
120 new String[] { tr("Apply Changes"), tr("Cancel")},
121 false
122 );
123 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
124 this.layer = layer;
125 setRelation(relation);
126 }
127
128 /**
129 * updates the title of the relation editor
130 */
131 protected void updateTitle() {
132 if (getRelation() == null) {
133 setTitle(tr("Create new relation in layer ''{0}''", layer.getName()));
134 } else if (getRelation().isNew()) {
135 setTitle(tr("Edit new relation in layer ''{0}''", layer.getName()));
136 } else {
137 setTitle(tr("Edit relation #{0} in layer ''{1}''", relation.getId(), layer.getName()));
138 }
139 }
140 /**
141 * Replies the currently edited relation
142 *
143 * @return the currently edited relation
144 */
145 protected Relation getRelation() {
146 return relation;
147 }
148
149 /**
150 * Sets the currently edited relation. Creates a snapshot of the current
151 * state of the relation. See {@see #getRelationSnapshot()}
152 *
153 * @param relation the relation
154 */
155 protected void setRelation(Relation relation) {
156 setRelationSnapshot((relation == null) ? null : new Relation(relation));
157 Relation oldValue = this.relation;
158 this.relation = relation;
159 if (this.relation != oldValue) {
160 support.firePropertyChange(RELATION_PROP, oldValue, this.relation);
161 }
162 updateTitle();
163 }
164
165 /**
166 * Replies the {@see OsmDataLayer} in whose context this relation editor is
167 * open
168 *
169 * @return the {@see OsmDataLayer} in whose context this relation editor is
170 * open
171 */
172 protected OsmDataLayer getLayer() {
173 return layer;
174 }
175
176 /**
177 * Replies the state of the edited relation when the editor has been launched
178 *
179 * @return the state of the edited relation when the editor has been launched
180 */
181 protected Relation getRelationSnapshot() {
182 return relationSnapshot;
183 }
184
185 protected void setRelationSnapshot(Relation snapshot) {
186 Relation oldValue = relationSnapshot;
187 relationSnapshot = snapshot;
188 if (relationSnapshot != oldValue) {
189 support.firePropertyChange(RELATION_SNAPSHOT_PROP, oldValue, relationSnapshot);
190 }
191 }
192
193 /**
194 * Replies true if the currently edited relation has been changed elsewhere.
195 *
196 * In this case a relation editor can't apply updates to the relation directly. Rather,
197 * it has to create a conflict.
198 *
199 * @return true if the currently edited relation has been changed elsewhere.
200 */
201 protected boolean isDirtyRelation() {
202 return ! relation.hasEqualSemanticAttributes(relationSnapshot);
203 }
204
205 /* ----------------------------------------------------------------------- */
206 /* property change support */
207 /* ----------------------------------------------------------------------- */
208 final private PropertyChangeSupport support = new PropertyChangeSupport(this);
209
210 @Override
211 public void addPropertyChangeListener(PropertyChangeListener listener) {
212 this.support.addPropertyChangeListener(listener);
213 }
214
215 @Override
216 public void removePropertyChangeListener(PropertyChangeListener listener) {
217 this.support.removePropertyChangeListener(listener);
218 }
219}
Note: See TracBrowser for help on using the repository browser.