001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.widgets;
003
004import java.awt.event.MouseAdapter;
005import java.awt.event.MouseEvent;
006
007import javax.swing.JPopupMenu;
008import javax.swing.ListSelectionModel;
009import javax.swing.SwingUtilities;
010import javax.swing.table.TableColumnModel;
011
012import org.openstreetmap.josm.Main;
013import org.openstreetmap.josm.actions.ZoomToAction;
014import org.openstreetmap.josm.data.osm.OsmPrimitive;
015import org.openstreetmap.josm.gui.layer.OsmDataLayer;
016
017/**
018 * Table displaying OSM primitives.
019 * @since 5297
020 */
021public abstract class OsmPrimitivesTable extends JosmTable {
022
023    /**
024     * the data layer in whose context primitives are edited in this table
025     */
026    private transient OsmDataLayer layer;
027
028    /** the popup menu */
029    private JPopupMenu popupMenu;
030    private ZoomToAction zoomToAction;
031
032    /**
033     * Constructs a new {@code OsmPrimitivesTable}.
034     * @param dm table model
035     * @param cm column model
036     * @param sm selection model
037     */
038    public OsmPrimitivesTable(OsmPrimitivesTableModel dm, TableColumnModel cm, ListSelectionModel sm) {
039        super(dm, cm, sm);
040        addMouseListener(new PopupMenuLauncher(getPopUpMenu()));
041        addMouseListener(new DblClickHandler());
042    }
043
044    /**
045     * Returns the table model.
046     * @return the table model
047     */
048    public OsmPrimitivesTableModel getOsmPrimitivesTableModel() {
049        return (OsmPrimitivesTableModel) getModel();
050    }
051
052    /**
053     * Returns the data layer.
054     * @return the data layer
055     */
056    public final OsmDataLayer getLayer() {
057        return layer;
058    }
059
060    /**
061     * Sets the data layer.
062     * @param layer the data layer
063     */
064    public final void setLayer(OsmDataLayer layer) {
065        this.layer = layer;
066    }
067
068    /**
069     * Replies the popup menu for this table
070     *
071     * @return the popup menu
072     */
073    protected final JPopupMenu getPopUpMenu() {
074        if (popupMenu == null) {
075            popupMenu = buildPopupMenu();
076        }
077        return popupMenu;
078    }
079
080    protected abstract ZoomToAction buildZoomToAction();
081
082    protected JPopupMenu buildPopupMenu() {
083        JPopupMenu menu = new JPopupMenu();
084        zoomToAction = buildZoomToAction();
085        getSelectionModel().addListSelectionListener(zoomToAction);
086        menu.add(zoomToAction);
087        return menu;
088    }
089
090    /**
091     * Adds all registered listeners by this table
092     * @see #unregisterListeners()
093     * @since 10454
094     */
095    public void registerListeners() {
096        Main.getLayerManager().addLayerChangeListener(zoomToAction);
097        Main.getLayerManager().addActiveLayerChangeListener(zoomToAction);
098    }
099
100    /**
101     * Removes all registered listeners by this table
102     * @since 10454
103     */
104    public void unregisterListeners() {
105        Main.getLayerManager().removeLayerChangeListener(zoomToAction);
106        Main.getLayerManager().removeActiveLayerChangeListener(zoomToAction);
107    }
108
109    /**
110     * Returns primitive at the specified row.
111     * @param row table row
112     * @param layer unused in this implementation, can be useful for subclasses
113     * @return primitive at the specified row
114     */
115    public OsmPrimitive getPrimitiveInLayer(int row, OsmDataLayer layer) {
116        return getOsmPrimitivesTableModel().getReferredPrimitive(row);
117    }
118
119    protected class DblClickHandler extends MouseAdapter {
120
121        protected void setSelection(MouseEvent e) {
122            int row = rowAtPoint(e.getPoint());
123            if (row < 0) return;
124            OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
125            if (layer != null && primitive != null) {
126                layer.data.setSelected(primitive.getPrimitiveId());
127            }
128        }
129
130        protected void addSelection(MouseEvent e) {
131            int row = rowAtPoint(e.getPoint());
132            if (row < 0) return;
133            OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
134            getSelectionModel().addSelectionInterval(row, row);
135            if (layer != null && primitive != null) {
136                layer.data.addSelected(primitive.getPrimitiveId());
137            }
138        }
139
140        @Override
141        public void mouseClicked(MouseEvent e) {
142            if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
143                if (e.isControlDown()) {
144                    addSelection(e);
145                } else {
146                    setSelection(e);
147                }
148            }
149        }
150    }
151}