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}