Search in sources :

Example 1 with UndoableTextArea

use of CCDD.CcddUndoHandler.UndoableTextArea in project CCDD by nasa.

the class CcddKeyboardHandler method getActiveUndoManager.

/**
 ********************************************************************************************
 * Get the active component's undo manager
 *
 * @return The active undo manager; null if no undo manager is active or no editor has focus
 ********************************************************************************************
 */
private CcddUndoManager getActiveUndoManager() {
    CellEditor cellEditor = null;
    CcddUndoManager undoManager = null;
    editPnlHandler = null;
    // Check if a modal dialog is active
    if (modalUndoManager != null) {
        // Set the undo manager to the modal dialog's undo manager
        undoManager = modalUndoManager;
        // Check if a modal table is active
        if (modalTable != null) {
            // Get the cell editor for the modal table
            cellEditor = modalTable.getCellEditor();
        }
        // Get a reference to the group manager dialog to shorten subsequent calls
        CcddGroupManagerDialog groupManager = ccddMain.getGroupManager();
        // Check if the group manager is open and has focus
        if (groupManager != null && groupManager.isFocused()) {
            // Get the group manager's editor panel handler
            editPnlHandler = groupManager.getEditorPanelHandler();
        }
    } else // No modal undo manager is active
    {
        // Step through each open table editor dialog
        for (CcddTableEditorDialog editorDialog : ccddMain.getTableEditorDialogs()) {
            // Check if this editor dialog has the keyboard focus
            if (editorDialog.isFocused()) {
                // Get the undo manager, cell editor, and editor panel handler for the active
                // table editor
                undoManager = editorDialog.getTableEditor().getFieldPanelUndoManager();
                cellEditor = editorDialog.getTableEditor().getTable().getCellEditor();
                editPnlHandler = editorDialog.getTableEditor().getInputFieldPanelHandler();
            }
            // Check if an undo manager is active
            if (undoManager != null) {
                // Stop searching
                break;
            }
        }
        // Get a reference to the type editor dialog to shorten subsequent calls
        CcddTableTypeEditorDialog editorDialog = ccddMain.getTableTypeEditor();
        // Check if no table undo manager is applicable and the table type editor is open
        if (undoManager == null && editorDialog != null) {
            // Check if the table type editor has the keyboard focus
            if (editorDialog.isFocused()) {
                // Get the undo manager, cell editor, and editor panel handler for the active
                // table type editor
                undoManager = editorDialog.getTypeEditor().getFieldPanelUndoManager();
                cellEditor = editorDialog.getTypeEditor().getTable().getCellEditor();
                editPnlHandler = editorDialog.getTypeEditor().getInputFieldPanelHandler();
            }
        }
        // Get a reference to the data field table editor dialog to shorten subsequent calls
        CcddFieldTableEditorDialog fieldEditor = ccddMain.getFieldTableEditor();
        // editor is open, and the editor has focus
        if (undoManager == null && fieldEditor != null && fieldEditor.isFocused()) {
            // Get the undo manager and cell editor for the data field table editor
            undoManager = fieldEditor.getTable().getUndoManager();
            cellEditor = fieldEditor.getTable().getCellEditor();
        }
        // Get a reference to the script manager dialog to shorten subsequent calls
        CcddScriptManagerDialog scriptManager = ccddMain.getScriptManager();
        // open, and the editor has focus
        if (undoManager == null && scriptManager != null && scriptManager.isFocused()) {
            // Get the undo manager and cell editor for the script manager
            undoManager = ccddMain.getScriptHandler().getAssociationsTable().getUndoManager();
            cellEditor = ccddMain.getScriptHandler().getAssociationsTable().getCellEditor();
        }
    }
    // Check if a table cell is actively being edited
    if (cellEditor != null) {
        // Incorporate any cell changes and terminate editing
        cellEditor.stopCellEditing();
    } else // No table cell is being edited
    {
        // Get the current owner of the keyboard focus
        Component focusOwner = focusManager.getFocusOwner();
        // Check if the focus is in an edit panel's description or data field
        if (focusOwner != null && (focusOwner instanceof UndoableTextField || focusOwner instanceof UndoableTextArea || focusOwner instanceof UndoableCheckBox)) {
            // Check if the focus owner is a text field data field
            if (focusOwner instanceof UndoableTextField) {
                // Force the text to update so that an undo command starts with this field
                ((JTextField) focusOwner).setText(((JTextField) focusOwner).getText());
            }
            // Clear the keyboard focus so that the current data field value is registered as
            // an edit
            focusManager.clearGlobalFocusOwner();
        }
    }
    return undoManager;
}
Also used : UndoableCheckBox(CCDD.CcddUndoHandler.UndoableCheckBox) CellEditor(javax.swing.CellEditor) UndoableTextArea(CCDD.CcddUndoHandler.UndoableTextArea) UndoableTextField(CCDD.CcddUndoHandler.UndoableTextField) Component(java.awt.Component) JTextComponent(javax.swing.text.JTextComponent) JTextField(javax.swing.JTextField)

Example 2 with UndoableTextArea

use of CCDD.CcddUndoHandler.UndoableTextArea in project CCDD by nasa.

the class CcddLinkManagerHandler method initialize.

