Search in sources :

Example 1 with ArrowFocusOption

use of CCDD.CcddConstants.ArrowFocusOption in project CCDD by nasa.

the class CcddKeyboardHandler method setKeyboardHandler.

/**
 ********************************************************************************************
 * Adjust the handling of Enter and space key inputs in order to activate dialog controls, and
 * keyboard focus changes in order to use the arrow keys like Tab keys
 ********************************************************************************************
 */
private void setKeyboardHandler() {
    // Get the keyboard focus manager
    focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
    // Listen for key presses
    focusManager.addKeyEventDispatcher(new KeyEventDispatcher() {

        boolean isShowMacros = false;

        Timer releaseTimer = null;

        /**
         ************************************************************************************
         * Alter the response to the Enter key to act like the Space key to activate button and
         * check box controls, and the arrow keys so as to mimic the Tab and Shift+Tab keys,
         * unless the key press originates within a table or combo box. For a tabbed pane the
         * left/right arrows are left unchanged so that these are used for traversing the
         * tabbed panes, but the down and up arrows act like Tab and Shift+Tab respectively
         ************************************************************************************
         */
        @Override
        public boolean dispatchKeyEvent(final KeyEvent ke) {
            // Flag that indicates if the key event has been handled by this method (true) or
            // that it still needs to be processed (false)
            boolean handled = false;
            // Get a reference to the component with the focus in order to shorten the
            // subsequent calls
            Component comp = ke.getComponent();
            // pressed
            if (ke.getID() == KeyEvent.KEY_PRESSED && !ke.isControlDown() && !ke.isShiftDown() && !ke.isAltDown()) {
                // Check if the Enter key is pressed
                if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
                    // Check if this is a button
                    if (comp instanceof JButton) {
                        // Activate the control (same as if Space key is pressed)
                        ((AbstractButton) comp).doClick();
                        handled = true;
                    } else // Check if this is a table
                    if (comp instanceof CcddJTableHandler || (comp.getParent() instanceof CcddJTableHandler && !(comp instanceof JComboBox))) {
                        // Handle the Enter key in the table
                        handled = tableEditCellHandler(comp);
                    }
                } else // Check if the space key is pressed
                if (ke.getKeyCode() == KeyEvent.VK_SPACE) {
                    // Check if this is a table
                    if (comp instanceof CcddJTableHandler) {
                        // Handle the space key in the table
                        handled = tableEditCellHandler(comp);
                    } else // Check this is a combo box in a table
                    if (comp.getParent() instanceof CcddJTableHandler && comp instanceof JComboBox) {
                        // Ignore the key press
                        handled = true;
                    }
                } else // produce a character and is not a modifier; this covers the arrow keys)
                if (ke.isActionKey()) {
                    // Assume that the default handling will be used with an arrow key
                    ArrowFocusOption arrowResponse = USE_DEFAULT_HANDLER;
                    // Check if the focus is on a tabbed pane's tab or on a slider
                    if (comp instanceof JTabbedPane || comp instanceof JSlider) {
                        // The left and right arrows traverse the tabs, and the up and down
                        // arrows behave like (Shift+)Tab
                        arrowResponse = HANDLE_UP_AND_DOWN_ARROWS;
                    } else // Check if the focus is in a text field within a table
                    if ((comp instanceof JTextField || comp instanceof JTextArea) && comp.getParent() instanceof CcddJTableHandler) {
                        // The up and down arrows are ignored. This prevents accidently exiting
                        // edit mode on a table cell and losing any changes
                        arrowResponse = IGNORE_UP_AND_DOWN_ARROWS;
                    } else // button, or check box
                    if (comp instanceof JButton || comp instanceof JRadioButton || comp instanceof JCheckBox) {
                        // The up and left arrow keys behave as Shift+Tab, and the down and
                        // right arrow keys behave as Tab
                        arrowResponse = HANDLE_ALL_ARROWS;
                    } else // Check if the focus is within a table
                    if (comp instanceof CcddJTableHandler) {
                        // Get the reference to the table with the focus
                        CcddJTableHandler table = (CcddJTableHandler) comp;
                        // Get the row containing the cell with the focus in order to shorten
                        // the subsequent calls
                        int row = table.getSelectedRow();
                        // Check if the table has no rows
                        if (row == -1) {
                            // Treat the table as if it wasn't there; i.e., the left and right
                            // arrows behave like the (Shift+)Tab key
                            arrowResponse = HANDLE_ALL_ARROWS;
                        } else // Check if the table has only a single row
                        if (table.getRowCount() == 1) {
                            // The up and down arrows behave like the (Shift+)Tab key
                            arrowResponse = HANDLE_UP_AND_DOWN_ARROWS;
                        } else // Check if the top row is selected
                        if (row == 0) {
                            // The up arrow behaves like the Shift+Tab key
                            arrowResponse = HANDLE_UP_ARROW;
                        } else // Check if the bottom row is selected
                        if (row == table.getRowCount() - 1) {
                            // The down arrow behaves like the Tab key
                            arrowResponse = HANDLE_DOWN_ARROW;
                        }
                    }
                    // Check if the key pressed is an arrow key and if so adjust its behavior
                    switch(ke.getKeyCode()) {
                        case KeyEvent.VK_LEFT:
                        case KeyEvent.VK_KP_LEFT:
                            // Check if the left arrow key should be handled
                            if (arrowResponse == HANDLE_ALL_ARROWS) {
                                // Treat the left arrow as a Shift+Tab key and indicate that
                                // the key has been handled
                                focusManager.focusPreviousComponent();
                                handled = true;
                            }
                            break;
                        case KeyEvent.VK_UP:
                        case KeyEvent.VK_KP_UP:
                            // Check if the up arrow key should be handled
                            if (arrowResponse == HANDLE_ALL_ARROWS || arrowResponse == HANDLE_UP_ARROW || arrowResponse == HANDLE_UP_AND_DOWN_ARROWS) {
                                // Treat the up arrow as a Shift+Tab key and indicate that the
                                // key has been handled
                                focusManager.focusPreviousComponent();
                                handled = true;
                            } else // Check if the up arrow should be ignored
                            if (arrowResponse == IGNORE_UP_AND_DOWN_ARROWS) {
                                // Indicate that the key has been handled
                                handled = true;
                            }
                            break;
                        case KeyEvent.VK_RIGHT:
                        case KeyEvent.VK_KP_RIGHT:
                            // Check if the right arrow key should be handled
                            if (arrowResponse == HANDLE_ALL_ARROWS) {
                                // Treat the right arrow as a Tab key and indicate that the key
                                // has been handled
                                focusManager.focusNextComponent();
                                handled = true;
                            }
                            break;
                        case KeyEvent.VK_DOWN:
                        case KeyEvent.VK_KP_DOWN:
                            // Check if the down arrow key should be handled
                            if (arrowResponse == HANDLE_ALL_ARROWS || arrowResponse == HANDLE_DOWN_ARROW || arrowResponse == HANDLE_UP_AND_DOWN_ARROWS) {
                                // Treat the down arrow as a Tab key and indicate that the key
                                // has been handled
                                focusManager.focusNextComponent();
                                handled = true;
                            } else // Check if the down arrow should be ignored
                            if (arrowResponse == IGNORE_UP_AND_DOWN_ARROWS) {
                                // Indicate that the key has been handled
                                handled = true;
                            }
                            break;
                    }
                }
            } else // Check if the Ctrl key is pressed
            if (ke.getID() == KeyEvent.KEY_PRESSED && ke.isControlDown() && !ke.isAltDown()) {
                // Check if the Ctrl-Z key is pressed
                if (ke.getKeyCode() == KeyEvent.VK_Z) {
                    // Get the currently active undo manager
                    final CcddUndoManager undoManager = getActiveUndoManager();
                    // Check if an active undo manager was found
                    if (undoManager != null) {
                        // Create a runnable object to be executed
                        SwingUtilities.invokeLater(new Runnable() {

                            /**
                             ****************************************************************
                             * Execute after all pending Swing events are finished so that the
                             * events occur in the desired order
                             ****************************************************************
                             */
                            @Override
                            public void run() {
                                // Undo the previous edit action
                                undoManager.undo();
                                // associated with the component
                                if (editPnlHandler != null) {
                                    // Update the data field background colors
                                    editPnlHandler.setFieldBackgound();
                                }
                                // Force the component to repaint so that the change is visible
                                ke.getComponent().repaint();
                            }
                        });
                        // Set the flag to indicate this key press was handled
                        handled = true;
                    }
                } else // Check if the Ctrl-Y key is pressed
                if (ke.getKeyCode() == KeyEvent.VK_Y) {
                    // Get the currently active undo manager
                    final CcddUndoManager undoManager = getActiveUndoManager();
                    // Check if an active undo manager was found
                    if (undoManager != null) {
                        // Create a runnable object to be executed
                        SwingUtilities.invokeLater(new Runnable() {

                            /**
                             ****************************************************************
                             * Execute after all pending Swing events are finished so that the
                             * events occur in the desired order
                             ****************************************************************
                             */
                            @Override
                            public void run() {
                                // Redo the previous undo action
                                undoManager.redo();
                                // associated with the component
                                if (editPnlHandler != null) {
                                    // Update the data field background colors
                                    editPnlHandler.setFieldBackgound();
                                }
                                // Force the component to repaint so that the change is visible
                                ke.getComponent().repaint();
                            }
                        });
                        // Set the flag to indicate this key press was handled
                        handled = true;
                    }
                } else // focus
                if (ke.getKeyCode() == KeyEvent.VK_F && ccddMain.getMainFrame().isFocused()) {
                    // Open the event log search dialog
                    ccddMain.showSearchDialog(SearchDialogType.LOG, null, ccddMain.getSessionEventLog(), ccddMain.getMainFrame());
                    // Set the flag to indicate this key press was handled
                    handled = true;
                } else // insertion
                if (ke.getKeyCode() == KeyEvent.VK_S) {
                    // Get the table editor dialog with the focus
                    CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
                    // contain a combo box
                    if (editorDialog != null && !(comp instanceof JComboBox)) {
                        // Check if a cell in the table is being edited
                        if (editorDialog.getTableEditor().getTable().isEditing()) {
                            // Insert the structure name chosen by the user into the text field
                            // at the current text insertion point
                            dataTypeHandler.insertDataTypeName((JFrame) editorDialog, (JTextArea) comp, true, editorDialog.getTableEditor().getValidDataTypes().toArray(new String[0]));
                        }
                    } else // Check if the data type editor editing is active
                    if (SwingUtilities.getWindowAncestor(comp) instanceof CcddDataTypeEditorDialog && modalTable.isEditing()) {
                        // Get the row and column being edited in the table, and the contents
                        // of the edited row's base data type
                        int row = modalTable.getEditingRow();
                        int column = modalTable.convertColumnIndexToModel(modalTable.getEditingColumn());
                        String baseType = modalTable.getValueAt(row, DataTypeEditorColumnInfo.BASE_TYPE.ordinal()).toString();
                        // base data type is empty or a pointer
                        if ((column == DataTypeEditorColumnInfo.USER_NAME.ordinal() || column == DataTypeEditorColumnInfo.C_NAME.ordinal()) && (baseType.isEmpty() || baseType.equals(BaseDataTypeInfo.POINTER.getName()))) {
                            // Insert the structure name chosen by the user into the text field
                            // at the current text insertion point
                            dataTypeHandler.insertDataTypeName((JDialog) SwingUtilities.getWindowAncestor(comp), (JTextArea) comp, false, null);
                        }
                    } else // Check if the macro editor editing is active
                    if (SwingUtilities.getWindowAncestor(comp) instanceof CcddMacroEditorDialog && modalTable.isEditing()) {
                        // Insert the structure name chosen by the user into the text field at
                        // the current text insertion point
                        dataTypeHandler.insertDataTypeName((JDialog) SwingUtilities.getWindowAncestor(comp), (JTextArea) comp, true, null);
                    }
                    // Set the flag to indicate this key press was handled
                    handled = true;
                } else // and expansion
                if (ke.getKeyCode() == KeyEvent.VK_M) {
                    // Check if the shift key is also pressed (Ctrl-Shift-M)
                    if (ke.isShiftDown()) {
                        // Check if the macros aren't already expanded
                        if (!isShowMacros) {
                            // Get the table editor dialog with the focus
                            CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
                            // Check if a table editor dialog has the focus
                            if (editorDialog != null) {
                                // Replace the macro names with their corresponding values in
                                // the currently selected table in this editor
                                editorDialog.getTableEditor().expandMacros(true, true);
                                isShowMacros = true;
                            } else // Check if this is the macro editor
                            if (SwingUtilities.getWindowAncestor(comp) instanceof CcddMacroEditorDialog) {
                                // Expand the macros in the macro value column
                                ((CcddMacroEditorDialog) SwingUtilities.getWindowAncestor(comp)).expandMacros(true);
                                isShowMacros = true;
                            }
                        }
                    } else // The shift key isn't pressed (Ctrl-M only). Check if this is a table cell
                    if (comp.getParent() instanceof CcddJTableHandler) {
                        // Get the table editor dialog with the focus
                        CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
                        // doesn't contain a combo box
                        if (editorDialog != null && !(comp instanceof JComboBox)) {
                            // Get references to shorten subsequent calls
                            CcddTableEditorHandler editor = editorDialog.getTableEditor();
                            CcddJTableHandler table = editor.getTable();
                            // Check if a cell in the table is being edited
                            if (table.isEditing()) {
                                // Get the index of the column being edited in model
                                // coordinates
                                int column = table.convertColumnIndexToModel(table.getEditingColumn());
                                // Get the input type for the column being edited
                                InputDataType inputType = editor.getTableTypeDefinition().getInputTypes()[column];
                                // Insert the macro name chosen by the user into the text
                                // component at the current text insertion point
                                macroHandler.insertMacroName(editorDialog, (JTextComponent) comp, inputType, editor.getValidDataTypes());
                            }
                        } else // column is being edited
                        if (SwingUtilities.getWindowAncestor(comp) instanceof CcddMacroEditorDialog && modalTable.isEditing() && modalTable.convertColumnIndexToModel(modalTable.getEditingColumn()) == MacroEditorColumnInfo.VALUE.ordinal()) {
                            // Insert the macro name chosen by the user into the text component
                            // at the current text insertion point
                            macroHandler.insertMacroName((JDialog) SwingUtilities.getWindowAncestor(comp), (JTextComponent) comp, InputDataType.TEXT, null);
                        }
                    }
                    // Set the flag to indicate this key press was handled
                    handled = true;
                } else // Check if the Ctrl-E key is pressed while the focus is on a tree
                if (ke.getKeyCode() == KeyEvent.VK_E && comp instanceof CcddCommonTreeHandler) {
                    // Expand/collapse the selected node(s)
                    ((CcddCommonTreeHandler) comp).expandCollapseSelectedNodes();
                }
            } else // text
            if (ke.getID() == KeyEvent.KEY_PRESSED && ke.isAltDown() && !ke.isControlDown() && ke.getKeyCode() == KeyEvent.VK_ENTER && comp.getParent() instanceof CcddJTableHandler && comp instanceof JTextArea) {
                // Get the table editor dialog with the focus
                CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
                // Check if a table editor dialog has the focus
                if (editorDialog != null) {
                    // Check if a cell in the table is being edited
                    if (editorDialog.getTableEditor().getTable().isEditing()) {
                        JTextComponent textComp = (JTextComponent) comp;
                        // Get the cell's current value
                        String cellValue = textComp.getText();
                        // Get the starting position of the selected text
                        int caretPosn = textComp.getSelectionStart();
                        // Replace the currently selected text with a line feed
                        textComp.setText(cellValue.substring(0, caretPosn) + "\n" + cellValue.substring(textComp.getSelectionEnd()));
                        // Position the cursor after the newly inserted line feed
                        textComp.setCaretPosition(caretPosn + 1);
                    }
                }
            }
            // key sequence is no longer active
            if (isShowMacros && ke.getID() == KeyEvent.KEY_RELEASED && ke.getKeyCode() == KeyEvent.VK_M) {
                // Check if the key release action timer doesn't exist
                if (releaseTimer == null) {
                    // Create the key release action timer. In Linux if a key is held it
                    // generates continuous key release events. This timer is used to ignore
                    // the key release events that are close together time-wise
                    releaseTimer = new Timer(75, new ActionListener() {

                        /**
                         ********************************************************************
                         * Handle the key release action
                         ********************************************************************
                         */
                        @Override
                        public void actionPerformed(ActionEvent ae) {
                            // Get the table editor dialog with the focus
                            CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
                            // Check if a table editor dialog has the focus
                            if (editorDialog != null) {
                                // Restore the macro names in the currently selected table in
                                // this editor
                                editorDialog.getTableEditor().expandMacros(false, true);
                                isShowMacros = false;
                            } else // Check if this is the macro editor
                            if (SwingUtilities.getWindowAncestor(modalTable) instanceof CcddMacroEditorDialog) {
                                // Expand the macros in the macro value column
                                ((CcddMacroEditorDialog) SwingUtilities.getWindowAncestor(modalTable)).expandMacros(false);
                                isShowMacros = false;
                            }
                        }
                    });
                    // Allow the timer to send only a single expiration event
                    releaseTimer.setRepeats(false);
                }
                // (Re)start the key release action timer
                releaseTimer.restart();
                // Set the flag to indicate this key press was handled
                handled = true;
            }
            return handled;
        }
    });
}
Also used : JTextArea(javax.swing.JTextArea) JRadioButton(javax.swing.JRadioButton) ActionEvent(java.awt.event.ActionEvent) ArrowFocusOption(CCDD.CcddConstants.ArrowFocusOption) JTabbedPane(javax.swing.JTabbedPane) JButton(javax.swing.JButton) JTextComponent(javax.swing.text.JTextComponent) JTextField(javax.swing.JTextField) KeyEvent(java.awt.event.KeyEvent) JFrame(javax.swing.JFrame) JSlider(javax.swing.JSlider) Component(java.awt.Component) JTextComponent(javax.swing.text.JTextComponent) InputDataType(CCDD.CcddConstants.InputDataType) JComboBox(javax.swing.JComboBox) KeyEventDispatcher(java.awt.KeyEventDispatcher) JCheckBox(javax.swing.JCheckBox) Timer(javax.swing.Timer) ActionListener(java.awt.event.ActionListener) JDialog(javax.swing.JDialog)

Aggregations

ArrowFocusOption (CCDD.CcddConstants.ArrowFocusOption)1 InputDataType (CCDD.CcddConstants.InputDataType)1 Component (java.awt.Component)1 KeyEventDispatcher (java.awt.KeyEventDispatcher)1 ActionEvent (java.awt.event.ActionEvent)1 ActionListener (java.awt.event.ActionListener)1 KeyEvent (java.awt.event.KeyEvent)1 JButton (javax.swing.JButton)1 JCheckBox (javax.swing.JCheckBox)1 JComboBox (javax.swing.JComboBox)1 JDialog (javax.swing.JDialog)1 JFrame (javax.swing.JFrame)1 JRadioButton (javax.swing.JRadioButton)1 JSlider (javax.swing.JSlider)1 JTabbedPane (javax.swing.JTabbedPane)1 JTextArea (javax.swing.JTextArea)1 JTextField (javax.swing.JTextField)1 Timer (javax.swing.Timer)1 JTextComponent (javax.swing.text.JTextComponent)1