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

Last change on this file since 14483 was 14483, checked in by Don-vip, 3 months ago

see #17040 - fix SonarQube issues

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