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 TagConflictResolverTable extends JTable implements MultiValueCellEditor.NavigationListener { 016 017 private SelectNextColumnCellAction selectNextColumnCellAction; 018 private SelectPreviousColumnCellAction selectPreviousColumnCellAction; 019 020 public TagConflictResolverTable(TagConflictResolverModel model) { 021 super(model, new TagConflictResolverColumnModel()); 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 ((MultiValueCellEditor)getColumnModel().getColumn(2).getCellEditor()).addNavigationListeners(this); 043 044 setRowHeight((int)new JosmComboBox().getPreferredSize().getHeight()); 045 } 046 047 /** 048 * Action to be run when the user navigates to the next cell in the table, for instance by 049 * pressing TAB or ENTER. The action alters the standard navigation path from cell to cell: <ul> 050 * <li>it jumps over cells in the first column</li> <li>it automatically add a new empty row 051 * when the user leaves the last cell in the table</li> <ul> 052 * 053 * 054 */ 055 class SelectNextColumnCellAction extends AbstractAction { 056 @Override 057 public void actionPerformed(ActionEvent e) { 058 run(); 059 } 060 061 public void run() { 062 int col = getSelectedColumn(); 063 int row = getSelectedRow(); 064 if (getCellEditor() != null) { 065 getCellEditor().stopCellEditing(); 066 } 067 068 if (col == 2 && row < getRowCount() - 1) { 069 row++; 070 } else if (row < getRowCount() - 1) { 071 col = 2; 072 row++; 073 } 074 changeSelection(row, col, false, false); 075 editCellAt(getSelectedRow(), getSelectedColumn()); 076 getEditorComponent().requestFocusInWindow(); 077 } 078 } 079 080 /** 081 * Action to be run when the user navigates to the previous cell in the table, for instance by 082 * pressing Shift-TAB 083 * 084 */ 085 class SelectPreviousColumnCellAction extends AbstractAction { 086 087 @Override 088 public void actionPerformed(ActionEvent e) { 089 run(); 090 } 091 092 public void run() { 093 int col = getSelectedColumn(); 094 int row = getSelectedRow(); 095 if (getCellEditor() != null) { 096 getCellEditor().stopCellEditing(); 097 } 098 099 if (col <= 0 && row <= 0) { 100 // change nothing 101 } else if (row > 0) { 102 col = 2; 103 row--; 104 } 105 changeSelection(row, col, false, false); 106 editCellAt(getSelectedRow(), getSelectedColumn()); 107 getEditorComponent().requestFocusInWindow(); 108 } 109 } 110 111 @Override 112 public void gotoNextDecision() { 113 selectNextColumnCellAction.run(); 114 } 115 116 @Override 117 public void gotoPreviousDecision() { 118 selectPreviousColumnCellAction.run(); 119 } 120}