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

Last change on this file since 10491 was 10454, checked in by Don-vip, 8 years ago

fix #12999 - Exception after resolving conflicts (patch by michael2402, modified) - gsoc-core

  • Property svn:eol-style set to native
File size: 8.8 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.Dimension;
10import java.awt.FlowLayout;
11import java.awt.event.ActionEvent;
12import java.beans.PropertyChangeEvent;
13import java.beans.PropertyChangeListener;
14
15import javax.swing.AbstractAction;
16import javax.swing.Action;
17import javax.swing.BorderFactory;
18import javax.swing.JButton;
19import javax.swing.JDialog;
20import javax.swing.JLabel;
21import javax.swing.JOptionPane;
22import javax.swing.JPanel;
23import javax.swing.WindowConstants;
24
25import org.openstreetmap.josm.Main;
26import org.openstreetmap.josm.command.Command;
27import org.openstreetmap.josm.data.osm.OsmPrimitive;
28import org.openstreetmap.josm.gui.DefaultNameFormatter;
29import org.openstreetmap.josm.gui.conflict.pair.ConflictResolver;
30import org.openstreetmap.josm.gui.help.HelpBrowser;
31import org.openstreetmap.josm.gui.help.HelpUtil;
32import org.openstreetmap.josm.gui.util.GuiHelper;
33import org.openstreetmap.josm.tools.ImageProvider;
34import org.openstreetmap.josm.tools.WindowGeometry;
35
36/**
37 * This is an extended dialog for resolving conflict between {@link OsmPrimitive}s.
38 * @since 1622
39 */
40public class ConflictResolutionDialog extends JDialog implements PropertyChangeListener {
41 /** the conflict resolver component */
42 private ConflictResolver resolver;
43 private JLabel titleLabel;
44
45 private ApplyResolutionAction applyResolutionAction;
46
47 @Override
48 public void removeNotify() {
49 super.removeNotify();
50 unregisterListeners();
51 }
52
53 @Override
54 public void addNotify() {
55 super.addNotify();
56 registerListeners();
57 }
58
59 @Override
60 public void setVisible(boolean isVisible) {
61 String geom = getClass().getName() + ".geometry";
62 if (isVisible) {
63 toFront();
64 new WindowGeometry(geom, WindowGeometry.centerInWindow(Main.parent,
65 new Dimension(600, 400))).applySafe(this);
66 } else {
67 if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
68 new WindowGeometry(this).remember(geom);
69 }
70 }
71 super.setVisible(isVisible);
72 }
73
74 private void closeDialog() {
75 setVisible(false);
76 dispose();
77 }
78
79 /**
80 * builds the sub panel with the control buttons
81 *
82 * @return the panel
83 */
84 protected JPanel buildButtonRow() {
85 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
86
87 applyResolutionAction = new ApplyResolutionAction();
88 JButton btn = new JButton(applyResolutionAction);
89 btn.setName("button.apply");
90 pnl.add(btn);
91
92 btn = new JButton(new CancelAction());
93 btn.setName("button.cancel");
94 pnl.add(btn);
95
96 btn = new JButton(new HelpAction());
97 btn.setName("button.help");
98 pnl.add(btn);
99
100 pnl.setBorder(BorderFactory.createLoweredBevelBorder());
101 return pnl;
102 }
103
104 private void registerListeners() {
105 resolver.addPropertyChangeListener(applyResolutionAction);
106 resolver.registerListeners();
107 }
108
109 private void unregisterListeners() {
110 resolver.removePropertyChangeListener(applyResolutionAction);
111 resolver.unregisterListeners();
112 }
113
114 /**
115 * builds the GUI
116 */
117 protected void build() {
118 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
119 getContentPane().setLayout(new BorderLayout());
120
121 titleLabel = new JLabel();
122 titleLabel.setHorizontalAlignment(JLabel.CENTER);
123 getContentPane().add(titleLabel, BorderLayout.NORTH);
124
125 updateTitle();
126
127 resolver = new ConflictResolver();
128 resolver.setName("panel.conflictresolver");
129 getContentPane().add(resolver, BorderLayout.CENTER);
130 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
131
132 resolver.addPropertyChangeListener(this);
133 HelpUtil.setHelpContext(this.getRootPane(), ht("Dialog/Conflict"));
134 }
135
136 /**
137 * Constructs a new {@code ConflictResolutionDialog}.
138 * @param parent parent component
139 */
140 public ConflictResolutionDialog(Component parent) {
141 super(GuiHelper.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
142 build();
143 pack();
144 if (getInsets().top > 0) {
145 titleLabel.setVisible(false);
146 }
147 }
148
149 /**
150 * Replies the conflict resolver component.
151 * @return the conflict resolver component
152 */
153 public ConflictResolver getConflictResolver() {
154 return resolver;
155 }
156
157 /**
158 * Action for canceling conflict resolution
159 */
160 class CancelAction extends AbstractAction {
161 CancelAction() {
162 putValue(Action.SHORT_DESCRIPTION, tr("Cancel conflict resolution and close the dialog"));
163 putValue(Action.NAME, tr("Cancel"));
164 new ImageProvider("cancel").getResource().attachImageIcon(this);
165 setEnabled(true);
166 }
167
168 @Override
169 public void actionPerformed(ActionEvent arg0) {
170 closeDialog();
171 }
172 }
173
174 /**
175 * Action for canceling conflict resolution
176 */
177 static class HelpAction extends AbstractAction {
178 HelpAction() {
179 putValue(Action.SHORT_DESCRIPTION, tr("Show help information"));
180 putValue(Action.NAME, tr("Help"));
181 new ImageProvider("help").getResource().attachImageIcon(this);
182 setEnabled(true);
183 }
184
185 @Override
186 public void actionPerformed(ActionEvent arg0) {
187 HelpBrowser.setUrlForHelpTopic(ht("/Dialog/Conflict"));
188 }
189 }
190
191 /**
192 * Action for applying resolved differences in a conflict
193 *
194 */
195 class ApplyResolutionAction extends AbstractAction implements PropertyChangeListener {
196 ApplyResolutionAction() {
197 putValue(Action.SHORT_DESCRIPTION, tr("Apply resolved conflicts and close the dialog"));
198 putValue(Action.NAME, tr("Apply Resolution"));
199 new ImageProvider("dialogs", "conflict").getResource().attachImageIcon(this);
200 updateEnabledState();
201 }
202
203 protected void updateEnabledState() {
204 setEnabled(resolver.isResolvedCompletely());
205 }
206
207 @Override
208 public void actionPerformed(ActionEvent arg0) {
209 if (!resolver.isResolvedCompletely()) {
210 Object[] options = {
211 tr("Close anyway"),
212 tr("Continue resolving")};
213 int ret = JOptionPane.showOptionDialog(Main.parent,
214 tr("<html>You did not finish to merge the differences in this conflict.<br>"
215 + "Conflict resolutions will not be applied unless all differences<br>"
216 + "are resolved.<br>"
217 + "Click <strong>{0}</strong> to close anyway.<strong> Already<br>"
218 + "resolved differences will not be applied.</strong><br>"
219 + "Click <strong>{1}</strong> to return to resolving conflicts.</html>",
220 options[0].toString(), options[1].toString()
221 ),
222 tr("Conflict not resolved completely"),
223 JOptionPane.YES_NO_OPTION,
224 JOptionPane.WARNING_MESSAGE,
225 null,
226 options,
227 options[1]
228 );
229 switch(ret) {
230 case JOptionPane.YES_OPTION:
231 closeDialog();
232 break;
233 default:
234 return;
235 }
236 }
237 Command cmd = resolver.buildResolveCommand();
238 Main.main.undoRedo.add(cmd);
239 closeDialog();
240 }
241
242 @Override
243 public void propertyChange(PropertyChangeEvent evt) {
244 if (evt.getPropertyName().equals(ConflictResolver.RESOLVED_COMPLETELY_PROP)) {
245 updateEnabledState();
246 }
247 }
248 }
249
250 protected void updateTitle() {
251 updateTitle(null);
252 }
253
254 protected void updateTitle(OsmPrimitive my) {
255 if (my == null) {
256 setTitle(tr("Resolve conflicts"));
257 } else {
258 setTitle(tr("Resolve conflicts for ''{0}''", my.getDisplayName(DefaultNameFormatter.getInstance())));
259 }
260 }
261
262 @Override
263 public void setTitle(String title) {
264 super.setTitle(title);
265 if (titleLabel != null) {
266 titleLabel.setText(title);
267 }
268 }
269
270 @Override
271 public void propertyChange(PropertyChangeEvent evt) {
272 if (evt.getPropertyName().equals(ConflictResolver.MY_PRIMITIVE_PROP)) {
273 updateTitle((OsmPrimitive) evt.getNewValue());
274 }
275 }
276}
Note: See TracBrowser for help on using the repository browser.