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.actions.ZoomToAction;
013import org.openstreetmap.josm.data.osm.OsmPrimitive;
014import org.openstreetmap.josm.gui.MapView;
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        MapView.addLayerChangeListener(zoomToAction);
086        getSelectionModel().addListSelectionListener(zoomToAction);
087        menu.add(zoomToAction);
088        return menu;
089    }
090
091    public void unlinkAsListener() {
092        MapView.removeLayerChangeListener(zoomToAction);
093    }
094
095    /**
096     * Returns primitive at the specified row.
097     * @param row table row
098     * @param layer unused in this implementation, can be useful for subclasses
099     * @return primitive at the specified row
100     */
101    public OsmPrimitive getPrimitiveInLayer(int row, OsmDataLayer layer) {
102        return getOsmPrimitivesTableModel().getReferredPrimitive(row);
103    }
104
105    protected class DblClickHandler extends MouseAdapter {
106
107        protected void setSelection(MouseEvent e) {
108            int row = rowAtPoint(e.getPoint());
109            if (row < 0) return;
110            OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
111            if (layer != null && primitive != null) {
112                layer.data.setSelected(primitive.getPrimitiveId());
113            }
114        }
115
116        protected void addSelection(MouseEvent e) {
117            int row = rowAtPoint(e.getPoint());
118            if (row < 0) return;
119            OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
120            getSelectionModel().addSelectionInterval(row, row);
121            if (layer != null && primitive != null) {
122                layer.data.addSelected(primitive.getPrimitiveId());
123            }
124        }
125
126        @Override
127        public void mouseClicked(MouseEvent e) {
128            if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
129                if (e.isControlDown()) {
130                    addSelection(e);
131                } else {
132                    setSelection(e);
133                }
134            }
135        }
136    }
137}