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

Last change on this file since 14675 was 14675, checked in by simon04, 6 weeks ago

HistoryViewer: fix code duplication

  • Property svn:eol-style set to native
File size: 9.4 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.Point;
7import java.awt.event.ActionEvent;
8import java.awt.event.MouseAdapter;
9import java.awt.event.MouseEvent;
10
11import javax.swing.AbstractAction;
12import javax.swing.JPopupMenu;
13import javax.swing.JTable;
14import javax.swing.ListSelectionModel;
15import javax.swing.event.TableModelEvent;
16import javax.swing.event.TableModelListener;
17
18import org.openstreetmap.josm.actions.AutoScaleAction;
19import org.openstreetmap.josm.actions.AutoScaleAction.AutoScaleMode;
20import org.openstreetmap.josm.data.osm.IPrimitive;
21import org.openstreetmap.josm.data.osm.OsmData;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
24import org.openstreetmap.josm.data.osm.PrimitiveId;
25import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
26import org.openstreetmap.josm.data.osm.history.History;
27import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
28import org.openstreetmap.josm.gui.MainApplication;
29import org.openstreetmap.josm.gui.util.GuiHelper;
30import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
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 {@link OsmPrimitive} in a {@link History}.
36 *
37 * <ul>
38 *   <li>on the left, it displays the node list for the version at {@link PointInTimeType#REFERENCE_POINT_IN_TIME}</li>
39 *   <li>on the right, it displays the node list for the version at {@link PointInTimeType#CURRENT_POINT_IN_TIME}</li>
40 * </ul>
41 * @since 1709
42 */
43public class NodeListViewer extends HistoryViewerPanel {
44
45    private final NodeListPopupMenu popupMenu = new NodeListPopupMenu();
46
47    /**
48     * Constructs a new {@code NodeListViewer}.
49     * @param model history browser model
50     */
51    public NodeListViewer(HistoryBrowserModel model) {
52        super(model);
53    }
54
55    @Override
56    protected JTable buildReferenceTable() {
57        return buildTable(PointInTimeType.REFERENCE_POINT_IN_TIME, "table.referencenodelisttable");
58    }
59
60    @Override
61    protected JTable buildCurrentTable() {
62        return buildTable(PointInTimeType.CURRENT_POINT_IN_TIME, "table.currentnodelisttable");
63    }
64
65    private JTable buildTable(PointInTimeType pointInTimeType, String name) {
66        final DiffTableModel tableModel = model.getNodeListTableModel(pointInTimeType);
67        final NodeListTableColumnModel columnModel = new NodeListTableColumnModel();
68        final JTable table = new JTable(tableModel, columnModel);
69        tableModel.addTableModelListener(new ReversedChangeListener(table, columnModel));
70        table.setName(name);
71        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
72        selectionSynchronizer.participateInSynchronizedSelection(table.getSelectionModel());
73        table.addMouseListener(new InternalPopupMenuLauncher());
74        table.addMouseListener(new DoubleClickAdapter(table));
75        return table;
76    }
77
78    static final class ReversedChangeListener implements TableModelListener {
79        private final NodeListTableColumnModel columnModel;
80        private final JTable table;
81        private Boolean reversed;
82        private final String nonReversedText;
83        private final String reversedText;
84
85        ReversedChangeListener(JTable table, NodeListTableColumnModel columnModel) {
86            this.columnModel = columnModel;
87            this.table = table;
88            nonReversedText = tr("Nodes") + (table.getFont().canDisplay('\u25bc') ? " \u25bc" : " (1-n)");
89            reversedText = tr("Nodes") + (table.getFont().canDisplay('\u25b2') ? " \u25b2" : " (n-1)");
90        }
91
92        @Override
93        public void tableChanged(TableModelEvent e) {
94            if (e.getSource() instanceof DiffTableModel) {
95                final DiffTableModel mod = (DiffTableModel) e.getSource();
96                if (reversed == null || reversed != mod.isReversed()) {
97                    reversed = mod.isReversed();
98                    columnModel.getColumn(0).setHeaderValue(reversed ? reversedText : nonReversedText);
99                    table.getTableHeader().setToolTipText(
100                            reversed ? tr("The nodes of this way are in reverse order") : null);
101                    table.getTableHeader().repaint();
102                }
103            }
104        }
105    }
106
107    static class NodeListPopupMenu extends JPopupMenu {
108        private final ZoomToNodeAction zoomToNodeAction;
109        private final ShowHistoryAction showHistoryAction;
110
111        NodeListPopupMenu() {
112            zoomToNodeAction = new ZoomToNodeAction();
113            add(zoomToNodeAction);
114            showHistoryAction = new ShowHistoryAction();
115            add(showHistoryAction);
116        }
117
118        public void prepare(PrimitiveId pid) {
119            zoomToNodeAction.setPrimitiveId(pid);
120            zoomToNodeAction.updateEnabledState();
121
122            showHistoryAction.setPrimitiveId(pid);
123            showHistoryAction.updateEnabledState();
124        }
125    }
126
127    static class ZoomToNodeAction extends AbstractAction {
128        private transient PrimitiveId primitiveId;
129
130        /**
131         * Constructs a new {@code ZoomToNodeAction}.
132         */
133        ZoomToNodeAction() {
134            putValue(NAME, tr("Zoom to node"));
135            putValue(SHORT_DESCRIPTION, tr("Zoom to this node in the current data layer"));
136            new ImageProvider("dialogs", "zoomin").getResource().attachImageIcon(this, true);
137        }
138
139        @Override
140        public void actionPerformed(ActionEvent e) {
141            if (!isEnabled())
142                return;
143            IPrimitive p = getPrimitiveToZoom();
144            if (p != null) {
145                OsmData<?, ?, ?, ?> ds = MainApplication.getLayerManager().getActiveData();
146                if (ds != null) {
147                    ds.setSelected(p.getPrimitiveId());
148                    AutoScaleAction.autoScale(AutoScaleMode.SELECTION);
149                }
150            }
151        }
152
153        public void setPrimitiveId(PrimitiveId pid) {
154            this.primitiveId = pid;
155            updateEnabledState();
156        }
157
158        protected IPrimitive getPrimitiveToZoom() {
159            if (primitiveId == null)
160                return null;
161            OsmData<?, ?, ?, ?> ds = MainApplication.getLayerManager().getActiveData();
162            if (ds == null)
163                return null;
164            return ds.getPrimitiveById(primitiveId);
165        }
166
167        public void updateEnabledState() {
168            setEnabled(MainApplication.getLayerManager().getActiveData() != null && getPrimitiveToZoom() != null);
169        }
170    }
171
172    static class ShowHistoryAction extends AbstractAction {
173        private transient PrimitiveId primitiveId;
174
175        /**
176         * Constructs a new {@code ShowHistoryAction}.
177         */
178        ShowHistoryAction() {
179            putValue(NAME, tr("Show history"));
180            putValue(SHORT_DESCRIPTION, tr("Open a history browser with the history of this node"));
181            new ImageProvider("dialogs", "history").getResource().attachImageIcon(this, true);
182        }
183
184        @Override
185        public void actionPerformed(ActionEvent e) {
186            if (isEnabled()) {
187                run();
188            }
189        }
190
191        public void setPrimitiveId(PrimitiveId pid) {
192            this.primitiveId = pid;
193            updateEnabledState();
194        }
195
196        public void run() {
197            if (HistoryDataSet.getInstance().getHistory(primitiveId) == null) {
198                MainApplication.worker.submit(new HistoryLoadTask().add(primitiveId));
199            }
200            MainApplication.worker.submit(() -> {
201                final History h = HistoryDataSet.getInstance().getHistory(primitiveId);
202                if (h == null)
203                    return;
204                GuiHelper.runInEDT(() -> HistoryBrowserDialogManager.getInstance().show(h));
205            });
206        }
207
208        public void updateEnabledState() {
209            setEnabled(primitiveId != null && !primitiveId.isNew());
210        }
211    }
212
213    private static PrimitiveId primitiveIdAtRow(DiffTableModel model, int row) {
214        Long id = (Long) model.getValueAt(row, 0).value;
215        return id == null ? null : new SimplePrimitiveId(id, OsmPrimitiveType.NODE);
216    }
217
218    class InternalPopupMenuLauncher extends PopupMenuLauncher {
219        InternalPopupMenuLauncher() {
220            super(popupMenu);
221        }
222
223        @Override
224        protected int checkTableSelection(JTable table, Point p) {
225            int row = super.checkTableSelection(table, p);
226            popupMenu.prepare(primitiveIdAtRow((DiffTableModel) table.getModel(), row));
227            return row;
228        }
229    }
230
231    static class DoubleClickAdapter extends MouseAdapter {
232        private final JTable table;
233        private final ShowHistoryAction showHistoryAction;
234
235        DoubleClickAdapter(JTable table) {
236            this.table = table;
237            showHistoryAction = new ShowHistoryAction();
238        }
239
240        @Override
241        public void mouseClicked(MouseEvent e) {
242            if (e.getClickCount() < 2)
243                return;
244            int row = table.rowAtPoint(e.getPoint());
245            if (row <= 0)
246                return;
247            PrimitiveId pid = primitiveIdAtRow((DiffTableModel) table.getModel(), row);
248            if (pid == null || pid.isNew())
249                return;
250            showHistoryAction.setPrimitiveId(pid);
251            showHistoryAction.run();
252        }
253    }
254}
Note: See TracBrowser for help on using the repository browser.