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

Last change on this file since 12620 was 12620, checked in by Don-vip, 12 months ago

see #15182 - deprecate all Main logging methods and introduce suitable replacements in Logging for most of them

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