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