source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTable.java@ 1868

Last change on this file since 1868 was 1868, checked in by Gubaer, 15 years ago

fixed #3041: Relation Editor: Provide action for zooming to a particular member

File size: 8.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import java.awt.event.ActionEvent;
5import java.awt.event.KeyEvent;
6import java.awt.event.MouseAdapter;
7import java.awt.event.MouseEvent;
8
9import javax.swing.AbstractAction;
10import javax.swing.JComponent;
11import javax.swing.JPopupMenu;
12import javax.swing.JTable;
13import javax.swing.KeyStroke;
14import javax.swing.ListSelectionModel;
15import javax.swing.event.ListSelectionEvent;
16import javax.swing.event.ListSelectionListener;
17import javax.swing.table.TableColumnModel;
18
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.actions.AutoScaleAction;
21import org.openstreetmap.josm.data.osm.DataSet;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.gui.layer.Layer;
24import org.openstreetmap.josm.gui.layer.OsmDataLayer;
25import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
26
27import static org.openstreetmap.josm.tools.I18n.tr;
28
29public class MemberTable extends JTable implements IMemberModelListener {
30
31 /**
32 * the data layer in whose context relation members are edited in this table
33 */
34 protected OsmDataLayer layer;
35
36 /** the popup menu */
37 protected JPopupMenu popupMenu;
38
39 /**
40 * constructor
41 *
42 * @param model
43 * @param columnModel
44 */
45 public MemberTable(OsmDataLayer layer, MemberTableModel model) {
46 super(model, new MemberTableColumnModel(), model.getSelectionModel());
47 this.layer = layer;
48 model.addMemberModelListener(this);
49 init();
50
51 }
52
53 /**
54 * initialize the table
55 */
56 protected void init() {
57 setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
58 setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
59 putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
60
61 // make ENTER behave like TAB
62 //
63 getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
64 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "selectNextColumnCell");
65
66 // install custom navigation actions
67 //
68 getActionMap().put("selectNextColumnCell", new SelectNextColumnCellAction());
69 getActionMap().put("selectPreviousColumnCell", new SelectPreviousColumnCellAction());
70
71 addMouseListener(new PopupListener());
72 }
73
74 /**
75 * adjusts the width of the columns for the tag name and the tag value to the width of the
76 * scroll panes viewport.
77 *
78 * Note: {@see #getPreferredScrollableViewportSize()} did not work as expected
79 *
80 * @param scrollPaneWidth the width of the scroll panes viewport
81 */
82 public void adjustColumnWidth(int scrollPaneWidth) {
83 TableColumnModel tcm = getColumnModel();
84 int width = scrollPaneWidth;
85 width = width / 3;
86 if (width > 0) {
87 tcm.getColumn(0).setMinWidth(width);
88 tcm.getColumn(0).setMaxWidth(width);
89 tcm.getColumn(1).setMinWidth(width);
90 tcm.getColumn(1).setMaxWidth(width);
91 tcm.getColumn(2).setMinWidth(width);
92 tcm.getColumn(2).setMaxWidth(width);
93
94 }
95 }
96
97 public void makeMemberVisible(int index) {
98 scrollRectToVisible(getCellRect(index, 0, true));
99 }
100
101 /**
102 * Action to be run when the user navigates to the next cell in the table, for instance by
103 * pressing TAB or ENTER. The action alters the standard navigation path from cell to cell: <ul>
104 * <li>it jumps over cells in the first column</li> <li>it automatically add a new empty row
105 * when the user leaves the last cell in the table</li> <ul>
106 *
107 *
108 */
109 class SelectNextColumnCellAction extends AbstractAction {
110 public void actionPerformed(ActionEvent e) {
111 run();
112 }
113
114 public void run() {
115 int col = getSelectedColumn();
116 int row = getSelectedRow();
117 if (getCellEditor() != null) {
118 getCellEditor().stopCellEditing();
119 }
120
121 if (col == 0 && row < getRowCount() - 1) {
122 row++;
123 } else if (row < getRowCount() - 1) {
124 col = 0;
125 row++;
126 }
127 changeSelection(row, col, false, false);
128 }
129 }
130
131 /**
132 * Action to be run when the user navigates to the previous cell in the table, for instance by
133 * pressing Shift-TAB
134 *
135 */
136 class SelectPreviousColumnCellAction extends AbstractAction {
137
138 public void actionPerformed(ActionEvent e) {
139 int col = getSelectedColumn();
140 int row = getSelectedRow();
141 if (getCellEditor() != null) {
142 getCellEditor().stopCellEditing();
143 }
144
145 if (col == 0 && row == 0) {
146 // change nothing
147 } else if (row > 0) {
148 col = 0;
149 row--;
150 }
151 changeSelection(row, col, false, false);
152 }
153 }
154
155 /**
156 * creates the popup men
157 */
158 protected void createPopupMenu() {
159 popupMenu = new JPopupMenu();
160 ZoomToAction zoomToAction = new ZoomToAction();
161 Layer.listeners.add(zoomToAction);
162 getSelectionModel().addListSelectionListener(zoomToAction);
163 popupMenu.add(zoomToAction);
164 }
165
166 /**
167 * Replies the popup menu for this table
168 *
169 * @return the popup menu
170 */
171 protected JPopupMenu getPopUpMenu() {
172 if (popupMenu == null) {
173 createPopupMenu();
174 }
175 return popupMenu;
176 }
177
178 class PopupListener extends MouseAdapter {
179 @Override
180 public void mousePressed(MouseEvent e) {
181 showPopup(e);
182 }
183
184 @Override
185 public void mouseReleased(MouseEvent e) {
186 showPopup(e);
187 }
188
189 private void showPopup(MouseEvent e) {
190 if (e.isPopupTrigger()) {
191 getPopUpMenu().show(e.getComponent(), e.getX(), e.getY());
192 }
193 }
194 }
195
196 class ZoomToAction extends AbstractAction implements LayerChangeListener, ListSelectionListener {
197 public ZoomToAction() {
198 putValue(NAME, tr("Zoom to"));
199 putValue(SHORT_DESCRIPTION, tr("Zoom to primitive the first selected member refers to"));
200 updateEnabledState();
201 }
202
203 public void actionPerformed(ActionEvent e) {
204 if (! isEnabled())
205 return;
206 int rows[] = getSelectedRows();
207 if (rows == null || rows.length == 0)
208 return;
209 int row = rows[0];
210 OsmPrimitive primitive = getMemberTableModel().getReferredPrimitive(row);
211 layer.data.setSelected(primitive);
212 DataSet.fireSelectionChanged(layer.data.getSelected());
213 AutoScaleAction action = new AutoScaleAction("selection");
214 action.autoScale();
215 }
216
217 protected void updateEnabledState() {
218 if (Main.main == null || Main.main.getEditLayer() != layer) {
219 setEnabled(false);
220 putValue(SHORT_DESCRIPTION, tr("Zooming disabled because layer of this relation is not active"));
221 return;
222 }
223 if (getSelectedRowCount() == 0) {
224 setEnabled(false);
225 putValue(SHORT_DESCRIPTION, tr("Zooming disabled because there is no selected member"));
226 return;
227 }
228 setEnabled(true);
229 putValue(SHORT_DESCRIPTION, tr("Zoom to primitive the first selected member refers to"));
230 }
231
232 public void valueChanged(ListSelectionEvent e) {
233 updateEnabledState();
234 }
235
236 public void activeLayerChange(Layer oldLayer, Layer newLayer) {
237 updateEnabledState();
238 }
239
240 public void layerAdded(Layer newLayer) {
241 updateEnabledState();
242 }
243
244 public void layerRemoved(Layer oldLayer) {
245 updateEnabledState();
246 }
247 }
248
249 protected MemberTableModel getMemberTableModel() {
250 return (MemberTableModel) getModel();
251 }
252}
Note: See TracBrowser for help on using the repository browser.