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.JTable;
009import javax.swing.ListSelectionModel;
010import javax.swing.SwingUtilities;
011import javax.swing.table.TableColumnModel;
012
013import org.openstreetmap.josm.actions.ZoomToAction;
014import org.openstreetmap.josm.data.osm.OsmPrimitive;
015import org.openstreetmap.josm.gui.MapView;
016import org.openstreetmap.josm.gui.layer.OsmDataLayer;
017
018public abstract class OsmPrimitivesTable extends JTable {
019
020    /**
021     * the data layer in whose context primitives are edited in this table
022     */
023    private transient OsmDataLayer layer;
024
025    /** the popup menu */
026    private JPopupMenu popupMenu;
027    private ZoomToAction zoomToAction;
028
029    public final OsmDataLayer getLayer() {
030        return layer;
031    }
032
033    public final void setLayer(OsmDataLayer layer) {
034        this.layer = layer;
035    }
036
037    public OsmPrimitivesTable(OsmPrimitivesTableModel dm, TableColumnModel cm, ListSelectionModel sm) {
038        super(dm, cm, sm);
039        addMouseListener(new PopupMenuLauncher(getPopUpMenu()));
040        addMouseListener(new DblClickHandler());
041    }
042
043    public OsmPrimitivesTableModel getOsmPrimitivesTableModel() {
044        return (OsmPrimitivesTableModel) getModel();
045    }
046
047    /**
048     * Replies the popup menu for this table
049     *
050     * @return the popup menu
051     */
052    protected final JPopupMenu getPopUpMenu() {
053        if (popupMenu == null) {
054            popupMenu = buildPopupMenu();
055        }
056        return popupMenu;
057    }
058
059    protected abstract ZoomToAction buildZoomToAction();
060
061    protected JPopupMenu buildPopupMenu() {
062        JPopupMenu menu = new JPopupMenu();
063        zoomToAction = buildZoomToAction();
064        MapView.addLayerChangeListener(zoomToAction);
065        getSelectionModel().addListSelectionListener(zoomToAction);
066        menu.add(zoomToAction);
067        return menu;
068    }
069
070    public void unlinkAsListener() {
071        MapView.removeLayerChangeListener(zoomToAction);
072    }
073
074    public OsmPrimitive getPrimitiveInLayer(int row, OsmDataLayer layer) {
075        return getOsmPrimitivesTableModel().getReferredPrimitive(row);
076    }
077
078    protected class DblClickHandler extends MouseAdapter {
079
080        protected void setSelection(MouseEvent e) {
081            int row = rowAtPoint(e.getPoint());
082            if (row < 0) return;
083            OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
084            if (layer != null && primitive != null) {
085                layer.data.setSelected(primitive.getPrimitiveId());
086            }
087        }
088
089        protected void addSelection(MouseEvent e) {
090            int row = rowAtPoint(e.getPoint());
091            if (row < 0) return;
092            OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
093            getSelectionModel().addSelectionInterval(row, row);
094            if (layer != null && primitive != null) {
095                layer.data.addSelected(primitive.getPrimitiveId());
096            }
097        }
098
099        @Override
100        public void mouseClicked(MouseEvent e) {
101            if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
102                if (e.isControlDown()) {
103                    addSelection(e);
104                } else {
105                    setSelection(e);
106                }
107            }
108        }
109    }
110}