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

Last change on this file since 5297 was 5297, checked in by Don-vip, 12 years ago

fix #4493, fix #7750: conflict dialog, nodes and members tab: allow selection via double-click, allow zoom via contexual menu, plus various fix in EDT violations

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