source: josm/trunk/src/org/openstreetmap/josm/gui/history/NodeListViewer.java@ 4689

Last change on this file since 4689 was 4498, checked in by simon04, 13 years ago

see #6774 - Make History dialog more diff-like (patch by olejorgenb)

  • Property svn:eol-style set to native
File size: 11.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.history;
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.Point;
10import java.awt.event.ActionEvent;
11import java.awt.event.MouseAdapter;
12import java.awt.event.MouseEvent;
13
14import javax.swing.AbstractAction;
15import javax.swing.JPanel;
16import javax.swing.JPopupMenu;
17import javax.swing.JScrollPane;
18import javax.swing.JTable;
19import javax.swing.ListSelectionModel;
20import javax.swing.table.TableModel;
21
22import org.openstreetmap.josm.Main;
23import org.openstreetmap.josm.actions.AutoScaleAction;
24import org.openstreetmap.josm.data.osm.OsmPrimitive;
25import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
26import org.openstreetmap.josm.data.osm.PrimitiveId;
27import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
28import org.openstreetmap.josm.data.osm.history.History;
29import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
30import org.openstreetmap.josm.gui.layer.OsmDataLayer;
31import org.openstreetmap.josm.tools.ImageProvider;
32
33/**
34 * NodeListViewer is a UI component which displays the node list of two
35 * version of a {@see OsmPrimitive} in a {@see History}.
36 *
37 * <ul>
38 * <li>on the left, it displays the node list for the version at {@see PointInTimeType#REFERENCE_POINT_IN_TIME}</li>
39 * <li>on the right, it displays the node list for the version at {@see PointInTimeType#CURRENT_POINT_IN_TIME}</li>
40 * </ul>
41 *
42 */
43public class NodeListViewer extends JPanel {
44
45 private HistoryBrowserModel model;
46 private VersionInfoPanel referenceInfoPanel;
47 private VersionInfoPanel currentInfoPanel;
48 private AdjustmentSynchronizer adjustmentSynchronizer;
49 private SelectionSynchronizer selectionSynchronizer;
50 private NodeListPopupMenu popupMenu;
51
52 protected JScrollPane embeddInScrollPane(JTable table) {
53 JScrollPane pane = new JScrollPane(table);
54 pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
55 pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
56 adjustmentSynchronizer.participateInSynchronizedScrolling(pane.getVerticalScrollBar());
57 return pane;
58 }
59
60 protected JTable buildReferenceNodeListTable() {
61 JTable table = new JTable(
62 model.getNodeListTableModel(PointInTimeType.REFERENCE_POINT_IN_TIME),
63 new NodeListTableColumnModel()
64 );
65 table.setName("table.referencenodelisttable");
66 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
67 selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
68 table.addMouseListener(new PopupMenuLauncher(table));
69 table.addMouseListener(new DoubleClickAdapter(table));
70 return table;
71 }
72
73 protected JTable buildCurrentNodeListTable() {
74 JTable table = new JTable(
75 model.getNodeListTableModel(PointInTimeType.CURRENT_POINT_IN_TIME),
76 new NodeListTableColumnModel()
77 );
78 table.setName("table.currentnodelisttable");
79 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
80 selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
81 table.addMouseListener(new PopupMenuLauncher(table));
82 table.addMouseListener(new DoubleClickAdapter(table));
83 return table;
84 }
85
86 protected void build() {
87 setLayout(new GridBagLayout());
88 GridBagConstraints gc = new GridBagConstraints();
89
90 // ---------------------------
91 gc.gridx = 0;
92 gc.gridy = 0;
93 gc.gridwidth = 1;
94 gc.gridheight = 1;
95 gc.weightx = 0.5;
96 gc.weighty = 0.0;
97 gc.insets = new Insets(5,5,5,0);
98 gc.fill = GridBagConstraints.HORIZONTAL;
99 gc.anchor = GridBagConstraints.FIRST_LINE_START;
100 referenceInfoPanel = new VersionInfoPanel(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
101 add(referenceInfoPanel,gc);
102
103 gc.gridx = 1;
104 gc.gridy = 0;
105 gc.gridwidth = 1;
106 gc.gridheight = 1;
107 gc.fill = GridBagConstraints.HORIZONTAL;
108 gc.weightx = 0.5;
109 gc.weighty = 0.0;
110 gc.anchor = GridBagConstraints.FIRST_LINE_START;
111 currentInfoPanel = new VersionInfoPanel(model, PointInTimeType.CURRENT_POINT_IN_TIME);
112 add(currentInfoPanel,gc);
113
114 adjustmentSynchronizer = new AdjustmentSynchronizer();
115 selectionSynchronizer = new SelectionSynchronizer();
116
117 // ---------------------------
118 gc.gridx = 0;
119 gc.gridy = 1;
120 gc.gridwidth = 1;
121 gc.gridheight = 1;
122 gc.weightx = 0.5;
123 gc.weighty = 1.0;
124 gc.fill = GridBagConstraints.BOTH;
125 gc.anchor = GridBagConstraints.NORTHWEST;
126 add(embeddInScrollPane(buildReferenceNodeListTable()),gc);
127
128 gc.gridx = 1;
129 gc.gridy = 1;
130 gc.gridwidth = 1;
131 gc.gridheight = 1;
132 gc.weightx = 0.5;
133 gc.weighty = 1.0;
134 gc.fill = GridBagConstraints.BOTH;
135 gc.anchor = GridBagConstraints.NORTHWEST;
136 add(embeddInScrollPane(buildCurrentNodeListTable()),gc);
137
138 popupMenu = new NodeListPopupMenu();
139 }
140
141 public NodeListViewer(HistoryBrowserModel model) {
142 setModel(model);
143 build();
144 }
145
146 protected void unregisterAsObserver(HistoryBrowserModel model) {
147 if (currentInfoPanel != null) {
148 model.deleteObserver(currentInfoPanel);
149 }
150 if (referenceInfoPanel != null) {
151 model.deleteObserver(referenceInfoPanel);
152 }
153 }
154 protected void registerAsObserver(HistoryBrowserModel model) {
155 if (currentInfoPanel != null) {
156 model.addObserver(currentInfoPanel);
157 }
158 if (referenceInfoPanel != null) {
159 model.addObserver(referenceInfoPanel);
160 }
161 }
162
163 public void setModel(HistoryBrowserModel model) {
164 if (this.model != null) {
165 unregisterAsObserver(model);
166 }
167 this.model = model;
168 if (this.model != null) {
169 registerAsObserver(model);
170 }
171 }
172
173 static class NodeListPopupMenu extends JPopupMenu {
174 private ZoomToNodeAction zoomToNodeAction;
175 private ShowHistoryAction showHistoryAction;
176
177 public NodeListPopupMenu() {
178 zoomToNodeAction = new ZoomToNodeAction();
179 add(zoomToNodeAction);
180 showHistoryAction = new ShowHistoryAction();
181 add(showHistoryAction);
182 }
183
184 public void prepare(PrimitiveId pid){
185 zoomToNodeAction.setPrimitiveId(pid);
186 zoomToNodeAction.updateEnabledState();
187
188 showHistoryAction.setPrimitiveId(pid);
189 showHistoryAction.updateEnabledState();
190 }
191 }
192
193 static class ZoomToNodeAction extends AbstractAction {
194 private PrimitiveId primitiveId;
195
196 public ZoomToNodeAction() {
197 putValue(NAME, tr("Zoom to node"));
198 putValue(SHORT_DESCRIPTION, tr("Zoom to this node in the current data layer"));
199 putValue(SMALL_ICON, ImageProvider.get("dialogs", "zoomin"));
200 }
201
202 public void actionPerformed(ActionEvent e) {
203 if (!isEnabled()) return;
204 OsmPrimitive p = getPrimitiveToZoom();
205 if (p!= null) {
206 getEditLayer().data.setSelected(p.getPrimitiveId());
207 AutoScaleAction.autoScale("selection");
208 }
209 }
210
211 public void setPrimitiveId(PrimitiveId pid) {
212 this.primitiveId = pid;
213 updateEnabledState();
214 }
215
216 protected OsmDataLayer getEditLayer() {
217 try {
218 return Main.map.mapView.getEditLayer();
219 } catch(NullPointerException e) {
220 return null;
221 }
222 }
223
224 protected OsmPrimitive getPrimitiveToZoom() {
225 if (primitiveId == null) return null;
226 OsmPrimitive p = getEditLayer().data.getPrimitiveById(primitiveId);
227 return p;
228 }
229
230 public void updateEnabledState() {
231 if (getEditLayer() == null) {
232 setEnabled(false);
233 return;
234 }
235 setEnabled(getPrimitiveToZoom() != null);
236 }
237 }
238
239 static class ShowHistoryAction extends AbstractAction {
240 private PrimitiveId primitiveId;
241
242 public ShowHistoryAction() {
243 putValue(NAME, tr("Show history"));
244 putValue(SHORT_DESCRIPTION, tr("Open a history browser with the history of this node"));
245 putValue(SMALL_ICON, ImageProvider.get("dialogs", "history"));
246 }
247
248 public void actionPerformed(ActionEvent e) {
249 if (!isEnabled()) return;
250 run();
251 }
252
253 public void setPrimitiveId(PrimitiveId pid) {
254 this.primitiveId = pid;
255 updateEnabledState();
256 }
257
258 public void run() {
259 if (HistoryDataSet.getInstance().getHistory(primitiveId) == null) {
260 Main.worker.submit(new HistoryLoadTask().add(primitiveId));
261 }
262 Runnable r = new Runnable() {
263 public void run() {
264 History h = HistoryDataSet.getInstance().getHistory(primitiveId);
265 if (h == null)
266 return;
267 HistoryBrowserDialogManager.getInstance().show(h);
268 }
269 };
270 Main.worker.submit(r);
271 }
272
273 public void updateEnabledState() {
274 setEnabled(primitiveId != null && primitiveId.getUniqueId() > 0);
275 }
276 }
277
278 static private PrimitiveId primitiveIdAtRow(TableModel model, int row) {
279 DiffTableModel castedModel = (DiffTableModel) model;
280 Long id = (Long)castedModel.getValueAt(row, 0).value;
281 if(id == null) return null;
282 return new SimplePrimitiveId(id, OsmPrimitiveType.NODE);
283 }
284
285 class PopupMenuLauncher extends MouseAdapter {
286 private JTable table;
287
288 public PopupMenuLauncher(JTable table) {
289 this.table = table;
290 }
291
292 @Override
293 public void mousePressed(MouseEvent e) {
294 showPopup(e);
295 }
296
297 @Override
298 public void mouseReleased(MouseEvent e) {
299 showPopup(e);
300 }
301
302 private void showPopup(MouseEvent e) {
303 if (!e.isPopupTrigger()) return;
304 Point p = e.getPoint();
305 int row = table.rowAtPoint(p);
306
307 PrimitiveId pid = primitiveIdAtRow(table.getModel(), row);
308 if (pid == null)
309 return;
310 popupMenu.prepare(pid);
311 popupMenu.show(e.getComponent(), e.getX(), e.getY());
312 }
313 }
314
315 static class DoubleClickAdapter extends MouseAdapter {
316 private JTable table;
317 private ShowHistoryAction showHistoryAction;
318
319 public DoubleClickAdapter(JTable table) {
320 this.table = table;
321 showHistoryAction = new ShowHistoryAction();
322 }
323
324 @Override
325 public void mouseClicked(MouseEvent e) {
326 if (e.getClickCount() < 2) return;
327 int row = table.rowAtPoint(e.getPoint());
328 if(row <= 0) return;
329 PrimitiveId pid = primitiveIdAtRow(table.getModel(), row);
330 if (pid == null)
331 return;
332 showHistoryAction.setPrimitiveId(pid);
333 showHistoryAction.run();
334 }
335 }
336}
Note: See TracBrowser for help on using the repository browser.