source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java

Last change on this file was 19307, checked in by taylor.smock, 17 months ago

Fix most new PMD issues

It would be better to use the newer switch syntax introduced in Java 14 (JEP 361),
but we currently target Java 11+. When we move to Java 17, this should be
reverted and the newer switch syntax should be used.

  • Property svn:eol-style set to native
File size: 8.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.BorderLayout;
8import java.awt.Component;
9import java.awt.event.ActionEvent;
10import java.beans.PropertyChangeEvent;
11import java.beans.PropertyChangeListener;
12
13import javax.swing.AbstractAction;
14import javax.swing.Action;
15import javax.swing.JLabel;
16import javax.swing.JOptionPane;
17import javax.swing.JPanel;
18import javax.swing.SwingConstants;
19
20import org.openstreetmap.josm.data.UndoRedoHandler;
21import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.gui.ExtendedDialog;
24import org.openstreetmap.josm.gui.MainApplication;
25import org.openstreetmap.josm.gui.conflict.pair.ConflictResolver;
26import org.openstreetmap.josm.gui.help.HelpBrowser;
27import org.openstreetmap.josm.gui.help.HelpUtil;
28import org.openstreetmap.josm.tools.ImageProvider;
29
30/**
31 * This is an extended dialog for resolving conflict between {@link OsmPrimitive}s.
32 * @since 1622
33 */
34public class ConflictResolutionDialog extends ExtendedDialog implements PropertyChangeListener {
35 /** the conflict resolver component */
36 private final ConflictResolver resolver = new ConflictResolver();
37 private final JLabel titleLabel = new JLabel("", null, SwingConstants.CENTER);
38
39 private final ApplyResolutionAction applyResolutionAction = new ApplyResolutionAction();
40
41 private boolean isRegistered;
42
43 /**
44 * Constructs a new {@code ConflictResolutionDialog}.
45 * @param parent parent component
46 */
47 public ConflictResolutionDialog(Component parent) {
48 // We define our own actions, but need to give a hint about number of buttons
49 super(parent, tr("Resolve conflicts"), null, null, null);
50 setDefaultButton(1);
51 setCancelButton(2);
52 build();
53 pack();
54 if (getInsets().top > 0) {
55 titleLabel.setVisible(false);
56 }
57 }
58
59 @Override
60 public void removeNotify() {
61 super.removeNotify();
62 unregisterListeners();
63 }
64
65 @Override
66 public void addNotify() {
67 super.addNotify();
68 registerListeners();
69 }
70
71 private synchronized void registerListeners() {
72 if (!isRegistered) {
73 resolver.addPropertyChangeListener(applyResolutionAction);
74 resolver.registerListeners();
75 isRegistered = true;
76 }
77 }
78
79 private synchronized void unregisterListeners() {
80 // See #13479 - See https://bugs.openjdk.java.net/browse/JDK-4387314
81 // Owner window keep a list of owned windows, and does not remove the references when the child is disposed.
82 // There's no easy way to remove ourselves from this list, so we must keep track of register state
83 if (isRegistered) {
84 resolver.removePropertyChangeListener(applyResolutionAction);
85 resolver.unregisterListeners();
86 isRegistered = false;
87 }
88 }
89
90 /**
91 * builds the GUI
92 */
93 protected void build() {
94 JPanel p = new JPanel(new BorderLayout());
95
96 p.add(titleLabel, BorderLayout.NORTH);
97
98 updateTitle();
99
100 resolver.setName("panel.conflictresolver");
101 p.add(resolver, BorderLayout.CENTER);
102
103 resolver.addPropertyChangeListener(this);
104 HelpUtil.setHelpContext(this.getRootPane(), ht("Dialog/Conflict"));
105
106 setContent(p, false);
107 }
108
109 @Override
110 protected Action createButtonAction(int i) {
111 switch (i) {
112 case 0: return applyResolutionAction;
113 case 1: return new CancelAction();
114 case 2: return new HelpAction();
115 default: return super.createButtonAction(i);
116 }
117 }
118
119 /**
120 * Replies the conflict resolver component.
121 * @return the conflict resolver component
122 */
123 public ConflictResolver getConflictResolver() {
124 return resolver;
125 }
126
127 /**
128 * Action for canceling conflict resolution
129 */
130 class CancelAction extends AbstractAction {
131 CancelAction() {
132 putValue(Action.SHORT_DESCRIPTION, tr("Cancel conflict resolution and close the dialog"));
133 putValue(Action.NAME, tr("Cancel"));
134 new ImageProvider("cancel").getResource().attachImageIcon(this);
135 setEnabled(true);
136 }
137
138 @Override
139 public void actionPerformed(ActionEvent evt) {
140 buttonAction(2, evt);
141 }
142 }
143
144 /**
145 * Action for canceling conflict resolution
146 */
147 static class HelpAction extends AbstractAction {
148 HelpAction() {
149 putValue(Action.SHORT_DESCRIPTION, tr("Show help information"));
150 putValue(Action.NAME, tr("Help"));
151 new ImageProvider("help").getResource().attachImageIcon(this);
152 setEnabled(true);
153 }
154
155 @Override
156 public void actionPerformed(ActionEvent evt) {
157 HelpBrowser.setUrlForHelpTopic(ht("/Dialog/Conflict"));
158 }
159 }
160
161 /**
162 * Action for applying resolved differences in a conflict
163 *
164 */
165 class ApplyResolutionAction extends AbstractAction implements PropertyChangeListener {
166 ApplyResolutionAction() {
167 putValue(Action.SHORT_DESCRIPTION, tr("Apply resolved conflicts and close the dialog"));
168 putValue(Action.NAME, tr("Apply Resolution"));
169 new ImageProvider("dialogs", "conflict").getResource().attachImageIcon(this);
170 updateEnabledState();
171 }
172
173 protected void updateEnabledState() {
174 setEnabled(resolver.isResolvedCompletely());
175 }
176
177 @Override
178 public void actionPerformed(ActionEvent evt) {
179 if (!resolver.isResolvedCompletely()) {
180 Object[] options = {
181 tr("Close anyway"),
182 tr("Continue resolving")};
183 int ret = JOptionPane.showOptionDialog(MainApplication.getMainFrame(),
184 tr("<html>You did not finish to merge the differences in this conflict.<br>"
185 + "Conflict resolutions will not be applied unless all differences<br>"
186 + "are resolved.<br>"
187 + "Click <strong>{0}</strong> to close anyway.<strong> Already<br>"
188 + "resolved differences will not be applied.</strong><br>"
189 + "Click <strong>{1}</strong> to return to resolving conflicts.</html>",
190 options[0].toString(), options[1].toString()
191 ),
192 tr("Conflict not resolved completely"),
193 JOptionPane.YES_NO_OPTION,
194 JOptionPane.WARNING_MESSAGE,
195 null,
196 options,
197 options[1]
198 );
199 if (ret == JOptionPane.YES_OPTION) {
200 buttonAction(1, evt);
201 } else {
202 return;
203 }
204 }
205 UndoRedoHandler.getInstance().add(resolver.buildResolveCommand());
206 buttonAction(1, evt);
207 }
208
209 @Override
210 public void propertyChange(PropertyChangeEvent evt) {
211 if (evt.getPropertyName().equals(ConflictResolver.RESOLVED_COMPLETELY_PROP)) {
212 updateEnabledState();
213 }
214 }
215 }
216
217 protected void updateTitle() {
218 updateTitle(null);
219 }
220
221 protected void updateTitle(OsmPrimitive my) {
222 if (my == null) {
223 setTitle(tr("Resolve conflicts"));
224 } else {
225 setTitle(tr("Resolve conflicts for ''{0}''", my.getDisplayName(DefaultNameFormatter.getInstance())));
226 }
227 }
228
229 @Override
230 public void setTitle(String title) {
231 super.setTitle(title);
232 if (titleLabel != null) {
233 titleLabel.setText(title);
234 }
235 }
236
237 @Override
238 public void propertyChange(PropertyChangeEvent evt) {
239 if (evt.getPropertyName().equals(ConflictResolver.MY_PRIMITIVE_PROP)) {
240 updateTitle((OsmPrimitive) evt.getNewValue());
241 }
242 }
243}
Note: See TracBrowser for help on using the repository browser.