source: josm/trunk/src/org/openstreetmap/josm/gui/ConflictResolver.java@ 1523

Last change on this file since 1523 was 1169, checked in by stoecker, 15 years ago

removed usage of tab stops

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