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

Last change on this file was 19050, checked in by taylor.smock, 3 days 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.