001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.conflict.tags; 003 004import java.awt.event.ActionEvent; 005import java.awt.event.KeyEvent; 006 007import javax.swing.AbstractAction; 008import javax.swing.JComponent; 009import javax.swing.JTable; 010import javax.swing.KeyStroke; 011import javax.swing.ListSelectionModel; 012 013import org.openstreetmap.josm.gui.widgets.JosmComboBox; 014 015public class RelationMemberConflictResolverTable extends JTable implements MultiValueCellEditor.NavigationListener { 016 017 private SelectNextColumnCellAction selectNextColumnCellAction; 018 private SelectPreviousColumnCellAction selectPreviousColumnCellAction; 019 020 public RelationMemberConflictResolverTable(RelationMemberConflictResolverModel model) { 021 super(model, new RelationMemberConflictResolverColumnModel()); 022 build(); 023 } 024 025 protected final void build() { 026 setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); 027 setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 028 putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 029 030 // make ENTER behave like TAB 031 // 032 getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( 033 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "selectNextColumnCell"); 034 035 // install custom navigation actions 036 // 037 selectNextColumnCellAction = new SelectNextColumnCellAction(); 038 selectPreviousColumnCellAction = new SelectPreviousColumnCellAction(); 039 getActionMap().put("selectNextColumnCell", selectNextColumnCellAction); 040 getActionMap().put("selectPreviousColumnCell", selectPreviousColumnCellAction); 041 042 setRowHeight((int) new JosmComboBox<String>().getPreferredSize().getHeight()); 043 } 044 045 /** 046 * Action to be run when the user navigates to the next cell in the table, for instance by 047 * pressing TAB or ENTER. The action alters the standard navigation path from cell to cell: <ul> 048 * <li>it jumps over cells in the first column</li> <li>it automatically add a new empty row 049 * when the user leaves the last cell in the table</li></ul> 050 * 051 * 052 */ 053 class SelectNextColumnCellAction extends AbstractAction { 054 @Override 055 public void actionPerformed(ActionEvent e) { 056 run(); 057 } 058 059 public void run() { 060 int col = getSelectedColumn(); 061 int row = getSelectedRow(); 062 if (getCellEditor() != null) { 063 getCellEditor().stopCellEditing(); 064 } 065 066 if (col == 2 && row < getRowCount() - 1) { 067 row++; 068 } else if (row < getRowCount() - 1) { 069 col = 2; 070 row++; 071 } 072 changeSelection(row, col, false, false); 073 editCellAt(getSelectedRow(), getSelectedColumn()); 074 getEditorComponent().requestFocusInWindow(); 075 } 076 } 077 078 /** 079 * Action to be run when the user navigates to the previous cell in the table, for instance by 080 * pressing Shift-TAB 081 * 082 */ 083 class SelectPreviousColumnCellAction extends AbstractAction { 084 085 @Override 086 public void actionPerformed(ActionEvent e) { 087 run(); 088 } 089 090 public void run() { 091 int col = getSelectedColumn(); 092 int row = getSelectedRow(); 093 if (getCellEditor() != null) { 094 getCellEditor().stopCellEditing(); 095 } 096 097 if (col <= 0 && row <= 0) { 098 // change nothing 099 } else if (row > 0) { 100 col = 2; 101 row--; 102 } 103 changeSelection(row, col, false, false); 104 editCellAt(getSelectedRow(), getSelectedColumn()); 105 getEditorComponent().requestFocusInWindow(); 106 } 107 } 108 109 @Override 110 public void gotoNextDecision() { 111 selectNextColumnCellAction.run(); 112 } 113 114 @Override 115 public void gotoPreviousDecision() { 116 selectPreviousColumnCellAction.run(); 117 } 118}