001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.gui.conflict.tags; 003 004 import java.awt.event.ActionEvent; 005 import java.awt.event.KeyEvent; 006 007 import javax.swing.AbstractAction; 008 import javax.swing.JComponent; 009 import javax.swing.JTable; 010 import javax.swing.KeyStroke; 011 import javax.swing.ListSelectionModel; 012 013 import org.openstreetmap.josm.gui.widgets.JosmComboBox; 014 015 public 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 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().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 public void actionPerformed(ActionEvent e) { 055 run(); 056 } 057 058 public void run() { 059 int col = getSelectedColumn(); 060 int row = getSelectedRow(); 061 if (getCellEditor() != null) { 062 getCellEditor().stopCellEditing(); 063 } 064 065 if (col == 2 && row < getRowCount() - 1) { 066 row++; 067 } else if (row < getRowCount() - 1) { 068 col = 2; 069 row++; 070 } 071 changeSelection(row, col, false, false); 072 editCellAt(getSelectedRow(), getSelectedColumn()); 073 getEditorComponent().requestFocusInWindow(); 074 } 075 } 076 077 /** 078 * Action to be run when the user navigates to the previous cell in the table, for instance by 079 * pressing Shift-TAB 080 * 081 */ 082 class SelectPreviousColumnCellAction extends AbstractAction { 083 084 public void actionPerformed(ActionEvent e) { 085 run(); 086 } 087 088 public void run() { 089 int col = getSelectedColumn(); 090 int row = getSelectedRow(); 091 if (getCellEditor() != null) { 092 getCellEditor().stopCellEditing(); 093 } 094 095 if (col <= 0 && row <= 0) { 096 // change nothing 097 } else if (row > 0) { 098 col = 2; 099 row--; 100 } 101 changeSelection(row, col, false, false); 102 editCellAt(getSelectedRow(), getSelectedColumn()); 103 getEditorComponent().requestFocusInWindow(); 104 } 105 } 106 107 public void gotoNextDecision() { 108 selectNextColumnCellAction.run(); 109 } 110 111 public void gotoPreviousDecision() { 112 selectPreviousColumnCellAction.run(); 113 } 114 }