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

Last change on this file was 19050, checked in by taylor.smock, 38 hours ago

Revert most var changes from r19048, fix most new compile warnings and checkstyle issues

Also, document why various ErrorProne checks were originally disabled and fix
generic SonarLint issues.

  • Property svn:eol-style set to native
File size: 8.2 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 switch (ret) {
200 case JOptionPane.YES_OPTION:
201 buttonAction(1, evt);
202 break;
203 default:
204 return;
205 }
206 }
207 UndoRedoHandler.getInstance().add(resolver.buildResolveCommand());
208 buttonAction(1, evt);
209 }
210
211 @Override
212 public void propertyChange(PropertyChangeEvent evt) {
213 if (evt.getPropertyName().equals(ConflictResolver.RESOLVED_COMPLETELY_PROP)) {
214 updateEnabledState();
215 }
216 }
217 }
218
219 protected void updateTitle() {
220 updateTitle(null);
221 }
222
223 protected void updateTitle(OsmPrimitive my) {
224 if (my == null) {
225 setTitle(tr("Resolve conflicts"));
226 } else {
227 setTitle(tr("Resolve conflicts for ''{0}''", my.getDisplayName(DefaultNameFormatter.getInstance())));
228 }
229 }
230
231 @Override
232 public void setTitle(String title) {
233 super.setTitle(title);
234 if (titleLabel != null) {
235 titleLabel.setText(title);
236 }
237 }
238
239 @Override
240 public void propertyChange(PropertyChangeEvent evt) {
241 if (evt.getPropertyName().equals(ConflictResolver.MY_PRIMITIVE_PROP)) {
242 updateTitle((OsmPrimitive) evt.getNewValue());
243 }
244 }
245}
Note: See TracBrowser for help on using the repository browser.