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    }