/**
 ********************************************************************************************
 * Create the variable link manager dialog
 *
 * @param availableRates
 *            array of sample rates available to this stream
 ********************************************************************************************
 */
private void initialize(String[] availableRates) {
    isNodeSelectionChanging = false;
    // Create borders for the dialog components
    border = BorderFactory.createCompoundBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.LIGHT_GRAY, Color.GRAY), BorderFactory.createEmptyBorder(ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing()));
    emptyBorder = BorderFactory.createEmptyBorder();
    selectedLink = null;
    currentLinks = new ArrayList<String[]>();
    // Set the initial layout manager characteristics
    GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing(), ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() / 2, 0, 0), 0, 0);
    // Add an undo edit manager
    undoManager = new CcddUndoManager() {

        /**
         ************************************************************************************
         * Update the change indicator if the link manager has changed
         ************************************************************************************
         */
        @Override
        protected void ownerHasChanged() {
            linkDialog.updateChangeIndicator();
        }
    };
    // Create the undo handler for the components with undoable actions. Disable storage of
    // edit actions during dialog creation
    undoHandler = new CcddUndoHandler(undoManager);
    pathSelect = undoHandler.new UndoableTreePathSelection();
    undoHandler.setAllowUndo(false);
    // Build the link tree
    linkTree = new CcddLinkTreeHandler(ccddMain, undoHandler, rateName, ccddMain.getMainFrame()) {

        /**
         ************************************************************************************
         * Respond to changes in selection of a node in the link tree
         ************************************************************************************
         */
        @Override
        protected void updateTableSelection() {
            // Check that a node selection change is not in progress
            if (!isNodeSelectionChanging) {
                // Set the flag to prevent link tree updates
                isNodeSelectionChanging = true;
                // Deselect any nodes that are disabled
                clearDisabledNodes();
                // Check if a link was selected
                if (selectedLink != null) {
                    // Store the description with the previous link
                    selectedLink.setDescription(descriptionFld.getText().trim());
                }
                // Update the description field text so that it can be undone/redone. The focus
                // change, which is usually used to perform the update, occurs after the node
                // selection edit and would cause the wrong description field to be changed
                descriptionFld.updateText(true);
                // Get the name of the selected link(s)
                String[] selected = getTopLevelSelectedNodeNames();
                // If a single link is selected then set the selected link, enable and populate
                // the description, rate, and size in bytes fields; otherwise clear the
                // selected link, disable and clear the description, rate, and size in bytes
                // fields
                setLinkAndFields(selected.length == 1 ? selected[0] : null, selected.length != 0);
                // the undo/redo stack
                if (undoHandler.isAllowUndo()) {
                    // Add the node path selection change to the undo/redo stack
                    pathSelect.selectTreePath(getSelectedPaths());
                }
                // Reset the flag to allow link tree updates
                isNodeSelectionChanging = false;
            }
        }
    };
    // Set the link tree reference in the undo handler so that tree edits can be undone/redone
    undoHandler.setTree(linkTree);
    // Store the initial link definitions. These are filtered so that only those with the same
    // data stream rate are represented
    updateCommittedLinks();
    // Create panels to hold the components of the dialog
    managerPnl = new JPanel(new GridBagLayout());
    JPanel titlePnl = new JPanel(new GridBagLayout());
    JPanel treePnl = new JPanel(new GridBagLayout());
    JPanel infoPnl = new JPanel(new GridBagLayout());
    JPanel descPnl = new JPanel(new GridBagLayout());
    JPanel rateAndSizePnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
    JPanel rateSelectPnl = new JPanel(new GridBagLayout());
    managerPnl.setBorder(emptyBorder);
    titlePnl.setBorder(emptyBorder);
    treePnl.setBorder(emptyBorder);
    infoPnl.setBorder(BorderFactory.createEtchedBorder());
    descPnl.setBorder(emptyBorder);
    rateSelectPnl.setBorder(emptyBorder);
    rateSelectPnl.setBorder(emptyBorder);
    // Create the link manager dialog labels and fields
    JLabel dlgLabel = new JLabel("Assign variables to links");
    dlgLabel.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    titlePnl.add(dlgLabel, gbc);
    // Add the upper panel components to the dialog panel
    managerPnl.add(titlePnl, gbc);
    // Initialize the currently selected rate to 1 Hz if present in the list of available
    // rates; otherwise choose the first rate if any rates exist, and if none exist set the
    // rate to a dummy value
    selectedRate = Arrays.asList(availableRates).contains("1") ? "1" : (availableRates.length != 0 ? CcddUtilities.removeHTMLTags(availableRates[0]) : "0");
    // Build the variable tree that shows tables and their variables for the selected rate. Use
    // the first rate in the available rates array to determine which variables to display in
    // the tree, or, if none, create the tree showing no variables
    variableTree = new CcddTableTreeHandler(ccddMain, new CcddGroupHandler(ccddMain, undoHandler, ccddMain.getMainFrame()), TableTreeType.INSTANCE_STRUCTURES_WITH_PRIMITIVES_AND_RATES, rateName, selectedRate, linkTree.getLinkVariables(null), ccddMain.getMainFrame()) {

        /**
         ************************************************************************************
         * Respond to changes in selection of a node in the variable tree
         ************************************************************************************
         */
        @Override
        protected void updateTableSelection() {
            // Check that a node selection change is not in progress
            if (!isNodeSelectionChanging) {
                // Select the associated link in the link tree if a linked variable is selected
                // in the variable tree. Note that below any linked variables are deselected,
                // so this call must occur first
                selectLinkByVariable();
                // Set the flag to prevent variable tree updates
                isNodeSelectionChanging = true;
                // Deselect any nodes that are disabled
                clearDisabledNodes();
                // Deselect any nodes that don't represent a table or the level immediately
                // above the table level
                clearNonTableNodes(1);
                // Reset the flag to allow variable tree updates
                isNodeSelectionChanging = false;
            }
        }

        /**
         ************************************************************************************
         * Override building the table tree in order to apply the rate filter and change the
         * instances node name
         ************************************************************************************
         */
        @Override
        protected void buildTableTree(Boolean isExpanded, String rateName, String rateFilter, Component parent) {
            super.buildTableTree(isExpanded, rateName, rateFilter, parent);
            // Rename the instances node. Indicate that the node changed so that the tree
            // redraws the name
            getInstancesNode().setUserObject("Structures & Variables");
            ((DefaultTreeModel) getModel()).nodeChanged(getInstancesNode());
            // Clean up the links following rebuilding the tree
            variableTree = this;
            cleanUpLinks(null);
        }
    };
    // Add the title panel components to the dialog panel
    managerPnl.add(titlePnl, gbc);
    // Create a table tree panel and add it to another panel (in order to control spacing)
    gbc.insets.top = 0;
    gbc.insets.bottom = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
    gbc.weighty = 1.0;
    treePnl.add(variableTree.createTreePanel("Variables", TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION, ccddMain.getMainFrame()), gbc);
    gbc.insets.top = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
    gbc.insets.bottom = 0;
    // Create a split pane containing the variable tree in the left pane and the link tree in
    // the right pane and add it to the panel. The arrow button panel is used as the split pane
    // divider
    gbc.insets.left = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing();
    gbc.insets.right = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing();
    gbc.gridy++;
    managerPnl.add(new CustomSplitPane(treePnl, linkTree.createTreePanel("Links", TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION), createArrowButtonPanel(), JSplitPane.HORIZONTAL_SPLIT), gbc);
    // Create the link description label
    JLabel descriptionLbl = new JLabel("Description");
    descriptionLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    descriptionLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
    gbc.insets.top = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
    gbc.insets.left = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() / 2;
    gbc.insets.bottom = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
    gbc.insets.right = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() / 2;
    gbc.weighty = 0.0;
    descPnl.add(descriptionLbl, gbc);
    // Create the link description input field
    descriptionFld = undoHandler.new UndoableTextArea("", 3, 1);
    descriptionFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
    descriptionFld.setEditable(false);
    descriptionFld.setLineWrap(true);
    descriptionFld.setWrapStyleWord(true);
    descriptionFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
    descriptionFld.setBackground(ModifiableColorInfo.INPUT_DISABLE_BACK.getColor());
    descriptionFld.setBorder(emptyBorder);
    descriptionFld.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
    descriptionFld.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
    // Add a listener to detect addition or deletion of text in the input field
    descriptionFld.getDocument().addDocumentListener(new DocumentListener() {

        /**
         ************************************************************************************
         * Update the change indicator when text is added
         ************************************************************************************
         */
        @Override
        public void insertUpdate(DocumentEvent de) {
            linkDialog.updateChangeIndicator();
        }

        /**
         ************************************************************************************
         * Update the change indicator when text is removed
         ************************************************************************************
         */
        @Override
        public void removeUpdate(DocumentEvent de) {
            linkDialog.updateChangeIndicator();
        }

        /**
         ************************************************************************************
         * Handle updates to a attribute change (unused)
         ************************************************************************************
         */
        @Override
        public void changedUpdate(DocumentEvent de) {
        }
    });
    descScrollPane = new JScrollPane(descriptionFld);
    descScrollPane.setBackground(ModifiableColorInfo.INPUT_DISABLE_BACK.getColor());
    descScrollPane.setBorder(border);
    // Add the description field to the dialog panel
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridy++;
    descPnl.add(descScrollPane, gbc);
    // Add the description panel to the link information panel
    gbc.gridy++;
    infoPnl.add(descPnl, gbc);
    // Create the link rate labels and fields
    JLabel rateLbl = new JLabel("Link rate (Hz):");
    rateLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    rateLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
    rateAndSizePnl.add(rateLbl);
    updateRateFld = new JTextField(2);
    updateRateFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
    updateRateFld.setEditable(false);
    updateRateFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
    updateRateFld.setBackground(ModifiableColorInfo.INPUT_DISABLE_BACK.getColor());
    updateRateFld.setBorder(border);
    updateRateFld.setHorizontalAlignment(SwingConstants.CENTER);
    rateAndSizePnl.add(updateRateFld);
    JLabel bytesLbl = new JLabel("   Size in bytes:");
    bytesLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    bytesLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
    rateAndSizePnl.add(bytesLbl);
    sizeInBytesFld = new JTextField(2);
    sizeInBytesFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
    sizeInBytesFld.setEditable(false);
    sizeInBytesFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
    sizeInBytesFld.setBackground(ModifiableColorInfo.INPUT_DISABLE_BACK.getColor());
    sizeInBytesFld.setBorder(border);
    sizeInBytesFld.setHorizontalAlignment(SwingConstants.CENTER);
    rateAndSizePnl.add(sizeInBytesFld);
    // Add the rate panel to the link information panel
    gbc.weighty = 0.0;
    gbc.gridy++;
    infoPnl.add(rateAndSizePnl, gbc);
    // Add the link information panel to the dialog
    gbc.insets.top = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing();
    gbc.insets.left = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing();
    managerPnl.add(infoPnl, gbc);
    // Create the rate selection label
    JLabel rateSelectLbl = new JLabel("Select rate:");
    rateSelectLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    rateSelectLbl.setForeground(ModifiableColorInfo.LABEL_TEXT.getColor());
    gbc.insets.top = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
    rateSelectPnl.add(rateSelectLbl, gbc);
    // Create the combo box that displays the variable rates and add it to the dialog panel
    rateFilter = new PaddedComboBox(availableRates, ModifiableFontInfo.INPUT_TEXT.getFont()) {

        /**
         ************************************************************************************
         * Override so that items flagged as disabled (grayed out) can't be selected
         ************************************************************************************
         */
        @Override
        public void setSelectedItem(Object anObject) {
            // Check if the item isn't flagged as disabled
            if (!anObject.toString().startsWith(DISABLED_TEXT_COLOR)) {
                // Set the selected item to the specified item, if it exists in the list
                super.setSelectedItem(anObject);
            }
        }
    };
    gbc.fill = GridBagConstraints.NONE;
    gbc.gridx++;
    rateSelectPnl.add(rateFilter, gbc);
    // Add a listener for rate filter selection changes
    rateFilter.addActionListener(new ActionListener() {

        /**
         ************************************************************************************
         * Rebuild the table tree using the selected rate filter
         ************************************************************************************
         */
        @Override
        public void actionPerformed(ActionEvent ae) {
            // Get the rate selected in the combo box
            String newRate = ((JComboBox<?>) ae.getSource()).getSelectedItem().toString();
            // Check if the rate changed
            if (!selectedRate.equals(newRate)) {
                // Set the new rate as the selected rate
                selectedRate = newRate;
                // Rebuild the variable tree using the selected rate as a filter
                variableTree.buildTableTree(null, rateName, selectedRate, linkDialog);
            }
            // Get the list of all variable tree paths in the variable tree and set these in
            // the links tree. This is used to maintain the correct variable order in the links
            // tree
            linkTree.setTreePathOrder(variableTree.getTableTreePathList(null, variableTree.getNodeByNodeName("Structures & Variables"), -1));
            // Check if this is the first time the rate selection occurs
            if (firstRateChange) {
                // Force the link tree to be rebuilt now that the tree path order is
                // established (via setting the rate filter). This forces the link variables to
                // appear in the same order as they are listed in their prototype tables
                linkTree.buildTree(false, false, rateName, false, linkDialog);
                // Set the flag to prevent rebuilding the link tree when subsequent rate
                // selection changes are made
                firstRateChange = false;
            }
            // Set the rate in the link tree to flag compatible links
            linkTree.setSelectedRate(selectedRate);
            // Add the rate and size to the link nodes and set the color based on the selected
            // rate
            linkTree.adjustNodeText(linkTree.getRootNode());
        }
    });
    // Set the flag so that the rate change executed below triggers a rebuilding of the links
    // tree using the tree path order in the variables tree
    firstRateChange = true;
    // Set the rate filter to the selected rate. This initial setting updates the link tree,
    // but skips rebuilding the variable tree unnecessarily
    rateFilter.setSelectedItem(selectedRate);
    // Re-enable storage of edit actions now that dialog creation is complete
    undoHandler.setAllowUndo(true);
    // Create the rate units label and add it to the dialog panel
    JLabel rateUnitsLbl = new JLabel("samples/second");
    rateUnitsLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    rateUnitsLbl.setForeground(ModifiableColorInfo.LABEL_TEXT.getColor());
    gbc.gridx++;
    rateSelectPnl.add(rateUnitsLbl, gbc);
    // Add the rate selection panel to the dialog panel
    gbc.gridx = 0;
    gbc.gridy++;
    managerPnl.add(rateSelectPnl, gbc);
}
Also used : JPanel(javax.swing.JPanel) DocumentListener(javax.swing.event.DocumentListener) GridBagConstraints(java.awt.GridBagConstraints) Insets(java.awt.Insets) FlowLayout(java.awt.FlowLayout) GridBagLayout(java.awt.GridBagLayout) ActionEvent(java.awt.event.ActionEvent) CustomSplitPane(CCDD.CcddClassesComponent.CustomSplitPane) JTextField(javax.swing.JTextField) PaddedComboBox(CCDD.CcddClassesComponent.PaddedComboBox) UndoableTextArea(CCDD.CcddUndoHandler.UndoableTextArea) Component(java.awt.Component) JScrollPane(javax.swing.JScrollPane) UndoableTreePathSelection(CCDD.CcddUndoHandler.UndoableTreePathSelection) JComboBox(javax.swing.JComboBox) JLabel(javax.swing.JLabel) DocumentEvent(javax.swing.event.DocumentEvent) ActionListener(java.awt.event.ActionListener)

