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;
}
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);
}
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();
}
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();
}
});
}
});
}
Aggregations