001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.widgets;
003    
004    import java.awt.event.MouseAdapter;
005    import java.awt.event.MouseEvent;
006    
007    import javax.swing.JPopupMenu;
008    import javax.swing.JTable;
009    import javax.swing.ListSelectionModel;
010    import javax.swing.SwingUtilities;
011    import javax.swing.table.TableColumnModel;
012    
013    import org.openstreetmap.josm.actions.ZoomToAction;
014    import org.openstreetmap.josm.data.osm.OsmPrimitive;
015    import org.openstreetmap.josm.gui.MapView;
016    import org.openstreetmap.josm.gui.layer.OsmDataLayer;
017    
018    public abstract class OsmPrimitivesTable extends JTable {
019        
020        /**
021         * the data layer in whose context primitives are edited in this table
022         */
023        private 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 PopupListener());
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 PopupListener extends MouseAdapter {
079            @Override
080            public void mousePressed(MouseEvent e) {
081                showPopup(e);
082            }
083    
084            @Override
085            public void mouseReleased(MouseEvent e) {
086                showPopup(e);
087            }
088    
089            private void showPopup(MouseEvent e) {
090                if (e.isPopupTrigger()) {
091                    getPopUpMenu().show(e.getComponent(), e.getX(), e.getY());
092                }
093            }
094        }
095        
096        protected class DblClickHandler extends MouseAdapter {
097    
098            protected void setSelection(MouseEvent e) {
099                int row = rowAtPoint(e.getPoint());
100                if (row < 0) return;
101                OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
102                if (layer != null && primitive != null) {
103                    layer.data.setSelected(primitive.getPrimitiveId());
104                }
105            }
106    
107            protected void addSelection(MouseEvent e) {
108                int row = rowAtPoint(e.getPoint());
109                if (row < 0) return;
110                OsmPrimitive primitive = getPrimitiveInLayer(row, layer);
111                getSelectionModel().addSelectionInterval(row, row);
112                if (layer != null && primitive != null) {
113                    layer.data.addSelected(primitive.getPrimitiveId());
114                }
115            }
116    
117            @Override
118            public void mouseClicked(MouseEvent e) {
119                if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
120                    if (e.isControlDown()) {
121                        addSelection(e);
122                    } else {
123                        setSelection(e);
124                    }
125                }
126            }
127        }
128    }