Example 3 with UndoableTextArea

use of CCDD.CcddUndoHandler.UndoableTextArea in project CCDD by nasa.

the class CcddInputFieldPanelHandler method createDataFieldPanel.

/**
 ********************************************************************************************
 * Create the data fields for display in the description and data field panel
 *
 * @param undoable
 *            true if the change(s) to the data fields should be stored for possible undo/redo
 *            operations; false to not store the changes
 ********************************************************************************************
 */
protected void createDataFieldPanel(boolean undoable) {
    maxFieldWidth = 0;
    // Set the preferred size so that the layout manager uses its default sizing
    fieldPnlHndlrOwner.setPreferredSize(null);
    // Check if the data fields are already displayed
    if (fieldPnl != null) {
        // Remove the existing data fields
        inputPnl.remove(fieldPnl);
    }
    // Check if this is a data table
    if (isDataTable) {
        // Build the data field information so that only applicable fields are displayed
        dataFieldHandler.buildFieldInformation(((CcddTableEditorHandler) this).getTableInformation().getTablePath(), ((CcddTableEditorHandler) this).getTableInformation().isRootStructure(), false);
    }
    // Check if any data fields exist
    if (dataFieldHandler.getFieldInformation() != null && !dataFieldHandler.getFieldInformation().isEmpty()) {
        // Create a panel to contain the data fields. As the editor is resized the field panel
        // is resized to contain the data fields, wrapping them to new lines as needed
        fieldPnl = new JPanel(new WrapLayout(FlowLayout.LEADING));
        // Adjust the border to align the first field with the description label
        fieldPnl.setBorder(BorderFactory.createEmptyBorder(-ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing(), -ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing(), 0, 0));
        // Step through each data field
        for (final FieldInformation fieldInfo : dataFieldHandler.getFieldInformation()) {
            switch(fieldInfo.getInputType().getInputFormat()) {
                case PAGE_FORMAT:
                    switch(fieldInfo.getInputType()) {
                        case BREAK:
                            // Create a text field for the separator so it can be handled like
                            // other fields
                            fieldInfo.setInputFld(undoHandler.new UndoableTextField());
                            // Add a vertical separator to the field panel
                            fieldPnl.add(new JSeparator(SwingConstants.VERTICAL));
                            break;
                        case SEPARATOR:
                            // Create a text field for the separator so it can be handled like
                            // other fields
                            fieldInfo.setInputFld(undoHandler.new UndoableTextField());
                            // Add a horizontal separator to the field panel
                            fieldPnl.add(new JSeparator());
                            break;
                        default:
                            break;
                    }
                    break;
                case BOOLEAN:
                    // Create the data field check box
                    fieldInfo.setInputFld(undoHandler.new UndoableCheckBox(fieldInfo.getFieldName(), Boolean.valueOf(fieldInfo.getValue())));
                    UndoableCheckBox booleanCb = (UndoableCheckBox) fieldInfo.getInputFld();
                    booleanCb.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
                    booleanCb.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
                    // Set the check box's name so that the undo handler can identify the check
                    // box, even if it's destroyed and recreated
                    booleanCb.setName(fieldInfo.getOwnerName() + DATA_FIELD_IDENTIFIER_SEPARATOR + fieldInfo.getFieldName());
                    // Adjust the left and right padding around the check box so that it is
                    // spaced the same as a text field data field
                    booleanCb.setBorder(BorderFactory.createEmptyBorder(0, ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing(), 0, ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing()));
                    // Check if a description exists for this field
                    if (!fieldInfo.getDescription().isEmpty()) {
                        // Set the description as the tool tip text for this check box
                        booleanCb.setToolTipText(CcddUtilities.wrapText(fieldInfo.getDescription(), ModifiableSizeInfo.MAX_TOOL_TIP_LENGTH.getSize()));
                    }
                    // And the check box to the field panel
                    fieldPnl.add(booleanCb);
                    // Store this check box's width if it is the largest data field width
                    maxFieldWidth = Math.max(maxFieldWidth, booleanCb.getPreferredSize().width);
                    break;
                default:
                    final JTextComponent inputFld;
                    // Create a panel for a single label and text field pair. This is necessary
                    // so that the two will stay together if line wrapping occurs due to a
                    // window size change
                    JPanel singleFldPnl = new JPanel(new FlowLayout(FlowLayout.LEADING, ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing(), ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 4));
                    singleFldPnl.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
                    // Create the data field label
                    JLabel fieldLbl = new JLabel(fieldInfo.getFieldName());
                    fieldLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
                    fieldLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
                    singleFldPnl.add(fieldLbl);
                    // Check if the input type is for multi-line text
                    if (fieldInfo.getInputType().equals(InputDataType.TEXT_MULTI)) {
                        // Create the data field input field as a text area, which allows new
                        // line characters which cause the field to be displayed in multiple
                        // rows
                        fieldInfo.setInputFld(undoHandler.new UndoableTextArea(fieldInfo.getValue(), 1, fieldInfo.getSize()));
                        inputFld = (UndoableTextArea) fieldInfo.getInputFld();
                    } else // The input type is one other than for multi-line text
                    {
                        // Create the data field input field as a text field, which allows a
                        // single rows
                        fieldInfo.setInputFld(undoHandler.new UndoableTextField(fieldInfo.getValue(), fieldInfo.getSize()));
                        inputFld = (UndoableTextField) fieldInfo.getInputFld();
                    }
                    inputFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
                    inputFld.setEditable(true);
                    inputFld.setBorder(border);
                    inputFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
                    inputFld.setBackground(fieldInfo.getValue().isEmpty() && fieldInfo.isRequired() ? ModifiableColorInfo.REQUIRED_BACK.getColor() : ModifiableColorInfo.INPUT_BACK.getColor());
                    // Set the text field's name so that the undo handler can identify the text
                    // field, even if it's destroyed and recreated
                    inputFld.setName(fieldInfo.getOwnerName() + DATA_FIELD_IDENTIFIER_SEPARATOR + fieldInfo.getFieldName());
                    // Check if a description exists for this field
                    if (!fieldInfo.getDescription().isEmpty()) {
                        // Set the description as the tool tip text for this text field
                        inputFld.setToolTipText(CcddUtilities.wrapText(fieldInfo.getDescription(), ModifiableSizeInfo.MAX_TOOL_TIP_LENGTH.getSize()));
                    }
                    // Add the data field to the single field panel
                    singleFldPnl.add(inputFld);
                    // And the single field to the field panel
                    fieldPnl.add(singleFldPnl);
                    // Store this field's width if it is the largest data field width
                    maxFieldWidth = Math.max(maxFieldWidth, singleFldPnl.getPreferredSize().width);
                    // Create an input field verifier for the data field
                    inputFld.setInputVerifier(new InputVerifier() {

                        // Storage for the last valid value entered; used to restore the data
                        // field value if an invalid value is entered. Initialize to the value
                        // at the time the field is created
                        String lastValid = inputFld.getText();

                        /**
                         ********************************************************************
                         * Verify the contents of a the data field
                         ********************************************************************
                         */
                        @Override
                        public boolean verify(JComponent input) {
                            boolean isValid = true;
                            // Get the data field reference to shorten subsequent calls
                            JTextComponent inFld = (JTextComponent) input;
                            // Get the data field contents
                            String inputTxt = inFld.getText();
                            // trailing white space characters
                            if (fieldInfo.getInputType() != InputDataType.TEXT_WHT_SPC && fieldInfo.getInputType() != InputDataType.TEXT_MULTI_WHT_SPC) {
                                // Remove leading and trailing white space characters
                                inputTxt = inputTxt.trim();
                            }
                            // Check if the field contains an illegal character
                            if (!fieldInfo.getInputType().getInputMatch().isEmpty() && !inputTxt.isEmpty() && !inputTxt.matches(fieldInfo.getInputType().getInputMatch())) {
                                // Inform the user that the data field contents is invalid
                                new CcddDialogHandler().showMessageDialog(fieldPnlHndlrOwner, "<html><b>Invalid characters in field '</b>" + fieldInfo.getFieldName() + "<b>'; characters consistent with input type '" + fieldInfo.getInputType().getInputName() + "' expected", "Invalid " + fieldInfo.getInputType().getInputName(), JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
                                // redrawn correctly
                                if (fieldPnlHndlrOwner instanceof CcddFrameHandler) {
                                    ((CcddFrameHandler) fieldPnlHndlrOwner).setControlsEnabled(false);
                                    ((CcddFrameHandler) fieldPnlHndlrOwner).setControlsEnabled(true);
                                } else if (fieldPnlHndlrOwner instanceof CcddDialogHandler) {
                                    ((CcddDialogHandler) fieldPnlHndlrOwner).setControlsEnabled(false);
                                    ((CcddDialogHandler) fieldPnlHndlrOwner).setControlsEnabled(true);
                                }
                                // Check if the data field is a text field
                                if (input instanceof UndoableTextField) {
                                    // Restore the previous value in the data field
                                    ((UndoableTextField) inFld).setText(lastValid, false);
                                } else // Check if the data field is a text area (multi-line)
                                if (input instanceof UndoableTextArea) {
                                    // Restore the previous value in the data field
                                    ((UndoableTextArea) inFld).setText(lastValid);
                                }
                                // Set the flag to indicate an invalid value was entered
                                isValid = false;
                            } else // The input is valid
                            {
                                // Store the 'cleaned' text back into the text field. For
                                // numeric types, reformat the input value
                                inFld.setText(fieldInfo.getInputType().formatInput(inputTxt));
                                fieldInfo.setValue(inFld.getText());
                                // Store the new value as the last valid value
                                lastValid = inFld.getText();
                                // Set the text field background color. If the field is empty
                                // and is flagged as required then set the background to
                                // indicate a value should be supplied
                                setFieldBackground(fieldInfo);
                            }
                            return isValid;
                        }
                    });
                    break;
            }
        }
        // Check that at least one field exists
        if (fieldPnl.getComponentCount() != 0) {
            // Add the data field panel to the dialog
            inputPnl.add(fieldPnl, gbc);
        }
    }
    // Check if this is a data table
    if (isDataTable) {
        // Build the data field information so that all fields are included
        dataFieldHandler.buildFieldInformation(((CcddTableEditorHandler) this).getTableInformation().getTablePath(), ((CcddTableEditorHandler) this).getTableInformation().isRootStructure(), true);
    }
    // Check if the data field panel change should be put in the undo/redo stack
    if (undoable) {
        // Store the field information in the undo handler in case the update needs to be
        // undone
        undoFieldPnl.addDataFieldEdit(this, dataFieldHandler.getFieldInformationCopy());
    }
    // Force the owner of the editor panel to redraw so that changes to the fields are
    // displayed and the owner's size is adjusted
    fieldPnlHndlrOwner.revalidate();
    fieldPnlHndlrOwner.repaint();
}
Also used : JPanel(javax.swing.JPanel) FlowLayout(java.awt.FlowLayout) JComponent(javax.swing.JComponent) JLabel(javax.swing.JLabel) JTextComponent(javax.swing.text.JTextComponent) UndoableTextField(CCDD.CcddUndoHandler.UndoableTextField) InputVerifier(javax.swing.InputVerifier) WrapLayout(CCDD.CcddClassesComponent.WrapLayout) JSeparator(javax.swing.JSeparator) UndoableCheckBox(CCDD.CcddUndoHandler.UndoableCheckBox) UndoableTextArea(CCDD.CcddUndoHandler.UndoableTextArea) FieldInformation(CCDD.CcddClassesDataTable.FieldInformation)

Example 4 with UndoableTextArea

use of CCDD.CcddUndoHandler.UndoableTextArea in project CCDD by nasa.

the class CcddInputFieldPanelHandler method createDescAndDataFieldPanel.

/**
 ********************************************************************************************
 * Create the table input field panel
 *
 * @param fieldPnlHndlrOwner
 *            reference to the owner of this description and data field handler
 *
 * @param tableScrollPane
 *            scroll pane containing the table; null if this field panel handler does not
 *            contain a table
 *
 * @param ownerName
 *            name of the owner of this field panel handler; null if no owner name is
 *            associated with it
 *
 * @param description
 *            description field text; null if the description is initially blank and disabled
 *
 * @param fieldHandler
 *            field handler reference
 ********************************************************************************************
 */
protected void createDescAndDataFieldPanel(final Component fieldPnlHndlrOwner, final JScrollPane tableScrollPane, String ownerName, String description, CcddFieldHandler fieldHandler) {
    this.fieldPnlHndlrOwner = fieldPnlHndlrOwner;
    this.ownerName = ownerName;
    this.dataFieldHandler = fieldHandler;
    // Set the flag to indicate if this input field panel handler is a data table
    isDataTable = this instanceof CcddTableEditorHandler;
    // Create the handler for undoing/redoing data field changes
    undoFieldPnl = undoHandler.new UndoableDataFieldPanel();
    // Set the initial layout manager characteristics
    gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
    // Create an outer panel to put the editor panel in (the border doesn't appear without
    // this) and add the table description text field
    inputPnl = new JPanel(new GridBagLayout());
    // Check if this editor contains a table
    if (tableScrollPane != null) {
        // Define the editor panel to contain the table
        JPanel innerPanel = new JPanel();
        innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.X_AXIS));
        innerPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
        innerPanel.add(tableScrollPane);
        inputPnl.add(innerPanel, gbc);
    }
    // Create borders for the input fields
    border = BorderFactory.createCompoundBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.LIGHT_GRAY, Color.GRAY), BorderFactory.createEmptyBorder(ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing(), ModifiableSpacingInfo.INPUT_FIELD_PADDING.getSpacing()));
    Border emptyBorder = BorderFactory.createEmptyBorder();
    // Create a panel to hold the table's system name, description and, if applicable, message
    // ID information
    JPanel descriptionPnl = new JPanel(new GridBagLayout());
    // Create the description label
    JLabel descriptionLbl = new JLabel("Description");
    descriptionLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
    descriptionLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
    // Check if this editor doesn't contain a table
    if (tableScrollPane == null) {
        gbc.insets.top = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
        gbc.insets.bottom = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing() / 2;
    }
    // Add the table description label
    gbc.insets.left = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() / 2;
    gbc.insets.right = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() / 2;
    gbc.weightx = 0.0;
    gbc.weighty = 0.0;
    gbc.gridy++;
    descriptionPnl.add(descriptionLbl, gbc);
    // Create the description input field
    descriptionFld = undoHandler.new UndoableTextArea(3, 1);
    descriptionFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
    descriptionFld.setBorder(emptyBorder);
    descriptionFld.setEditable(true);
    descriptionFld.setLineWrap(true);
    descriptionFld.setWrapStyleWord(true);
    descriptionFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
    descriptionFld.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
    descriptionFld.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
    descScrollPane = new JScrollPane(descriptionFld);
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridwidth = GridBagConstraints.REMAINDER;
    gbc.weightx = 1.0;
    // Check if the description field is initially disabled
    if (description == null) {
        // Set the description field and description field scroll pane background color to
        // indicate these are disabled
        descriptionFld.setBackground(ModifiableColorInfo.INPUT_DISABLE_BACK.getColor());
        descScrollPane.setBackground(ModifiableColorInfo.INPUT_DISABLE_BACK.getColor());
    } else {
        // Set the description field and description field scroll pane background color to
        // indicate these are enabled, and set the description field text
        descriptionFld.setBackground(ModifiableColorInfo.INPUT_BACK.getColor());
        descScrollPane.setBackground(ModifiableColorInfo.INPUT_BACK.getColor());
        descriptionFld.setText(description);
    }
    // Check if this editor doesn't contain a table
    if (tableScrollPane == null) {
        // Place the description field within a scroll pane and add the field to the editor
        inputPnl.setBorder(BorderFactory.createEtchedBorder());
        descScrollPane.setBorder(border);
        descScrollPane.setMinimumSize(descScrollPane.getPreferredSize());
        gbc.gridy++;
        descriptionPnl.add(descScrollPane, gbc);
    } else // The editor contains a table
    {
        // Place the description field within a scroll pane and add the field to the editor
        inputPnl.setBorder(emptyBorder);
        descriptionFld.setToolTipText(CcddUtilities.wrapText("Table description", ModifiableSizeInfo.MAX_TOOL_TIP_LENGTH.getSize()));
        descScrollPane.setBorder(emptyBorder);
        descScrollPane.setViewportBorder(border);
        descScrollPane.setMinimumSize(descScrollPane.getPreferredSize());
        gbc.gridx++;
        descriptionPnl.add(descScrollPane, gbc);
        gbc.insets.top = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing();
        gbc.insets.bottom = ModifiableSpacingInfo.LABEL_VERTICAL_SPACING.getSpacing();
    }
    // Add the description panel to the editor
    gbc.gridx = 0;
    gbc.gridy++;
    inputPnl.add(descriptionPnl, gbc);
    // Add the data field panel to the editor
    gbc.gridy++;
    gbc.insets.top = 0;
    gbc.insets.bottom = 0;
    createDataFieldPanel(false);
    // Check if this editor doesn't contain a table
    if (tableScrollPane == null) {
        // Add an invisible component in order to force the description panel and data fields
        // to the top of the panel
        JLabel invisibleLbl = new JLabel("");
        gbc.weighty = 1.0;
        gbc.gridy++;
        inputPnl.add(invisibleLbl, gbc);
        gbc.weighty = 0.0;
        gbc.gridy--;
    }
    // Add a listener for changes in the editor panel's size
    inputPnl.addComponentListener(new ComponentAdapter() {

        /**
         ************************************************************************************
         * Handle resizing of the editor panel
         ************************************************************************************
         */
        @Override
        public void componentResized(ComponentEvent ce) {
            // Create a runnable object to be executed
            SwingUtilities.invokeLater(new Runnable() {

                /**
                 ****************************************************************************
                 * Since the size returned by get___Size() can lag the actual size, use
                 * invokeLater to let the sizes "catch up"
                 ****************************************************************************
                 */
                @Override
                public void run() {
                    // Revalidate to force the editor panel to redraw to the new sizes, which
                    // causes the data fields to be correctly sized so that all of the fields
                    // are visible
                    inputPnl.revalidate();
                }
            });
        }
    });
}
Also used : JScrollPane(javax.swing.JScrollPane) JPanel(javax.swing.JPanel) GridBagConstraints(java.awt.GridBagConstraints) Insets(java.awt.Insets) GridBagLayout(java.awt.GridBagLayout) BoxLayout(javax.swing.BoxLayout) JLabel(javax.swing.JLabel) UndoableTextArea(CCDD.CcddUndoHandler.UndoableTextArea) ComponentEvent(java.awt.event.ComponentEvent) UndoableDataFieldPanel(CCDD.CcddUndoHandler.UndoableDataFieldPanel) Border(javax.swing.border.Border) BevelBorder(javax.swing.border.BevelBorder) EtchedBorder(javax.swing.border.EtchedBorder) ComponentAdapter(java.awt.event.ComponentAdapter)

