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    }