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

Last change on this file since 17318 was 14153, checked in by Don-vip, 6 years ago

see #15229 - deprecate Main.parent and Main itself

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