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

Last change on this file since 2308 was 2308, checked in by Gubaer, 14 years ago

fixed #3762: Deleted relation still referenced when deleting former member
Clean up of Delete command. New: only one confirmation dialog for all parent relations of deleted objects, see help.
Improved infrastructure for context-sensitive help, improved internal help browser.

File size: 9.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.FlowLayout;
10import java.awt.Point;
11import java.awt.event.ActionEvent;
12import java.beans.PropertyChangeEvent;
13import java.beans.PropertyChangeListener;
14import java.util.logging.Logger;
15
16import javax.swing.AbstractAction;
17import javax.swing.Action;
18import javax.swing.BorderFactory;
19import javax.swing.JButton;
20import javax.swing.JDialog;
21import javax.swing.JOptionPane;
22import javax.swing.JPanel;
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.conflict.pair.properties.OperationCancelledException;
30import org.openstreetmap.josm.gui.help.HelpBrowser;
31import org.openstreetmap.josm.gui.help.HelpBrowserProxy;
32import org.openstreetmap.josm.gui.help.HelpUtil;
33import org.openstreetmap.josm.tools.ImageProvider;
34
35/**
36 * This is an extended dialog for resolving conflict between {@see OsmPrimitive}s.
37 *
38 */
39public class ConflictResolutionDialog extends JDialog implements PropertyChangeListener {
40 private static final Logger logger = Logger.getLogger(ConflictResolutionDialog.class.getName());
41 public final static Dimension DEFAULT_SIZE = new Dimension(600,400);
42
43 /** the conflict resolver component */
44 private ConflictResolver resolver;
45
46 /**
47 * restore position and size on screen from preference settings
48 *
49 */
50 protected void restorePositionAndDimension() {
51 Point p = new Point();
52 Dimension d = new Dimension();
53 try {
54 p.x = Integer.parseInt(Main.pref.get("conflictresolutiondialog.x", "0"));
55 p.x = Math.max(0,p.x);
56 } catch(Exception e) {
57 logger.warning("unexpected value for preference conflictresolutiondialog.x, assuming 0");
58 p.x = 0;
59 }
60 try {
61 p.y = Integer.parseInt(Main.pref.get("conflictresolutiondialog.y", "0"));
62 p.y = Math.max(0,p.y);
63 } catch(Exception e) {
64 logger.warning("unexpected value for preference conflictresolutiondialog.x, assuming 0");
65 p.y = 0;
66 }
67 try {
68 d.width = Integer.parseInt(Main.pref.get("conflictresolutiondialog.width", Integer.toString(DEFAULT_SIZE.width)));
69 d.width = Math.max(0,d.width);
70 } catch(Exception e) {
71 logger.warning("unexpected value for preference conflictresolutiondialog.width, assuming " + DEFAULT_SIZE.width);
72 p.y = 0;
73 }
74 try {
75 d.height = Integer.parseInt(Main.pref.get("conflictresolutiondialog.height", Integer.toString(DEFAULT_SIZE.height)));
76 d.height = Math.max(0,d.height);
77 } catch(Exception e) {
78 logger.warning("unexpected value for preference conflictresolutiondialog.height, assuming " + + DEFAULT_SIZE.height);
79 p.y = 0;
80 }
81
82 setLocation(p);
83 setSize(d);
84 }
85
86 /**
87 * remember position and size on screen in the preferences
88 *
89 */
90 protected void rememberPositionAndDimension() {
91 Point p = getLocation();
92 Main.pref.put("conflictresolutiondialog.x", Integer.toString(p.x));
93 Main.pref.put("conflictresolutiondialog.y", Integer.toString(p.y));
94
95 Dimension d = getSize();
96 Main.pref.put("conflictresolutiondialog.width", Integer.toString(d.width));
97 Main.pref.put("conflictresolutiondialog.height", Integer.toString(d.height));
98 }
99
100
101 @Override
102 public void setVisible(boolean isVisible) {
103 if (isVisible){
104 restorePositionAndDimension();
105 toFront();
106 } else {
107 rememberPositionAndDimension();
108 }
109 super.setVisible(isVisible);
110 }
111
112 /**
113 * builds the sub panel with the control buttons
114 *
115 * @return the panel
116 */
117 protected JPanel buildButtonRow() {
118 JPanel pnl = new JPanel();
119 pnl.setLayout(new FlowLayout(FlowLayout.CENTER));
120
121 ApplyResolutionAction applyResolutionAction = new ApplyResolutionAction();
122 resolver.addPropertyChangeListener(applyResolutionAction);
123 JButton btn = new JButton(applyResolutionAction);
124 btn.setName("button.apply");
125 pnl.add(btn);
126
127 btn = new JButton(new CancelAction());
128 btn.setName("button.cancel");
129 pnl.add(btn);
130
131 btn = new JButton(new HelpAction());
132 btn.setName("button.help");
133 pnl.add(btn);
134
135 pnl.setBorder(BorderFactory.createLoweredBevelBorder());
136 return pnl;
137 }
138
139 /**
140 * builds the GUI
141 */
142 protected void build() {
143 updateTitle();
144 getContentPane().setLayout(new BorderLayout());
145
146 resolver = new ConflictResolver();
147 resolver.setName("panel.conflictresolver");
148 getContentPane().add(resolver, BorderLayout.CENTER);
149 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
150
151 resolver.addPropertyChangeListener(this);
152 HelpUtil.setHelpContext(this.getRootPane(), "Dialog/ConflictDialog");
153 }
154
155
156 public ConflictResolutionDialog(Component parent) {
157 super(JOptionPane.getFrameForComponent(parent), true /* modal */);
158 build();
159 }
160
161 public ConflictResolver getConflictResolver() {
162 return resolver;
163 }
164
165 /**
166 * Action for canceling conflict resolution
167 */
168 class CancelAction extends AbstractAction {
169 public CancelAction() {
170 putValue(Action.SHORT_DESCRIPTION, tr("Cancel conflict resolution and close the dialog"));
171 putValue(Action.NAME, tr("Cancel"));
172 putValue(Action.SMALL_ICON, ImageProvider.get("", "cancel"));
173 setEnabled(true);
174 }
175
176
177 public void actionPerformed(ActionEvent arg0) {
178 setVisible(false);
179 }
180 }
181
182 /**
183 * Action for canceling conflict resolution
184 */
185 class HelpAction extends AbstractAction {
186 public HelpAction() {
187 putValue(Action.SHORT_DESCRIPTION, tr("Show help information"));
188 putValue(Action.NAME, tr("Help"));
189 putValue(Action.SMALL_ICON, ImageProvider.get("help"));
190 setEnabled(true);
191 }
192
193 public void actionPerformed(ActionEvent arg0) {
194 HelpBrowserProxy.getInstance().setUrlForHelpTopic("/Dialog/ConflictDialog");
195 }
196 }
197
198 /**
199 * Action for applying resolved differences in a conflict
200 *
201 */
202 class ApplyResolutionAction extends AbstractAction implements PropertyChangeListener {
203 public ApplyResolutionAction() {
204 putValue(Action.SHORT_DESCRIPTION, tr("Apply resolved conflicts and close the dialog"));
205 putValue(Action.NAME, tr("Apply Resolution"));
206 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs", "conflict"));
207 updateEnabledState();
208 }
209
210 protected void updateEnabledState() {
211 setEnabled(resolver.isResolvedCompletely());
212 }
213
214 public void actionPerformed(ActionEvent arg0) {
215 if (! resolver.isResolvedCompletely()) {
216 Object[] options = {
217 tr("Close anyway"),
218 tr("Continue resolving")};
219 int ret = JOptionPane.showOptionDialog(Main.parent,
220 tr("<html>You didn''t finish to merge the differences in this conflict.<br>"
221 + "Conflict resolutions won't be applied unless all differences<br>"
222 + "are resolved."
223 + "Click <strong>{0}</strong> to close anyway.<strong>Already<br>"
224 + "resolved differences won't be applied.</strong><br>"
225 + "Click <strong>{1}</strong> to return to resolving conflicts.</html>"
226 , options[0].toString(), options[1].toString()
227 ),
228 tr("Conflict not resolved completely"),
229 JOptionPane.YES_NO_OPTION,
230 JOptionPane.WARNING_MESSAGE,
231 null,
232 options,
233 options[1]
234 );
235 switch(ret) {
236 case JOptionPane.YES_OPTION:
237 setVisible(false);
238 break;
239 default:
240 return;
241 }
242 }
243 try {
244 Command cmd = resolver.buildResolveCommand();
245 Main.main.undoRedo.add(cmd);
246 setVisible(false);
247 } catch(OperationCancelledException e) {
248 // do nothing. Exception already reported
249 }
250 }
251
252 public void propertyChange(PropertyChangeEvent evt) {
253 if (evt.getPropertyName().equals(ConflictResolver.RESOLVED_COMPLETELY_PROP)) {
254 updateEnabledState();
255 }
256 }
257 }
258
259 protected void updateTitle() {
260 updateTitle(null);
261 }
262
263 protected void updateTitle(OsmPrimitive my) {
264 if (my == null) {
265 setTitle(tr("Resolve conflicts"));
266 } else {
267 setTitle(tr("Resolve conflicts for ''{0}''", my.getDisplayName(DefaultNameFormatter.getInstance())));
268 }
269 }
270
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.