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 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 public void actionPerformed(ActionEvent e) { 057 run(); 058 } 059 060 public void run() { 061 int col = getSelectedColumn(); 062 int row = getSelectedRow(); 063 if (getCellEditor() != null) { 064 getCellEditor().stopCellEditing(); 065 } 066 067 if (col == 2 && row < getRowCount() - 1) { 068 row++; 069 } else if (row < getRowCount() - 1) { 070 col = 2; 071 row++; 072 } 073 changeSelection(row, col, false, false); 074 editCellAt(getSelectedRow(), getSelectedColumn()); 075 getEditorComponent().requestFocusInWindow(); 076 } 077 } 078 079 /** 080 * Action to be run when the user navigates to the previous cell in the table, for instance by 081 * pressing Shift-TAB 082 * 083 */ 084 class SelectPreviousColumnCellAction extends AbstractAction { 085 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 public void gotoNextDecision() { 110 selectNextColumnCellAction.run(); 111 } 112 113 public void gotoPreviousDecision() { 114 selectPreviousColumnCellAction.run(); 115 } 116 }