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

Last change on this file since 6336 was 6336, checked in by Don-vip, 11 years ago

code cleanup / robustness in edit layer handling

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