source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/SavingAction.java@ 9665

Last change on this file since 9665 was 9665, checked in by stoecker, 8 years ago

fix eol-style issues and similar formating stuff, see #12410

File size: 8.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.util.ArrayList;
8import java.util.List;
9
10import javax.swing.JOptionPane;
11import javax.swing.SwingUtilities;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.command.AddCommand;
15import org.openstreetmap.josm.command.ChangeCommand;
16import org.openstreetmap.josm.command.conflict.ConflictAddCommand;
17import org.openstreetmap.josm.data.conflict.Conflict;
18import org.openstreetmap.josm.data.osm.Relation;
19import org.openstreetmap.josm.data.osm.RelationMember;
20import org.openstreetmap.josm.gui.DefaultNameFormatter;
21import org.openstreetmap.josm.gui.HelpAwareOptionPane;
22import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
23import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
24import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
25import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
26import org.openstreetmap.josm.gui.dialogs.relation.RelationDialogManager;
27import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
28import org.openstreetmap.josm.gui.layer.OsmDataLayer;
29import org.openstreetmap.josm.gui.tagging.TagEditorModel;
30import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
31import org.openstreetmap.josm.tools.ImageProvider;
32
33/**
34 * Abstract superclass of relation saving actions (OK, Apply, Cancel).
35 * @since 9496
36 */
37abstract class SavingAction extends AbstractRelationEditorAction {
38
39 protected final TagEditorModel tagModel;
40 protected final AutoCompletingTextField tfRole;
41
42 protected SavingAction(MemberTable memberTable, MemberTableModel memberTableModel, TagEditorModel tagModel, OsmDataLayer layer,
43 IRelationEditor editor, AutoCompletingTextField tfRole) {
44 super(memberTable, memberTableModel, null, layer, editor);
45 this.tagModel = tagModel;
46 this.tfRole = tfRole;
47 }
48
49 /**
50 * apply updates to a new relation
51 * @param tagEditorModel tag editor model
52 */
53 protected void applyNewRelation(TagEditorModel tagEditorModel) {
54 final Relation newRelation = new Relation();
55 tagEditorModel.applyToPrimitive(newRelation);
56 memberTableModel.applyToRelation(newRelation);
57 List<RelationMember> newMembers = new ArrayList<>();
58 for (RelationMember rm: newRelation.getMembers()) {
59 if (!rm.getMember().isDeleted()) {
60 newMembers.add(rm);
61 }
62 }
63 if (newRelation.getMembersCount() != newMembers.size()) {
64 newRelation.setMembers(newMembers);
65 String msg = tr("One or more members of this new relation have been deleted while the relation editor\n" +
66 "was open. They have been removed from the relation members list.");
67 JOptionPane.showMessageDialog(Main.parent, msg, tr("Warning"), JOptionPane.WARNING_MESSAGE);
68 }
69 // If the user wanted to create a new relation, but hasn't added any members or
70 // tags, don't add an empty relation
71 if (newRelation.getMembersCount() == 0 && !newRelation.hasKeys())
72 return;
73 Main.main.undoRedo.add(new AddCommand(layer, newRelation));
74
75 // make sure everybody is notified about the changes
76 //
77 layer.data.fireSelectionChanged();
78 editor.setRelation(newRelation);
79 if (editor instanceof RelationEditor) {
80 RelationDialogManager.getRelationDialogManager().updateContext(
81 layer, editor.getRelation(), (RelationEditor) editor);
82 }
83 SwingUtilities.invokeLater(new Runnable() {
84 @Override
85 public void run() {
86 // Relation list gets update in EDT so selecting my be postponed to following EDT run
87 Main.map.relationListDialog.selectRelation(newRelation);
88 }
89 });
90 }
91
92 /**
93 * Apply the updates for an existing relation which has been changed outside of the relation editor.
94 * @param tagEditorModel tag editor model
95 */
96 protected void applyExistingConflictingRelation(TagEditorModel tagEditorModel) {
97 Relation editedRelation = new Relation(editor.getRelation());
98 tagEditorModel.applyToPrimitive(editedRelation);
99 memberTableModel.applyToRelation(editedRelation);
100 Conflict<Relation> conflict = new Conflict<>(editor.getRelation(), editedRelation);
101 Main.main.undoRedo.add(new ConflictAddCommand(layer, conflict));
102 }
103
104 /**
105 * Apply the updates for an existing relation which has not been changed outside of the relation editor.
106 * @param tagEditorModel tag editor model
107 */
108 protected void applyExistingNonConflictingRelation(TagEditorModel tagEditorModel) {
109 Relation editedRelation = new Relation(editor.getRelation());
110 tagEditorModel.applyToPrimitive(editedRelation);
111 memberTableModel.applyToRelation(editedRelation);
112 Main.main.undoRedo.add(new ChangeCommand(editor.getRelation(), editedRelation));
113 layer.data.fireSelectionChanged();
114 }
115
116 protected boolean confirmClosingBecauseOfDirtyState() {
117 ButtonSpec[] options = new ButtonSpec[] {
118 new ButtonSpec(
119 tr("Yes, create a conflict and close"),
120 ImageProvider.get("ok"),
121 tr("Click to create a conflict and close this relation editor"),
122 null /* no specific help topic */
123 ),
124 new ButtonSpec(
125 tr("No, continue editing"),
126 ImageProvider.get("cancel"),
127 tr("Click to return to the relation editor and to resume relation editing"),
128 null /* no specific help topic */
129 )
130 };
131
132 int ret = HelpAwareOptionPane.showOptionDialog(
133 Main.parent,
134 tr("<html>This relation has been changed outside of the editor.<br>"
135 + "You cannot apply your changes and continue editing.<br>"
136 + "<br>"
137 + "Do you want to create a conflict and close the editor?</html>"),
138 tr("Conflict in data"),
139 JOptionPane.WARNING_MESSAGE,
140 null,
141 options,
142 options[0], // OK is default
143 "/Dialog/RelationEditor#RelationChangedOutsideOfEditor"
144 );
145 return ret == 0;
146 }
147
148 protected void warnDoubleConflict() {
149 JOptionPane.showMessageDialog(
150 Main.parent,
151 tr("<html>Layer ''{0}'' already has a conflict for object<br>"
152 + "''{1}''.<br>"
153 + "Please resolve this conflict first, then try again.</html>",
154 layer.getName(),
155 editor.getRelation().getDisplayName(DefaultNameFormatter.getInstance())
156 ),
157 tr("Double conflict"),
158 JOptionPane.WARNING_MESSAGE
159 );
160 }
161
162 @Override
163 protected void updateEnabledState() {
164 // Do nothing
165 }
166
167 protected boolean applyChanges() {
168 if (editor.getRelation() == null) {
169 applyNewRelation(tagModel);
170 } else if (isEditorDirty()) {
171 if (editor.isDirtyRelation()) {
172 if (confirmClosingBecauseOfDirtyState()) {
173 if (layer.getConflicts().hasConflictForMy(editor.getRelation())) {
174 warnDoubleConflict();
175 return false;
176 }
177 applyExistingConflictingRelation(tagModel);
178 hideEditor();
179 } else
180 return false;
181 } else {
182 applyExistingNonConflictingRelation(tagModel);
183 }
184 }
185 editor.setRelation(editor.getRelation());
186 return true;
187 }
188
189 protected void hideEditor() {
190 if (editor instanceof Component) {
191 ((Component) editor).setVisible(false);
192 }
193 }
194
195 protected boolean isEditorDirty() {
196 Relation snapshot = editor.getRelationSnapshot();
197 return (snapshot != null && !memberTableModel.hasSameMembersAs(snapshot)) || tagModel.isDirty();
198 }
199}
Note: See TracBrowser for help on using the repository browser.