Aggregations

UndoableTextArea (CCDD.CcddUndoHandler.UndoableTextArea)4 JLabel (javax.swing.JLabel)3 JPanel (javax.swing.JPanel)3 UndoableCheckBox (CCDD.CcddUndoHandler.UndoableCheckBox)2 UndoableTextField (CCDD.CcddUndoHandler.UndoableTextField)2 Component (java.awt.Component)2 FlowLayout (java.awt.FlowLayout)2 GridBagConstraints (java.awt.GridBagConstraints)2 GridBagLayout (java.awt.GridBagLayout)2 Insets (java.awt.Insets)2 JScrollPane (javax.swing.JScrollPane)2 JTextField (javax.swing.JTextField)2 JTextComponent (javax.swing.text.JTextComponent)2 CustomSplitPane (CCDD.CcddClassesComponent.CustomSplitPane)1 PaddedComboBox (CCDD.CcddClassesComponent.PaddedComboBox)1 WrapLayout (CCDD.CcddClassesComponent.WrapLayout)1 FieldInformation (CCDD.CcddClassesDataTable.FieldInformation)1 UndoableDataFieldPanel (CCDD.CcddUndoHandler.UndoableDataFieldPanel)1 UndoableTreePathSelection (CCDD.CcddUndoHandler.UndoableTreePathSelection)1 ActionEvent (java.awt.event.ActionEvent)1