source: josm/trunk/src/org/openstreetmap/josm/gui/conflict/pair/properties/PropertiesMerger.java@ 5299

Last change on this file since 5299 was 5266, checked in by bastiK, 12 years ago

fixed majority of javadoc warnings by replacing "{@see" by "{@link"

  • Property svn:eol-style set to native
File size: 18.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.conflict.pair.properties;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagConstraints;
7import java.awt.GridBagLayout;
8import java.awt.Insets;
9import java.awt.event.ActionEvent;
10import java.text.DecimalFormat;
11import java.util.List;
12import java.util.Observable;
13import java.util.Observer;
14
15import javax.swing.AbstractAction;
16import javax.swing.Action;
17import javax.swing.BorderFactory;
18import javax.swing.JButton;
19import javax.swing.JLabel;
20import javax.swing.JPanel;
21
22import org.openstreetmap.josm.data.conflict.Conflict;
23import org.openstreetmap.josm.data.coor.LatLon;
24import org.openstreetmap.josm.data.osm.OsmPrimitive;
25import org.openstreetmap.josm.gui.DefaultNameFormatter;
26import org.openstreetmap.josm.gui.conflict.ConflictColors;
27import org.openstreetmap.josm.gui.conflict.pair.IConflictResolver;
28import org.openstreetmap.josm.gui.conflict.pair.MergeDecisionType;
29import org.openstreetmap.josm.tools.ImageProvider;
30
31/**
32 * This class represents a UI component for resolving conflicts in some properties
33 * of {@link OsmPrimitive}.
34 *
35 */
36public class PropertiesMerger extends JPanel implements Observer, IConflictResolver {
37 private static DecimalFormat COORD_FORMATTER = new DecimalFormat("###0.0000000");
38
39 private JLabel lblMyVersion;
40 private JLabel lblMergedVersion;
41 private JLabel lblTheirVersion;
42
43 private JLabel lblMyCoordinates;
44 private JLabel lblMergedCoordinates;
45 private JLabel lblTheirCoordinates;
46
47 private JLabel lblMyDeletedState;
48 private JLabel lblMergedDeletedState;
49 private JLabel lblTheirDeletedState;
50
51 private JLabel lblMyReferrers;
52 private JLabel lblTheirReferrers;
53
54 private final PropertiesMergeModel model;
55
56 protected JLabel buildValueLabel(String name) {
57 JLabel lbl = new JLabel();
58 lbl.setName(name);
59 lbl.setHorizontalAlignment(JLabel.CENTER);
60 lbl.setOpaque(true);
61 lbl.setBorder(BorderFactory.createLoweredBevelBorder());
62 return lbl;
63 }
64
65 protected void buildHeaderRow() {
66 GridBagConstraints gc = new GridBagConstraints();
67
68 gc.gridx = 1;
69 gc.gridy = 0;
70 gc.gridwidth = 1;
71 gc.gridheight = 1;
72 gc.fill = GridBagConstraints.NONE;
73 gc.anchor = GridBagConstraints.CENTER;
74 gc.weightx = 0.0;
75 gc.weighty = 0.0;
76 gc.insets = new Insets(10,0,10,0);
77 lblMyVersion = new JLabel(tr("My version"));
78 lblMyVersion.setToolTipText(tr("Properties in my dataset, i.e. the local dataset"));
79 add(lblMyVersion, gc);
80
81 gc.gridx = 3;
82 gc.gridy = 0;
83 lblMergedVersion = new JLabel(tr("Merged version"));
84 lblMergedVersion.setToolTipText(tr("Properties in the merged element. They will replace properties in my elements when merge decisions are applied."));
85 add(lblMergedVersion, gc);
86
87 gc.gridx = 5;
88 gc.gridy = 0;
89 lblTheirVersion = new JLabel(tr("Their version"));
90 lblTheirVersion.setToolTipText(tr("Properties in their dataset, i.e. the server dataset"));
91 add(lblTheirVersion, gc);
92 }
93
94 protected void buildCoordinateConflictRows() {
95 GridBagConstraints gc = new GridBagConstraints();
96
97 gc.gridx = 0;
98 gc.gridy = 1;
99 gc.gridwidth = 1;
100 gc.gridheight = 1;
101 gc.fill = GridBagConstraints.HORIZONTAL;
102 gc.anchor = GridBagConstraints.LINE_START;
103 gc.weightx = 0.0;
104 gc.weighty = 0.0;
105 gc.insets = new Insets(0,5,0,5);
106 add(new JLabel(tr("Coordinates:")), gc);
107
108 gc.gridx = 1;
109 gc.gridy = 1;
110 gc.fill = GridBagConstraints.BOTH;
111 gc.anchor = GridBagConstraints.CENTER;
112 gc.weightx = 0.33;
113 gc.weighty = 0.0;
114 add(lblMyCoordinates = buildValueLabel("label.mycoordinates"), gc);
115
116 gc.gridx = 2;
117 gc.gridy = 1;
118 gc.fill = GridBagConstraints.NONE;
119 gc.anchor = GridBagConstraints.CENTER;
120 gc.weightx = 0.0;
121 gc.weighty = 0.0;
122 KeepMyCoordinatesAction actKeepMyCoordinates = new KeepMyCoordinatesAction();
123 model.addObserver(actKeepMyCoordinates);
124 JButton btnKeepMyCoordinates = new JButton(actKeepMyCoordinates);
125 btnKeepMyCoordinates.setName("button.keepmycoordinates");
126 add(btnKeepMyCoordinates, gc);
127
128 gc.gridx = 3;
129 gc.gridy = 1;
130 gc.fill = GridBagConstraints.BOTH;
131 gc.anchor = GridBagConstraints.CENTER;
132 gc.weightx = 0.33;
133 gc.weighty = 0.0;
134 add(lblMergedCoordinates = buildValueLabel("label.mergedcoordinates"), gc);
135
136 gc.gridx = 4;
137 gc.gridy = 1;
138 gc.fill = GridBagConstraints.NONE;
139 gc.anchor = GridBagConstraints.CENTER;
140 gc.weightx = 0.0;
141 gc.weighty = 0.0;
142 KeepTheirCoordinatesAction actKeepTheirCoordinates = new KeepTheirCoordinatesAction();
143 model.addObserver(actKeepTheirCoordinates);
144 JButton btnKeepTheirCoordinates = new JButton(actKeepTheirCoordinates);
145 add(btnKeepTheirCoordinates, gc);
146
147 gc.gridx = 5;
148 gc.gridy = 1;
149 gc.fill = GridBagConstraints.BOTH;
150 gc.anchor = GridBagConstraints.CENTER;
151 gc.weightx = 0.33;
152 gc.weighty = 0.0;
153 add(lblTheirCoordinates = buildValueLabel("label.theircoordinates"), gc);
154
155 // ---------------------------------------------------
156 gc.gridx = 3;
157 gc.gridy = 2;
158 gc.fill = GridBagConstraints.NONE;
159 gc.anchor = GridBagConstraints.CENTER;
160 gc.weightx = 0.0;
161 gc.weighty = 0.0;
162 UndecideCoordinateConflictAction actUndecideCoordinates = new UndecideCoordinateConflictAction();
163 model.addObserver(actUndecideCoordinates);
164 JButton btnUndecideCoordinates = new JButton(actUndecideCoordinates);
165 add(btnUndecideCoordinates, gc);
166 }
167
168 protected void buildDeletedStateConflictRows() {
169 GridBagConstraints gc = new GridBagConstraints();
170
171 gc.gridx = 0;
172 gc.gridy = 3;
173 gc.gridwidth = 1;
174 gc.gridheight = 1;
175 gc.fill = GridBagConstraints.BOTH;
176 gc.anchor = GridBagConstraints.LINE_START;
177 gc.weightx = 0.0;
178 gc.weighty = 0.0;
179 gc.insets = new Insets(0,5,0,5);
180 add(new JLabel(tr("Deleted State:")), gc);
181
182 gc.gridx = 1;
183 gc.gridy = 3;
184 gc.fill = GridBagConstraints.BOTH;
185 gc.anchor = GridBagConstraints.CENTER;
186 gc.weightx = 0.33;
187 gc.weighty = 0.0;
188 add(lblMyDeletedState = buildValueLabel("label.mydeletedstate"), gc);
189
190 gc.gridx = 2;
191 gc.gridy = 3;
192 gc.fill = GridBagConstraints.NONE;
193 gc.anchor = GridBagConstraints.CENTER;
194 gc.weightx = 0.0;
195 gc.weighty = 0.0;
196 KeepMyDeletedStateAction actKeepMyDeletedState = new KeepMyDeletedStateAction();
197 model.addObserver(actKeepMyDeletedState);
198 JButton btnKeepMyDeletedState = new JButton(actKeepMyDeletedState);
199 btnKeepMyDeletedState.setName("button.keepmydeletedstate");
200 add(btnKeepMyDeletedState, gc);
201
202 gc.gridx = 3;
203 gc.gridy = 3;
204 gc.fill = GridBagConstraints.BOTH;
205 gc.anchor = GridBagConstraints.CENTER;
206 gc.weightx = 0.33;
207 gc.weighty = 0.0;
208 add(lblMergedDeletedState = buildValueLabel("label.mergeddeletedstate"), gc);
209
210 gc.gridx = 4;
211 gc.gridy = 3;
212 gc.fill = GridBagConstraints.NONE;
213 gc.anchor = GridBagConstraints.CENTER;
214 gc.weightx = 0.0;
215 gc.weighty = 0.0;
216 KeepTheirDeletedStateAction actKeepTheirDeletedState = new KeepTheirDeletedStateAction();
217 model.addObserver(actKeepTheirDeletedState);
218 JButton btnKeepTheirDeletedState = new JButton(actKeepTheirDeletedState);
219 btnKeepTheirDeletedState.setName("button.keeptheirdeletedstate");
220 add(btnKeepTheirDeletedState, gc);
221
222 gc.gridx = 5;
223 gc.gridy = 3;
224 gc.fill = GridBagConstraints.BOTH;
225 gc.anchor = GridBagConstraints.CENTER;
226 gc.weightx = 0.33;
227 gc.weighty = 0.0;
228 add(lblTheirDeletedState = buildValueLabel("label.theirdeletedstate"), gc);
229
230 // ---------------------------------------------------
231 gc.gridx = 3;
232 gc.gridy = 4;
233 gc.fill = GridBagConstraints.NONE;
234 gc.anchor = GridBagConstraints.CENTER;
235 gc.weightx = 0.0;
236 gc.weighty = 0.0;
237 UndecideDeletedStateConflictAction actUndecideDeletedState = new UndecideDeletedStateConflictAction();
238 model.addObserver(actUndecideDeletedState);
239 JButton btnUndecideDeletedState = new JButton(actUndecideDeletedState);
240 btnUndecideDeletedState.setName("button.undecidedeletedstate");
241 add(btnUndecideDeletedState, gc);
242 }
243
244 protected void buildReferrersRow() {
245 GridBagConstraints gc = new GridBagConstraints();
246
247 gc.gridx = 0;
248 gc.gridy = 7;
249 gc.gridwidth = 1;
250 gc.gridheight = 1;
251 gc.fill = GridBagConstraints.BOTH;
252 gc.anchor = GridBagConstraints.LINE_START;
253 gc.weightx = 0.0;
254 gc.weighty = 0.0;
255 gc.insets = new Insets(0,5,0,5);
256 add(new JLabel(tr("Referenced by:")), gc);
257
258 gc.gridx = 1;
259 gc.gridy = 7;
260 gc.fill = GridBagConstraints.BOTH;
261 gc.anchor = GridBagConstraints.CENTER;
262 gc.weightx = 0.33;
263 gc.weighty = 0.0;
264 add(lblMyReferrers = buildValueLabel("label.myreferrers"), gc);
265
266 gc.gridx = 5;
267 gc.gridy = 7;
268 gc.fill = GridBagConstraints.BOTH;
269 gc.anchor = GridBagConstraints.CENTER;
270 gc.weightx = 0.33;
271 gc.weighty = 0.0;
272 add(lblTheirReferrers = buildValueLabel("label.theirreferrers"), gc);
273 }
274
275 protected void build() {
276 setLayout(new GridBagLayout());
277 buildHeaderRow();
278 buildCoordinateConflictRows();
279 buildDeletedStateConflictRows();
280 buildReferrersRow();
281 }
282
283 public PropertiesMerger() {
284 model = new PropertiesMergeModel();
285 model.addObserver(this);
286 build();
287 }
288
289 public String coordToString(LatLon coord) {
290 if (coord == null)
291 return tr("(none)");
292 StringBuilder sb = new StringBuilder();
293 sb.append("(")
294 .append(COORD_FORMATTER.format(coord.lat()))
295 .append(",")
296 .append(COORD_FORMATTER.format(coord.lon()))
297 .append(")");
298 return sb.toString();
299 }
300
301 public String deletedStateToString(Boolean deleted) {
302 if (deleted == null)
303 return tr("(none)");
304 if (deleted)
305 return tr("deleted");
306 else
307 return tr("not deleted");
308 }
309
310 public String referrersToString(List<OsmPrimitive> referrers) {
311 if (referrers.isEmpty())
312 return tr("(none)");
313 String str = "<html>";
314 for (OsmPrimitive r: referrers) {
315 str = str + r.getDisplayName(DefaultNameFormatter.getInstance()) + "<br>";
316 }
317 str = str + "</html>";
318 return str;
319 }
320
321 protected void updateCoordinates() {
322 lblMyCoordinates.setText(coordToString(model.getMyCoords()));
323 lblMergedCoordinates.setText(coordToString(model.getMergedCoords()));
324 lblTheirCoordinates.setText(coordToString(model.getTheirCoords()));
325 if (! model.hasCoordConflict()) {
326 lblMyCoordinates.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
327 lblMergedCoordinates.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
328 lblTheirCoordinates.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
329 } else {
330 if (!model.isDecidedCoord()) {
331 lblMyCoordinates.setBackground(ConflictColors.BGCOLOR_UNDECIDED.get());
332 lblMergedCoordinates.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
333 lblTheirCoordinates.setBackground(ConflictColors.BGCOLOR_UNDECIDED.get());
334 } else {
335 lblMyCoordinates.setBackground(
336 model.isCoordMergeDecision(MergeDecisionType.KEEP_MINE)
337 ? ConflictColors.BGCOLOR_DECIDED.get() : ConflictColors.BGCOLOR_NO_CONFLICT.get()
338 );
339 lblMergedCoordinates.setBackground(ConflictColors.BGCOLOR_DECIDED.get());
340 lblTheirCoordinates.setBackground(
341 model.isCoordMergeDecision(MergeDecisionType.KEEP_THEIR)
342 ? ConflictColors.BGCOLOR_DECIDED.get() : ConflictColors.BGCOLOR_NO_CONFLICT.get()
343 );
344 }
345 }
346 }
347
348 protected void updateDeletedState() {
349 lblMyDeletedState.setText(deletedStateToString(model.getMyDeletedState()));
350 lblMergedDeletedState.setText(deletedStateToString(model.getMergedDeletedState()));
351 lblTheirDeletedState.setText(deletedStateToString(model.getTheirDeletedState()));
352
353 if (! model.hasDeletedStateConflict()) {
354 lblMyDeletedState.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
355 lblMergedDeletedState.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
356 lblTheirDeletedState.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
357 } else {
358 if (!model.isDecidedDeletedState()) {
359 lblMyDeletedState.setBackground(ConflictColors.BGCOLOR_UNDECIDED.get());
360 lblMergedDeletedState.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
361 lblTheirDeletedState.setBackground(ConflictColors.BGCOLOR_UNDECIDED.get());
362 } else {
363 lblMyDeletedState.setBackground(
364 model.isDeletedStateDecision(MergeDecisionType.KEEP_MINE)
365 ? ConflictColors.BGCOLOR_DECIDED.get() : ConflictColors.BGCOLOR_NO_CONFLICT.get()
366 );
367 lblMergedDeletedState.setBackground(ConflictColors.BGCOLOR_DECIDED.get());
368 lblTheirDeletedState.setBackground(
369 model.isDeletedStateDecision(MergeDecisionType.KEEP_THEIR)
370 ? ConflictColors.BGCOLOR_DECIDED.get() : ConflictColors.BGCOLOR_NO_CONFLICT.get()
371 );
372 }
373 }
374 }
375
376 protected void updateReferrers() {
377 lblMyReferrers.setText(referrersToString(model.getMyReferrers()));
378 lblMyReferrers.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
379 lblTheirReferrers.setText(referrersToString(model.getTheirReferrers()));
380 lblTheirReferrers.setBackground(ConflictColors.BGCOLOR_NO_CONFLICT.get());
381 }
382
383 public void update(Observable o, Object arg) {
384 updateCoordinates();
385 updateDeletedState();
386 updateReferrers();
387 }
388
389 public PropertiesMergeModel getModel() {
390 return model;
391 }
392
393 class KeepMyCoordinatesAction extends AbstractAction implements Observer {
394 public KeepMyCoordinatesAction() {
395 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeepmine"));
396 putValue(Action.SHORT_DESCRIPTION, tr("Keep my coordinates"));
397 }
398
399 public void actionPerformed(ActionEvent e) {
400 model.decideCoordsConflict(MergeDecisionType.KEEP_MINE);
401 }
402
403 public void update(Observable o, Object arg) {
404 setEnabled(model.hasCoordConflict() && ! model.isDecidedCoord());
405 }
406 }
407
408 class KeepTheirCoordinatesAction extends AbstractAction implements Observer {
409 public KeepTheirCoordinatesAction() {
410 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeeptheir"));
411 putValue(Action.SHORT_DESCRIPTION, tr("Keep their coordinates"));
412 }
413
414 public void actionPerformed(ActionEvent e) {
415 model.decideCoordsConflict(MergeDecisionType.KEEP_THEIR);
416 }
417
418 public void update(Observable o, Object arg) {
419 setEnabled(model.hasCoordConflict() && ! model.isDecidedCoord());
420 }
421 }
422
423 class UndecideCoordinateConflictAction extends AbstractAction implements Observer {
424 public UndecideCoordinateConflictAction() {
425 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagundecide"));
426 putValue(Action.SHORT_DESCRIPTION, tr("Undecide conflict between different coordinates"));
427 }
428
429 public void actionPerformed(ActionEvent e) {
430 model.decideCoordsConflict(MergeDecisionType.UNDECIDED);
431 }
432
433 public void update(Observable o, Object arg) {
434 setEnabled(model.hasCoordConflict() && model.isDecidedCoord());
435 }
436 }
437
438 class KeepMyDeletedStateAction extends AbstractAction implements Observer {
439 public KeepMyDeletedStateAction() {
440 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeepmine"));
441 putValue(Action.SHORT_DESCRIPTION, tr("Keep my deleted state"));
442 }
443
444 public void actionPerformed(ActionEvent e) {
445 model.decideDeletedStateConflict(MergeDecisionType.KEEP_MINE);
446 }
447
448 public void update(Observable o, Object arg) {
449 setEnabled(model.hasDeletedStateConflict() && ! model.isDecidedDeletedState());
450 }
451 }
452
453 class KeepTheirDeletedStateAction extends AbstractAction implements Observer {
454 public KeepTheirDeletedStateAction() {
455 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagkeeptheir"));
456 putValue(Action.SHORT_DESCRIPTION, tr("Keep their deleted state"));
457 }
458
459 public void actionPerformed(ActionEvent e) {
460 model.decideDeletedStateConflict(MergeDecisionType.KEEP_THEIR);
461 }
462
463 public void update(Observable o, Object arg) {
464 setEnabled(model.hasDeletedStateConflict() && ! model.isDecidedDeletedState());
465 }
466 }
467
468 class UndecideDeletedStateConflictAction extends AbstractAction implements Observer {
469 public UndecideDeletedStateConflictAction() {
470 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs/conflict", "tagundecide"));
471 putValue(Action.SHORT_DESCRIPTION, tr("Undecide conflict between deleted state"));
472 }
473
474 public void actionPerformed(ActionEvent e) {
475 model.decideDeletedStateConflict(MergeDecisionType.UNDECIDED);
476 }
477
478 public void update(Observable o, Object arg) {
479 setEnabled(model.hasDeletedStateConflict() && model.isDecidedDeletedState());
480 }
481 }
482
483 public void deletePrimitive(boolean deleted) {
484 if (deleted) {
485 if (model.getMergedCoords() == null) {
486 model.decideCoordsConflict(MergeDecisionType.KEEP_MINE);
487 }
488 } else {
489 model.decideCoordsConflict(MergeDecisionType.UNDECIDED);
490 }
491 }
492
493 public void populate(Conflict<? extends OsmPrimitive> conflict) {
494 model.populate(conflict);
495 }
496}
Note: See TracBrowser for help on using the repository browser.