001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.relation; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.beans.PropertyChangeListener; 007import java.beans.PropertyChangeSupport; 008import java.util.Collection; 009 010import org.openstreetmap.josm.Main; 011import org.openstreetmap.josm.data.osm.Relation; 012import org.openstreetmap.josm.data.osm.RelationMember; 013import org.openstreetmap.josm.gui.ExtendedDialog; 014import org.openstreetmap.josm.gui.layer.OsmDataLayer; 015import org.openstreetmap.josm.tools.CheckParameterUtil; 016 017/** 018 * Abstract relation editor. 019 * @since 1599 020 */ 021public abstract class RelationEditor extends ExtendedDialog implements IRelationEditor { 022 private static final long serialVersionUID = 1L; 023 024 /** the property name for the current relation. 025 * @see #setRelation(Relation) 026 * @see #getRelation() 027 */ 028 public static final String RELATION_PROP = RelationEditor.class.getName() + ".relation"; 029 030 /** the property name for the current relation snapshot 031 * @see #getRelationSnapshot() 032 */ 033 public static final String RELATION_SNAPSHOT_PROP = RelationEditor.class.getName() + ".relationSnapshot"; 034 035 /** The relation that this editor is working on. */ 036 private transient Relation relation; 037 038 /** The version of the relation when editing is started. This is null if a new relation is created. */ 039 private transient Relation relationSnapshot; 040 041 /** The data layer the relation belongs to */ 042 private final transient OsmDataLayer layer; 043 044 private final PropertyChangeSupport support = new PropertyChangeSupport(this); 045 046 /** 047 * Creates a new relation editor 048 * 049 * @param layer the {@link OsmDataLayer} in whose context a relation is edited. Must not be null. 050 * @param relation the relation. Can be null if a new relation is to be edited. 051 * @throws IllegalArgumentException if layer is null 052 */ 053 protected RelationEditor(OsmDataLayer layer, Relation relation) { 054 super(Main.parent, 055 "", 056 new String[] {tr("Apply Changes"), tr("Cancel")}, 057 false, 058 false 059 ); 060 CheckParameterUtil.ensureParameterNotNull(layer, "layer"); 061 this.layer = layer; 062 setRelation(relation); 063 layer.removeRecentRelation(relation); 064 } 065 066 /** 067 * This is a factory method that creates an appropriate RelationEditor instance suitable for editing the relation 068 * that was passed in as an argument. 069 * 070 * This method is guaranteed to return a working RelationEditor. 071 * 072 * @param layer the data layer the relation is a member of 073 * @param r the relation to be edited 074 * @param selectedMembers a collection of relation members which shall be selected when the editor is first launched 075 * @return an instance of RelationEditor suitable for editing that kind of relation 076 */ 077 public static RelationEditor getEditor(OsmDataLayer layer, Relation r, Collection<RelationMember> selectedMembers) { 078 if (RelationDialogManager.getRelationDialogManager().isOpenInEditor(layer, r)) 079 return RelationDialogManager.getRelationDialogManager().getEditorForRelation(layer, r); 080 else { 081 RelationEditor editor = new GenericRelationEditor(layer, r, selectedMembers); 082 RelationDialogManager.getRelationDialogManager().positionOnScreen(editor); 083 RelationDialogManager.getRelationDialogManager().register(layer, r, editor); 084 return editor; 085 } 086 } 087 088 /** 089 * updates the title of the relation editor 090 */ 091 protected void updateTitle() { 092 if (getRelation() == null) { 093 setTitle(tr("Create new relation in layer ''{0}''", layer.getName())); 094 } else if (getRelation().isNew()) { 095 setTitle(tr("Edit new relation in layer ''{0}''", layer.getName())); 096 } else { 097 setTitle(tr("Edit relation #{0} in layer ''{1}''", relation.getId(), layer.getName())); 098 } 099 } 100 101 @Override 102 public final Relation getRelation() { 103 return relation; 104 } 105 106 @Override 107 public final void setRelation(Relation relation) { 108 setRelationSnapshot((relation == null) ? null : new Relation(relation)); 109 Relation oldValue = this.relation; 110 this.relation = relation; 111 if (this.relation != oldValue) { 112 support.firePropertyChange(RELATION_PROP, oldValue, this.relation); 113 } 114 updateTitle(); 115 } 116 117 @Override 118 public final OsmDataLayer getLayer() { 119 return layer; 120 } 121 122 @Override 123 public final Relation getRelationSnapshot() { 124 return relationSnapshot; 125 } 126 127 protected final void setRelationSnapshot(Relation snapshot) { 128 Relation oldValue = relationSnapshot; 129 relationSnapshot = snapshot; 130 if (relationSnapshot != oldValue) { 131 support.firePropertyChange(RELATION_SNAPSHOT_PROP, oldValue, relationSnapshot); 132 } 133 } 134 135 @Override 136 public final boolean isDirtyRelation() { 137 return !relation.hasEqualSemanticAttributes(relationSnapshot); 138 } 139 140 /* ----------------------------------------------------------------------- */ 141 /* property change support */ 142 /* ----------------------------------------------------------------------- */ 143 144 @Override 145 public final void addPropertyChangeListener(PropertyChangeListener listener) { 146 this.support.addPropertyChangeListener(listener); 147 } 148 149 @Override 150 public final void removePropertyChangeListener(PropertyChangeListener listener) { 151 this.support.removePropertyChangeListener(listener); 152 } 153 154 @Override 155 public void dispose() { 156 layer.setRecentRelation(relation); 157 super.dispose(); 158 } 159}