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}