source: josm/branch/0.5/src/org/openstreetmap/josm/gui/ConflictResolver.java@ 340

Last change on this file since 340 was 340, checked in by framm, 17 years ago
  • merged in JOSM render speed patch by Brent Easton
  • merged in Imi's changes to remove eigenheimstrasse.de references
  • merged in the plugin download whitespace stripping bugfix
File size: 9.3 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.Font;
10import java.awt.GridBagLayout;
11import java.awt.event.ActionEvent;
12import java.awt.event.MouseAdapter;
13import java.awt.event.MouseEvent;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.Iterator;
17import java.util.List;
18import java.util.Map;
19import java.util.TreeSet;
20import java.util.Map.Entry;
21
22import javax.swing.AbstractAction;
23import javax.swing.JButton;
24import javax.swing.JLabel;
25import javax.swing.JOptionPane;
26import javax.swing.JPanel;
27import javax.swing.JScrollPane;
28import javax.swing.JTable;
29import javax.swing.ListSelectionModel;
30import javax.swing.event.ListSelectionEvent;
31import javax.swing.event.ListSelectionListener;
32import javax.swing.event.TableModelListener;
33import javax.swing.table.DefaultTableCellRenderer;
34import javax.swing.table.TableCellRenderer;
35import javax.swing.table.TableModel;
36
37import org.openstreetmap.josm.Main;
38import org.openstreetmap.josm.data.conflict.ConflictItem;
39import org.openstreetmap.josm.data.conflict.DeleteConflict;
40import org.openstreetmap.josm.data.conflict.PositionConflict;
41import org.openstreetmap.josm.data.conflict.PropertyConflict;
42import org.openstreetmap.josm.data.osm.OsmPrimitive;
43import org.openstreetmap.josm.tools.GBC;
44import org.openstreetmap.josm.tools.ImageProvider;
45
46/**
47 * A panel which implement the conflict resolving of a set of primitive-pairs. There will be
48 * three tables in the screen, one for each both sides and one resulting table. The user can
49 * move items from either one of the sides ("my" and "their") to the resulting table.
50 *
51 * @author Imi
52 */
53public class ConflictResolver extends JPanel {
54
55 public static enum Resolution {MY, THEIR}
56
57 private final class ConflictTableModel implements TableModel {
58 private final Resolution resolution;
59 public ConflictTableModel(Resolution resolution) {
60 this.resolution = resolution;
61 }
62
63 public int getRowCount() {
64 return conflicts.size();
65 }
66
67 public Object getValueAt(int rowIndex, int columnIndex) {
68 ConflictItem ci = conflicts.get(rowIndex);
69 if (columnIndex == 0)
70 return ci.key();
71 Resolution r = resolution == null ? ci.resolution : resolution;
72 if (r == null)
73 return "<html><i>???</i></html>";
74 JLabel l = new JLabel(r == Resolution.MY ? ci.my : ci.their);
75 if (ci.resolution == resolution && resolution != null)
76 l.setFont(l.getFont().deriveFont(Font.BOLD));
77 return l;
78 }
79
80 public String getColumnName(int columnIndex) {return columnIndex == 0 ? tr("Key") : tr("Value");}
81 public int getColumnCount() {return 2;}
82 public boolean isCellEditable(int row, int column) {return false;}
83 public Class<?> getColumnClass(int columnIndex) {return Object.class;}
84
85 public void addTableModelListener(TableModelListener l) {}
86 public void removeTableModelListener(TableModelListener l) {}
87 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {}
88 }
89
90 private final class DblClickListener extends MouseAdapter {
91 private final Resolution resolution;
92 public DblClickListener(Resolution resolution) {
93 this.resolution = resolution;
94 }
95 @Override public void mouseClicked(MouseEvent e) {
96 if (e.getClickCount() >= 2) {
97 int sel = ((JTable)e.getSource()).getSelectedRow();
98 if (sel == -1)
99 return;
100 ConflictResolver.this.conflicts.get(sel).resolution = resolution;
101 repaint();
102 }
103 }
104 }
105 private final class ResolveAction extends AbstractAction {
106 private final Resolution resolution;
107 public ResolveAction(String name, Resolution resolution) {
108 super(null, ImageProvider.get("dialogs", name));
109 this.resolution = resolution;
110 }
111 public void actionPerformed(ActionEvent e) {
112 int sel = myTable.getSelectedRow();
113 if (sel == -1)
114 return;
115 conflicts.get(sel).resolution = resolution;
116 if (sel == myTable.getRowCount()-1)
117 myTable.clearSelection();
118 else
119 myTable.getSelectionModel().setSelectionInterval(sel+1, sel+1);
120 repaint();
121 }
122 }
123
124 public final List<ConflictItem> conflicts = new ArrayList<ConflictItem>();
125
126 private final ConflictTableModel my = new ConflictTableModel(Resolution.MY);
127 private final JTable myTable;
128 private final ConflictTableModel their = new ConflictTableModel(Resolution.THEIR);
129 private final JTable theirTable;
130 private final ConflictTableModel resolve = new ConflictTableModel(null);
131 private final JTable resolveTable;
132
133
134 public ConflictResolver(Map<OsmPrimitive, OsmPrimitive> conflicts) {
135 super(new GridBagLayout());
136 Collection<ConflictItem> possibleConflicts = new ArrayList<ConflictItem>();
137 possibleConflicts.add(new DeleteConflict());
138 possibleConflicts.add(new PositionConflict());
139 TreeSet<String> allkeys = new TreeSet<String>();
140 for (Entry<OsmPrimitive, OsmPrimitive> e : conflicts.entrySet()) {
141 allkeys.addAll(e.getKey().keySet());
142 allkeys.addAll(e.getValue().keySet());
143 }
144 for (String s : allkeys)
145 possibleConflicts.add(new PropertyConflict(s));
146
147 for (Entry<OsmPrimitive, OsmPrimitive> e : conflicts.entrySet()) {
148 for (Iterator<ConflictItem> it = possibleConflicts.iterator(); it.hasNext();) {
149 ConflictItem ci = it.next();
150 if (ci.hasConflict(e.getKey(), e.getValue())) {
151 ci.initialize(conflicts);
152 this.conflicts.add(ci);
153 it.remove();
154 }
155 }
156 }
157
158
159 // have to initialize the JTables here and not in the declaration, because its constructor
160 // may access this.conflicts (indirectly)
161 myTable = new JTable(my);
162 theirTable = new JTable(their);
163 resolveTable = new JTable(resolve);
164
165 myTable.setPreferredScrollableViewportSize(new Dimension(250,70));
166 theirTable.setPreferredScrollableViewportSize(new Dimension(250,70));
167 resolveTable.setPreferredScrollableViewportSize(new Dimension(250,70));
168
169 TableCellRenderer renderer = new DefaultTableCellRenderer(){
170 final Font defFont = new JLabel().getFont();
171 @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
172 JLabel c = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
173 c.setIcon(null);
174 c.setFont(defFont);
175 if (value instanceof JLabel) {
176 JLabel l = (JLabel)value;
177 String text = l.getText();
178 c.setText(text);
179 c.setFont(l.getFont());
180 if (text.startsWith("<html>") && l.getFont().isBold())
181 c.setText("<html>"+"<b>"+text.substring(6, text.length()-12));
182 } else {
183 String s = value.toString();
184 int i = s.indexOf('|');
185 if (i != -1) {
186 c.setIcon(ImageProvider.get("data", s.substring(0,i)));
187 c.setText(s.substring(i+1));
188 }
189 }
190 return c;
191 }
192 };
193 myTable.setDefaultRenderer(Object.class, renderer);
194 theirTable.setDefaultRenderer(Object.class, renderer);
195 resolveTable.setDefaultRenderer(Object.class, renderer);
196
197 myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
198 theirTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
199 resolveTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
200 ListSelectionListener selListener = new ListSelectionListener(){
201 public void valueChanged(ListSelectionEvent e) {
202 if (((ListSelectionModel)e.getSource()).isSelectionEmpty()) {
203 myTable.clearSelection();
204 theirTable.clearSelection();
205 resolveTable.clearSelection();
206 } else {
207 int i = ((ListSelectionModel)e.getSource()).getMinSelectionIndex();
208 myTable.scrollRectToVisible(myTable.getCellRect(i, 0, true));
209 myTable.getSelectionModel().setSelectionInterval(i, i);
210 theirTable.scrollRectToVisible(theirTable.getCellRect(i, 0, true));
211 theirTable.getSelectionModel().setSelectionInterval(i, i);
212 resolveTable.scrollRectToVisible(resolveTable.getCellRect(i, 0, true));
213 resolveTable.getSelectionModel().setSelectionInterval(i, i);
214 }
215 }
216 };
217 myTable.getSelectionModel().addListSelectionListener(selListener);
218 theirTable.getSelectionModel().addListSelectionListener(selListener);
219 resolveTable.getSelectionModel().addListSelectionListener(selListener);
220 myTable.getSelectionModel().setSelectionInterval(0,0);
221
222 myTable.addMouseListener(new DblClickListener(Resolution.MY));
223 theirTable.addMouseListener(new DblClickListener(Resolution.THEIR));
224 resolveTable.addMouseListener(new DblClickListener(null));
225
226 add(new JLabel(trn("{0} object has conflicts:","{0} objects have conflicts:",conflicts.size(),conflicts.size())), GBC.eol().insets(0,0,0,10));
227
228 JPanel p = new JPanel(new GridBagLayout());
229 p.add(new JLabel(tr("my version:")), GBC.eol());
230 p.add(new JScrollPane(myTable), GBC.eol().fill(GBC.BOTH));
231 p.add(new JButton(new ResolveAction("down", Resolution.MY)), GBC.eol().anchor(GBC.CENTER).insets(0,5,0,0));
232 add(p, GBC.std().insets(0,0,5,0));
233
234 p = new JPanel(new GridBagLayout());
235 p.add(new JLabel(tr("their version:")), GBC.eol());
236 p.add(new JScrollPane(theirTable), GBC.eol().fill(GBC.BOTH));
237 p.add(new JButton(new ResolveAction("down", Resolution.THEIR)), GBC.eol().anchor(GBC.CENTER).insets(0,5,0,0));
238 add(p, GBC.eop().insets(5,0,0,0));
239
240 add(new JButton(new ResolveAction("up", null)), GBC.eol().anchor(GBC.CENTER));
241 add(new JLabel(tr("resolved version:")), GBC.eol().insets(0,5,0,0));
242 add(new JScrollPane(resolveTable), GBC.eol().anchor(GBC.CENTER).fill(GBC.BOTH));
243 }
244}
Note: See TracBrowser for help on using the repository browser.