use of javax.swing.text.JTextComponent 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;
}
});
}
use of javax.swing.text.JTextComponent in project CCDD by nasa.
the class CcddScriptHandler method getAssociationsPanel.
/**
********************************************************************************************
* Create the panel containing the script associations table
*
* @param title
* text to display above the script associations table; null or blank if no text is
* to be displayed
*
* @param allowSelectDisabled
* true if disabled associations can be selected; false if not. In the script
* manager disabled associations are selectable so that these can be deleted if
* desired. Scripts that are selected and disabled are ignored when executing
* scripts
*
* @param parent
* GUI component calling this method
*
* @return Reference to the JPanel containing the script associations table
********************************************************************************************
*/
@SuppressWarnings("serial")
protected JPanel getAssociationsPanel(String title, final boolean allowSelectDisabled, final Component parent) {
// 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(), 0, 0, 0), 0, 0);
// Define the panel to contain the table
JPanel assnsPnl = new JPanel(new GridBagLayout());
// Check if a table title is provided
if (title != null && !title.isEmpty()) {
// Create the script associations label
JLabel assnsLbl = new JLabel(title);
assnsLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
assnsLbl.setForeground(ModifiableColorInfo.SPECIAL_LABEL_TEXT.getColor());
assnsPnl.add(assnsLbl, gbc);
gbc.gridy++;
}
// Create the table to display the search results
assnsTable = new CcddJTableHandler() {
/**
************************************************************************************
* Allow multiple line display in all columns
************************************************************************************
*/
@Override
protected boolean isColumnMultiLine(int column) {
return true;
}
/**
************************************************************************************
* Allow HTML-formatted text in the specified column(s)
************************************************************************************
*/
@Override
protected boolean isColumnHTML(int column) {
return column == AssociationsTableColumnInfo.MEMBERS.ordinal();
}
/**
************************************************************************************
* Hide the the specified columns
************************************************************************************
*/
@Override
protected boolean isColumnHidden(int column) {
return column == AssociationsTableColumnInfo.AVAILABLE.ordinal();
}
/**
************************************************************************************
* Allow editing the description in the script manager's associations table
************************************************************************************
*/
@Override
public boolean isCellEditable(int row, int column) {
return (column == convertColumnIndexToModel(AssociationsTableColumnInfo.NAME.ordinal()) || column == convertColumnIndexToModel(AssociationsTableColumnInfo.DESCRIPTION.ordinal())) && allowSelectDisabled;
}
/**
************************************************************************************
* Validate changes to the editable cells
*
* @param tableData
* list containing the table data row arrays
*
* @param row
* table model row number
*
* @param column
* table model column number
*
* @param oldValue
* original cell contents
*
* @param newValue
* new cell contents
*
* @param showMessage
* true to display the invalid input dialog, if applicable
*
* @param isMultiple
* true if this is one of multiple cells to be entered and checked; false if
* only a single input is being entered
*
* @return Always returns false
***********************************************************************************
*/
@Override
protected Boolean validateCellContent(List<Object[]> tableData, int row, int column, Object oldValue, Object newValue, Boolean showMessage, boolean isMultiple) {
// Reset the flag that indicates the last edited cell's content is invalid
setLastCellValid(true);
// Create a string version of the new value
String newValueS = newValue.toString();
try {
// Check if the value isn't blank
if (!newValueS.isEmpty()) {
// blank
if (column == AssociationsTableColumnInfo.NAME.ordinal()) {
// type
if (!newValueS.matches(InputDataType.ALPHANUMERIC.getInputMatch())) {
throw new CCDDException("Illegal character(s) in association name");
}
// avoid creating a duplicate
for (int otherRow = 0; otherRow < getRowCount(); otherRow++) {
// association name matches the one being added (case insensitive)
if (otherRow != row && newValueS.equalsIgnoreCase(tableData.get(otherRow)[column].toString())) {
throw new CCDDException("Association name already in use");
}
}
}
}
} catch (CCDDException ce) {
// Set the flag that indicates the last edited cell's content is invalid
setLastCellValid(false);
// Check if the input error dialog should be displayed
if (showMessage) {
// Inform the user that the input value is invalid
new CcddDialogHandler().showMessageDialog(parent, "<html><b>" + ce.getMessage(), "Invalid Input", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
}
// Restore the cell contents to its original value and pop the edit from the
// stack
tableData.get(row)[column] = oldValue;
getUndoManager().undoRemoveEdit();
}
return false;
}
/**
************************************************************************************
* Load the script associations data into the table and format the table cells
************************************************************************************
*/
@Override
protected void loadAndFormatData() {
// Place the data into the table model along with the column names, set up the
// editors and renderers for the table cells, set up the table grid lines, and
// calculate the minimum width required to display the table information
int totalWidth = setUpdatableCharacteristics(getScriptAssociationData(allowSelectDisabled, parent), AssociationsTableColumnInfo.getColumnNames(), null, AssociationsTableColumnInfo.getToolTips(), true, true, true);
// Check if the script manager or executive is active
if (scriptDialog != null) {
// Set the script manager or executive width to the associations table width
scriptDialog.setTableWidth(totalWidth + LAF_SCROLL_BAR_WIDTH + ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing() * 2);
}
}
/**
************************************************************************************
* Alter the association table cell color or contents
*
* @param component
* reference to the table cell renderer component
*
* @param value
* cell value
*
* @param isSelected
* true if the cell is to be rendered with the selection highlighted
*
* @param int
* row cell row, view coordinates
*
* @param column
* cell column, view coordinates
************************************************************************************
*/
@Override
protected void doSpecialRendering(Component component, String text, boolean isSelected, int row, int column) {
// Check if the association on the specified row is flagged as unavailable
if (!isAssociationAvailable(convertRowIndexToModel(row))) {
// Set the text color for this row to indicate it's not available
((JTextComponent) component).setForeground(Color.GRAY);
// Check if selection of disabled associations isn't allowed
if (!allowSelectDisabled) {
// Set the background color to indicate the row isn't selectable
((JTextComponent) component).setBackground(ModifiableColorInfo.TABLE_BACK.getColor());
}
}
// displayed
if (column == convertColumnIndexToView(AssociationsTableColumnInfo.SCRIPT_FILE.ordinal()) && hideScriptFilePath.isSelected()) {
// Remove the path, leaving only the script file name
((JTextComponent) component).setText(((JTextComponent) component).getText().replaceFirst(".*" + Pattern.quote(File.separator), ""));
}
}
/**
************************************************************************************
* Override the method that sets the row sorter so that special sorting can be
* performed on the script file column
************************************************************************************
*/
@Override
protected void setTableSortable() {
super.setTableSortable();
// Get a reference to the sorter
@SuppressWarnings("unchecked") TableRowSorter<UndoableTableModel> sorter = (TableRowSorter<UndoableTableModel>) getRowSorter();
// rows in the table
if (sorter != null) {
// Add a sort comparator for the script file column
sorter.setComparator(AssociationsTableColumnInfo.SCRIPT_FILE.ordinal(), new Comparator<String>() {
/**
************************************************************************
* Override the comparison when sorting the script file column to ignore
* the script file paths if these are currently hidden
************************************************************************
*/
@Override
public int compare(String filePath1, String filePath2) {
return (hideScriptFilePath.isSelected() ? filePath1.replaceFirst(".*" + Pattern.quote(File.separator), "") : filePath1).compareTo(hideScriptFilePath.isSelected() ? filePath2.replaceFirst(".*" + Pattern.quote(File.separator), "") : filePath2);
}
});
}
}
/**
************************************************************************************
* Handle a change to the table's content
************************************************************************************
*/
@Override
protected void processTableContentChange() {
// associations manager dialog is open)
if (scriptDialog != null && scriptDialog instanceof CcddScriptManagerDialog) {
// Update the script associations manager change indicator
((CcddScriptManagerDialog) scriptDialog).updateChangeIndicator();
}
}
};
// Set the list selection model in order to detect table rows that aren't allowed to be
// selected
assnsTable.setSelectionModel(new DefaultListSelectionModel() {
/**
************************************************************************************
* Check if the script association table item is selected, ignoring associations that
* are flagged as unavailable
************************************************************************************
*/
@Override
public boolean isSelectedIndex(int row) {
return allowSelectDisabled || isAssociationAvailable(assnsTable.convertRowIndexToModel(row)) ? super.isSelectedIndex(row) : false;
}
});
// Place the table into a scroll pane
JScrollPane scrollPane = new JScrollPane(assnsTable);
// Set up the search results table parameters
assnsTable.setFixedCharacteristics(scrollPane, false, ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, TableSelectionMode.SELECT_BY_ROW, true, ModifiableColorInfo.TABLE_BACK.getColor(), true, true, ModifiableFontInfo.OTHER_TABLE_CELL.getFont(), true);
// Define the panel to contain the table and add it to the dialog
JPanel assnsTblPnl = new JPanel();
assnsTblPnl.setLayout(new BoxLayout(assnsTblPnl, BoxLayout.X_AXIS));
assnsTblPnl.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
assnsTblPnl.add(scrollPane);
gbc.weighty = 1.0;
assnsPnl.add(assnsTblPnl, gbc);
// Create the check box for hiding/showing the file paths in the associations table script
// file column
hideScriptFilePath = new JCheckBox("Hide script file path", ccddMain.getProgPrefs().getBoolean(HIDE_SCRIPT_PATH, false));
hideScriptFilePath.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
hideScriptFilePath.setBorder(BorderFactory.createEmptyBorder());
hideScriptFilePath.setToolTipText(CcddUtilities.wrapText("Remove the file paths from the script file column", ModifiableSizeInfo.MAX_TOOL_TIP_LENGTH.getSize()));
// Add a listener for check box selection changes
hideScriptFilePath.addActionListener(new ActionListener() {
/**
************************************************************************************
* Handle a change in the hide script file path check box state
************************************************************************************
*/
@Override
public void actionPerformed(ActionEvent ae) {
assnsTable.repaint();
ccddMain.getProgPrefs().putBoolean(HIDE_SCRIPT_PATH, hideScriptFilePath.isSelected());
}
});
gbc.weighty = 0.0;
gbc.gridy++;
assnsPnl.add(hideScriptFilePath, gbc);
// Create a panel to contain the environment variable override label and field
JPanel envVarOverridePnl = new JPanel(new GridBagLayout());
JLabel envVarOverrideLbl = new JLabel("Environment variable override");
envVarOverrideLbl.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
gbc.insets.right = ModifiableSpacingInfo.LABEL_HORIZONTAL_SPACING.getSpacing();
gbc.weightx = 0.0;
gbc.gridy++;
envVarOverridePnl.add(envVarOverrideLbl, gbc);
envVarOverrideFld = new JTextField(ModifiableOtherSettingInfo.ENV_VAR_OVERRIDE.getValue());
envVarOverrideFld.setFont(ModifiableFontInfo.INPUT_TEXT.getFont());
envVarOverrideFld.setEditable(true);
envVarOverrideFld.setForeground(ModifiableColorInfo.INPUT_TEXT.getColor());
envVarOverrideFld.setBackground(ModifiableColorInfo.INPUT_BACK.getColor());
envVarOverrideFld.setBorder(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())));
// Add a listener for focus changes on the environment variable override field
envVarOverrideFld.addFocusListener(new FocusAdapter() {
/**
************************************************************************************
* Handle a loss of focus
************************************************************************************
*/
@Override
public void focusLost(FocusEvent fe) {
// Update the environment variable map and association availability
getEnvironmentVariableMap(parent);
}
});
gbc.insets.right = 0;
gbc.weightx = 1.0;
gbc.gridx++;
envVarOverridePnl.add(envVarOverrideFld, gbc);
gbc.gridx = 0;
assnsPnl.add(envVarOverridePnl, gbc);
// Initialize the environment variable map
getEnvironmentVariableMap(parent);
return assnsPnl;
}
use of javax.swing.text.JTextComponent in project CCDD by nasa.
the class CcddTableEditorDialog method initialize.
/**
********************************************************************************************
* Create the data table editor dialog
*
* @param tableInformation
* list containing information for each table
*
* @param editor
* reference to an existing table editor
********************************************************************************************
*/
private void initialize(List<TableInformation> tableInformation, CcddTableEditorHandler editor) {
// Menu ///////////////////////////////////////////////////////////////////////////////////
// Create the data table menu bar
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
// Create the File menu and menu items
JMenu mnFile = ccddMain.createMenu(menuBar, "File", KeyEvent.VK_F, 1, null);
mntmOpen = ccddMain.createMenuItem(mnFile, "Edit table(s)", KeyEvent.VK_E, 1, "Open one or more data tables for editing");
mntmOpenPrototype = ccddMain.createMenuItem(mnFile, "Edit prototype", KeyEvent.VK_T, 2, "Open the prototype for the current table");
mnFile.addSeparator();
mntmStore = ccddMain.createMenuItem(mnFile, "Store current", KeyEvent.VK_U, 1, "Store changes to the current editor table");
mntmStoreAll = ccddMain.createMenuItem(mnFile, "Store all", KeyEvent.VK_L, 1, "Store the changes to all tables in this editor");
mnFile.addSeparator();
mntmImport = ccddMain.createMenuItem(mnFile, "Import data", KeyEvent.VK_I, 1, "Import data from a CSV, EDS XML, JSON, or XTCE XML file into the current editor table");
JMenu mnExport = ccddMain.createSubMenu(mnFile, "Export table", KeyEvent.VK_X, 1, null);
mntmExportCSV = ccddMain.createMenuItem(mnExport, "CSV", KeyEvent.VK_C, 1, "Export the current editor table in CSV format");
mntmExportEDS = ccddMain.createMenuItem(mnExport, "EDS", KeyEvent.VK_E, 1, "Export the current editor table in EDS XML format");
mntmExportJSON = ccddMain.createMenuItem(mnExport, "JSON", KeyEvent.VK_J, 1, "Export the current editor table in JSON format");
mntmExportXTCE = ccddMain.createMenuItem(mnExport, "XTCE", KeyEvent.VK_X, 1, "Export the current editor table in XTCE XML format");
mnFile.addSeparator();
mntmPrint = ccddMain.createMenuItem(mnFile, "Print current", KeyEvent.VK_P, 1, "Print the current editor table information");
mntmSearchTable = ccddMain.createMenuItem(mnFile, "Search tables", KeyEvent.VK_S, 1, "Search the project database tables");
mnFile.addSeparator();
mntmCloseActive = ccddMain.createMenuItem(mnFile, "Close current", KeyEvent.VK_C, 2, "Close the current editor table");
mntmCloseAll = ccddMain.createMenuItem(mnFile, "Close all", KeyEvent.VK_A, 1, "Close all tables in this editor");
// Create the Edit menu and menu items
JMenu mnEdit = ccddMain.createMenu(menuBar, "Edit", KeyEvent.VK_E, 1, null);
mntmCopy = ccddMain.createMenuItem(mnEdit, "Copy", KeyEvent.VK_C, 1, "Copy the selected cell(s) to the clipboard");
mntmPaste = ccddMain.createMenuItem(mnEdit, "Paste (Ctrl-V)", KeyEvent.VK_V, 1, "Paste the clipboard contents at the current focus location");
mntmInsert = ccddMain.createMenuItem(mnEdit, "Insert", KeyEvent.VK_I, 1, "Insert the clipboard contents at the current focus location");
mnEdit.addSeparator();
mntmUndo = ccddMain.createMenuItem(mnEdit, "Undo (Ctrl-Z)", KeyEvent.VK_Z, 1, "Undo the last edit operation");
mntmRedo = ccddMain.createMenuItem(mnEdit, "Redo (Ctrl-Y)", KeyEvent.VK_Y, 1, "Redo the last undone edit operation");
mnEdit.addSeparator();
mntmInsertMacro = ccddMain.createMenuItem(mnEdit, "Insert macro", KeyEvent.VK_M, 1, "Insert a macro selected from the pop-up list");
mntmShowMacros = ccddMain.createCheckBoxMenuItem(mnEdit, "Show macros", KeyEvent.VK_S, 1, "Temporarily replace macro(s) with the corresponding value(s)", false);
mnEdit.addSeparator();
JMenu mnClearSelected = ccddMain.createSubMenu(mnEdit, "Replace selected", KeyEvent.VK_L, 1, null);
mntmWithBlanks = ccddMain.createMenuItem(mnClearSelected, "With blank", KeyEvent.VK_B, 1, "Replace the values in the selected cells with blanks");
mntmWithPrototype = ccddMain.createMenuItem(mnClearSelected, "With prototype", KeyEvent.VK_P, 1, "Replace the values in the selected cells with the prototype's values");
// Create the Row menu and menu items
JMenu mnRow = ccddMain.createMenu(menuBar, "Row", KeyEvent.VK_R, 1, null);
mntmInsertRow = ccddMain.createMenuItem(mnRow, "Insert row", KeyEvent.VK_I, 1, "Insert a row below the current focus location");
mntmDeleteRow = ccddMain.createMenuItem(mnRow, "Delete row(s)", KeyEvent.VK_D, 1, "Delete the currently selected row(s)");
mnRow.addSeparator();
mntmMoveUp = ccddMain.createMenuItem(mnRow, "Move up", KeyEvent.VK_U, 1, "Move the currently selected row(s) up one row");
mntmMoveDown = ccddMain.createMenuItem(mnRow, "Move down", KeyEvent.VK_N, 1, "Move the currently selected row(s) down one row");
mnRow.addSeparator();
mntmExpColArray = ccddMain.createCheckBoxMenuItem(mnRow, "Expand arrays", KeyEvent.VK_E, 1, "Expand/collapse display of array members", false);
JMenu mnOverwrite = ccddMain.createSubMenu(mnRow, "Array overwrite", KeyEvent.VK_O, 1, null);
mntmOverwriteAll = ccddMain.createRadioButtonMenuItem(mnOverwrite, "Overwrite all", KeyEvent.VK_A, 1, "Copy array definition value change to all members", true);
mntmOverwriteEmpty = ccddMain.createRadioButtonMenuItem(mnOverwrite, "Overwrite empty", KeyEvent.VK_E, 3, "Copy array definition value change only to empty members", false);
mntmOverwriteNone = ccddMain.createRadioButtonMenuItem(mnOverwrite, "Overwrite none", KeyEvent.VK_N, 1, "Do not copy definition value change to members", false);
ButtonGroup rbtnGroup = new ButtonGroup();
rbtnGroup.add(mntmOverwriteAll);
rbtnGroup.add(mntmOverwriteEmpty);
rbtnGroup.add(mntmOverwriteNone);
// Create the Column menu and menu items
JMenu mnColumn = ccddMain.createMenu(menuBar, "Column", KeyEvent.VK_M, 1, null);
mntmMoveLeft = ccddMain.createMenuItem(mnColumn, "Move left", KeyEvent.VK_L, 1, "Move the currently selected column(s) left one column");
mntmMoveRight = ccddMain.createMenuItem(mnColumn, "Move right", KeyEvent.VK_R, 1, "Move the currently selected column(s) right one column");
mntmResetOrder = ccddMain.createMenuItem(mnColumn, "Reset order", KeyEvent.VK_O, 1, "Reset the column order to the default");
// Create the Field menu and menu items
JMenu mnField = ccddMain.createMenu(menuBar, "Field", KeyEvent.VK_L, 1, null);
mntmManageFields = ccddMain.createMenuItem(mnField, "Manage fields", KeyEvent.VK_M, 1, "Open the data field manager");
mntmClearValues = ccddMain.createMenuItem(mnField, "Clear values", KeyEvent.VK_C, 1, "Clear the data field values");
// Add a listener for the Open Table command
mntmOpen.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Open a table in this editor dialog
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Open a table and add it to the tabbed pane. This calls TableSelectDialog, but
// doesn't spawn a separate editor
new CcddTableManagerDialog(ccddMain, ManagerDialogType.EDIT, CcddTableEditorDialog.this);
}
});
// Add a listener for the Open Prototype Table command
mntmOpenPrototype.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Open the currently displayed table's prototype table in this editor dialog
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Open the active table's prototype table
dbTable.loadTableDataInBackground(activeEditor.getTableInformation().getPrototypeName(), CcddTableEditorDialog.this);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Import command
mntmImport.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Import a file into the table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
fileIOHandler.importSelectedFileIntoTable(activeEditor);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Export - CSV command
mntmExportCSV.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Export the table to a file in CSV format
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
new CcddTableManagerDialog(ccddMain, ManagerDialogType.EXPORT_CSV, CcddTableEditorDialog.this);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Export - EDS command
mntmExportEDS.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Export the table to a file in EDS XML format
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
new CcddTableManagerDialog(ccddMain, ManagerDialogType.EXPORT_EDS, CcddTableEditorDialog.this);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Export - JSON command
mntmExportJSON.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Export the table to a file in JSON format
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
new CcddTableManagerDialog(ccddMain, ManagerDialogType.EXPORT_JSON, CcddTableEditorDialog.this);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Export - XTCE command
mntmExportXTCE.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Export the table to a file in XTCE XML format
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
new CcddTableManagerDialog(ccddMain, ManagerDialogType.EXPORT_XTCE, CcddTableEditorDialog.this);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Print command
mntmPrint.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Output the table to the printer
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Print the table
activeEditor.getTable().printTable("Table: " + activeEditor.getOwnerName(), activeEditor.getFieldHandler(), CcddTableEditorDialog.this, PageFormat.LANDSCAPE);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Search tables menu item
mntmSearchTable.addActionListener(new ActionListener() {
/**
************************************************************************************
* Display the search tables dialog
************************************************************************************
*/
@Override
public void actionPerformed(ActionEvent ae) {
ccddMain.showSearchDialog(SearchDialogType.TABLES, CcddTableEditorDialog.this);
}
});
// Add a listener for the Copy command
mntmCopy.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Copy the selected table cell(s) contents into the clipboard
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Send a Ctrl-C key press
controlKeyAction(KeyEvent.VK_C);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Paste command
mntmPaste.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Paste the clipboard contents in the table, overwriting any existing data in the
* target cells and adding new rows at the end of the table if needed
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Send a Ctrl-V key press
controlKeyAction(KeyEvent.VK_V);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Insert command
mntmInsert.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Insert the clipboard contents in the table, creating new rows to contain the data
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Send a ctrl-I key press
controlKeyAction(KeyEvent.VK_I);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Clear selected | With blanks command
mntmWithBlanks.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Erase the data in the selected cell(s)
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Check if there are any rows to clear
if (activeEditor.getTableModel().getRowCount() != 0) {
// Clear the selected cell(s)
activeEditor.getTable().deleteCell(false);
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Clear selected | With prototype command
mntmWithPrototype.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Erase the data in the selected cell(s) and the corresponding entry(s) in the custom
* values table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Check if there are any rows to clear
if (activeEditor.getTableModel().getRowCount() != 0) {
// Clear the selected cell(s)
activeEditor.getTable().deleteCell(true);
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the insert macro command
mntmInsertMacro.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Insert the macro chosen from the pop-up list into the current cell
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// and end values are valid
if (getTable().getLastSelectionStart() != -1 && getTable().getLastSelectionEnd() != -1) {
// Initiate editing in the selected cell
getTable().editCellAt(getTable().getSelectedRow(), getTable().getSelectedColumn());
// Get the cell's component
final Component comp = getTable().getEditorComponent();
// Check if the cell represents a text component (text area, text field, etc.)
if (comp instanceof JTextComponent) {
// Set the focus to the cell
comp.requestFocusInWindow();
// Execute the event after any pending events
EventQueue.invokeLater(new Runnable() {
/**
********************************************************************
* Set the selected text start and end positions
********************************************************************
*/
@Override
public void run() {
// Set the text selected text to the last known positions
((JTextComponent) comp).setSelectionStart(getTable().getLastSelectionStart());
((JTextComponent) comp).setSelectionEnd(getTable().getLastSelectionEnd());
}
});
}
// Send a Ctrl-M key press to display the insert macro pop-up
controlKeyAction(KeyEvent.VK_M);
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Show macros command
mntmShowMacros.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Temporarily replace any macros with the corresponding values
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// If the check box is selected then disable the controls that are not allowed
// while macros are shown, else enable the controls
setControlsEnabled(!mntmShowMacros.isSelected());
// Step through each table opened in the editor dialog
for (CcddTableEditorHandler editor : tableEditors) {
// Expand all macros in the table if the check box is selected and disable
// editing for the table, else restore all macros and enable editing
editor.expandMacros(mntmShowMacros.isSelected(), false);
editor.setTableEditEnable(!mntmShowMacros.isSelected());
}
// Redraw the visible table
activeEditor.getTable().repaint();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Store All command
mntmStoreAll.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Store the changes to all open table contents, if any, in the database
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// action
if (isTablesChanged() && new CcddDialogHandler().showMessageDialog(CcddTableEditorDialog.this, "<html><b>Store changes for all?", "Store Changes", JOptionPane.QUESTION_MESSAGE, DialogOption.OK_CANCEL_OPTION) == OK_BUTTON) {
// Update the database for every table that has changes
storeAllChanges();
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Reset Order command
mntmResetOrder.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Reset the column order to the default
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.resetColumnOrder();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Manage Fields command
mntmManageFields.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Manage the data fields
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Create the field editor dialog showing the fields for this table
new CcddFieldEditorDialog(ccddMain, activeEditor, activeEditor.getTableInformation().getTablePath(), (activeEditor.getTableTypeDefinition().isStructure() && !activeEditor.getTableInformation().getTablePath().contains(",")), MIN_WINDOW_WIDTH);
// Enable/disable the Clear values command depending on if any data fields remain
mntmClearValues.setEnabled(!activeEditor.getFieldHandler().getFieldInformation().isEmpty());
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add a listener for the Clear values command
mntmClearValues.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Clear the table data field values
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Check if there are any data fields to clear
if (!activeEditor.getFieldHandler().getFieldInformation().isEmpty()) {
// Remove all of the data field values from the table
activeEditor.getInputFieldPanelHandler().clearFieldValues();
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Create the lower (button) panel
JPanel buttonPnl = new JPanel();
// Define the buttons for the lower panel: New button
btnInsertRow = CcddButtonPanelHandler.createButton("Ins Row", INSERT_ICON, KeyEvent.VK_I, "Insert a new row into the table");
// Create a listener for the Insert Row command
ActionListener insertAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Insert a new row into the table at the selected location
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getTable().insertEmptyRow(true);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the insert listener to the Insert Row button and menu command
btnInsertRow.addActionListener(insertAction);
mntmInsertRow.addActionListener(insertAction);
// Delete button
btnDeleteRow = CcddButtonPanelHandler.createButton("Del Row", DELETE_ICON, KeyEvent.VK_D, "Delete the selected row(s) from the table");
// Create a listener for the Delete Row command
ActionListener deleteAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Delete the selected row(s) from the table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getTable().deleteRow(true);
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the delete listener to the Delete Row button and menu command
btnDeleteRow.addActionListener(deleteAction);
mntmDeleteRow.addActionListener(deleteAction);
// Create a listener for the Expand arrays command
mntmExpColArray.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Expand or collapse the array members
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// Toggle between showing and hiding the array member rows
activeEditor.showHideArrayMembers();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Move Up button
btnMoveUp = CcddButtonPanelHandler.createButton("Up", UP_ICON, KeyEvent.VK_U, "Move the selected row(s) up");
// Create a listener for the Move Up command
ActionListener moveUpAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Move the selected row(s) up in the table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getTable().moveRowUp();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the move up listener to the Move Up button and menu command
btnMoveUp.addActionListener(moveUpAction);
mntmMoveUp.addActionListener(moveUpAction);
// Move Down button
btnMoveDown = CcddButtonPanelHandler.createButton("Down", DOWN_ICON, KeyEvent.VK_N, "Move the selected row(s) down");
// Create a listener for the Move Down command
ActionListener moveDownAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Move the selected row(s) down in the table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getTable().moveRowDown();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the move down listener to the Move Down button and menu command
btnMoveDown.addActionListener(moveDownAction);
mntmMoveDown.addActionListener(moveDownAction);
// Move Left button
btnMoveLeft = CcddButtonPanelHandler.createButton("Left", LEFT_ICON, KeyEvent.VK_L, "Move the selected column(s) left");
// Create a listener for the Move Left command
ActionListener moveLeftAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Move the selected column(s) left in the table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getTable().moveColumnLeft();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the move left listener to the Move Left button and menu command
btnMoveLeft.addActionListener(moveLeftAction);
mntmMoveLeft.addActionListener(moveLeftAction);
// Move Right button
btnMoveRight = CcddButtonPanelHandler.createButton("Right", RIGHT_ICON, KeyEvent.VK_R, "Move the selected column(s) right");
// Create a listener for the Move Right command
ActionListener moveRightAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Move the selected column(s) right in the table
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getTable().moveColumnRight();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the move right listener to the Move Right button and menu command
btnMoveRight.addActionListener(moveRightAction);
mntmMoveRight.addActionListener(moveRightAction);
// Undo button
btnUndo = CcddButtonPanelHandler.createButton("Undo", UNDO_ICON, KeyEvent.VK_Z, "Undo the last edit action");
// Create a listener for the Undo command
ActionListener undoAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Undo the last cell edit
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getFieldPanelUndoManager().undo();
// Update the data field background colors
activeEditor.getInputFieldPanelHandler().setFieldBackgound();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the undo listener to the Undo button and menu command
mntmUndo.addActionListener(undoAction);
btnUndo.addActionListener(undoAction);
// Redo button
btnRedo = CcddButtonPanelHandler.createButton("Redo", REDO_ICON, KeyEvent.VK_Y, "Redo the last undone edit action");
// Create a listener for the Redo command
ActionListener redoAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Redo the last cell edit that was undone
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
activeEditor.getFieldPanelUndoManager().redo();
// Update the data field background colors
activeEditor.getInputFieldPanelHandler().setFieldBackgound();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the redo listener to the Redo button and menu command
mntmRedo.addActionListener(redoAction);
btnRedo.addActionListener(redoAction);
// Store button
btnStore = CcddButtonPanelHandler.createButton("Store", STORE_ICON, KeyEvent.VK_S, "Store the table updates in the database");
// Create a listener for the Store command
ActionListener storeAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Store the changes to the table contents, if any, in the database
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// required columns are empty, and the user confirms the action
if (activeEditor.isTableChanged() && !activeEditor.checkForMissingColumns() && new CcddDialogHandler().showMessageDialog(CcddTableEditorDialog.this, "<html><b>Store changes in project database?", "Store Changes", JOptionPane.QUESTION_MESSAGE, DialogOption.OK_CANCEL_OPTION) == OK_BUTTON) {
// Store the changes for the currently displayed editor in the database
storeChanges(activeEditor);
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the store listener to the Store button and menu command
btnStore.addActionListener(storeAction);
mntmStore.addActionListener(storeAction);
// Close button
btnCloseActive = CcddButtonPanelHandler.createButton("Close", CLOSE_ICON, KeyEvent.VK_C, "Close the table editor");
// Add a listener for the Close active table command
ActionListener closeAction = new ValidateCellActionListener() {
/**
************************************************************************************
* Close the active editor
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
// confirm discarding the changes
if (activeEditor.getTable().isLastCellValid() && (!activeEditor.isTableChanged() || new CcddDialogHandler().showMessageDialog(CcddTableEditorDialog.this, "<html><b>Discard changes?", "Discard Changes", JOptionPane.QUESTION_MESSAGE, DialogOption.OK_CANCEL_OPTION) == OK_BUTTON)) {
// Close the active table. If this is the only table in the editor then close
// the editor
closeTableEditor(activeEditor.getOwnerName());
}
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
};
// Add the close listener to the Close button and menu command
btnCloseActive.addActionListener(closeAction);
mntmCloseActive.addActionListener(closeAction);
// Create a listener for the Close All menu command
mntmCloseAll.addActionListener(new ValidateCellActionListener() {
/**
************************************************************************************
* Close the table editor
************************************************************************************
*/
@Override
protected void performAction(ActionEvent ae) {
windowCloseButtonAction();
}
/**
************************************************************************************
* Get the reference to the currently displayed table
************************************************************************************
*/
@Override
protected CcddJTableHandler getTable() {
return activeEditor.getTable();
}
});
// Add buttons in the order in which they'll appear (left to right, top to bottom)
buttonPnl.add(btnInsertRow);
buttonPnl.add(btnMoveUp);
buttonPnl.add(btnMoveLeft);
buttonPnl.add(btnUndo);
buttonPnl.add(btnStore);
buttonPnl.add(btnDeleteRow);
buttonPnl.add(btnMoveDown);
buttonPnl.add(btnMoveRight);
buttonPnl.add(btnRedo);
buttonPnl.add(btnCloseActive);
// Distribute the buttons across two rows
setButtonRows(2);
// Table Editors //////////////////////////////////////////////////////////////////////////
// Create a tabbed pane for the editors to appear in
tabbedPane = new DnDTabbedPane(JTabbedPane.TOP, CcddTableEditorDialog.class, true) {
/**
************************************************************************************
* Update the table editor list order following a tab move
************************************************************************************
*/
@Override
protected Object tabMoveCleanup(int oldTabIndex, int newTabIndex, Object tabContents) {
CcddTableEditorHandler editor = (CcddTableEditorHandler) tabContents;
// Check if the tab originated in the editor dialog
if (oldTabIndex != -1) {
// Get the reference to the moved tab's original location in the list
editor = tableEditors.get(oldTabIndex);
// Remove the table editor reference associated with the tab
tableEditors.remove(oldTabIndex);
} else // The tab originated in another editor dialog
{
// Bring the editor dialog to the foreground
CcddTableEditorDialog.this.toFront();
}
// Check if the tab is to be placed within this editor
if (newTabIndex != -1) {
// Update the editor's reference to the dialog that owns it to this editor
// dialog
editor.setEditorDialog(CcddTableEditorDialog.this);
// Add the table editor reference at the specified location
tableEditors.add(newTabIndex - (oldTabIndex != -1 && newTabIndex > oldTabIndex ? 1 : 0), editor);
}
// Check if the last editor was removed from the dialog
if (tableEditors.isEmpty()) {
// Close the editor dialog
CcddTableEditorDialog.this.closeFrame();
} else // An editor remains in the dialog
{
// Update the active tab pointer
activeEditor = tableEditors.get(tabbedPane.getSelectedIndex());
}
return editor;
}
/**
************************************************************************************
* Move the specified tab's table to a new table editor dialog
************************************************************************************
*/
@Override
protected void spawnContainer(int tabIndex, Object tabContents) {
// Create a new table editor dialog and place the editor from the other dialog into
// it
ccddMain.getTableEditorDialogs().add(new CcddTableEditorDialog(ccddMain, (CcddTableEditorHandler) tabContents));
}
};
tabbedPane.setFont(ModifiableFontInfo.LABEL_BOLD.getFont());
// Listen for tab selection changes
tabbedPane.addChangeListener(new ChangeListener() {
/**
************************************************************************************
* Update the editor to the one associated with the selected tab
************************************************************************************
*/
@Override
public void stateChanged(ChangeEvent ce) {
// Check if the tab index is within bounds
if (tabbedPane.getSelectedIndex() >= 0 && tabbedPane.getSelectedIndex() < tableEditors.size()) {
// Set the active editor to the selected tab
activeEditor = tableEditors.get(tabbedPane.getSelectedIndex());
// Change the dialog's title to the active table's name
(CcddTableEditorDialog.this).setTitle(activeEditor.getOwnerName());
// Update the expand/collapse arrays check box
updateExpandArrayCheckBox();
// Check if the Show macros command is not in effect
if (!mntmShowMacros.isSelected()) {
// Update the editor controls state
setControlsEnabled(true);
}
}
}
});
// Add each table as a tab in the editor dialog tabbed pane
addTablePanes(tableInformation, editor);
// Set the first tab as the active editor
activeEditor = tableEditors.get(0);
// Display the table editor dialog
createFrame(ccddMain.getMainFrame(), tabbedPane, buttonPnl, null, activeEditor.getOwnerName(), null);
// Enable the editor controls
setControlsEnabled(true);
}
use of javax.swing.text.JTextComponent in project CCDD by nasa.
the class CcddTableEditorHandler method initialize.
/**
********************************************************************************************
* Create the table editor
********************************************************************************************
*/
private void initialize() {
// Set the table type definition
setTypeDefinition();
// Get the model column indices for columns with special input types
getSpecialColumnIndices();
// Create a copy of the table information
setCommittedInformation(tableInfo);
// Get the array size and index column indices and create a row filter to show/hide the
// array member rows if an array size column exists
setUpArraySizeColumn();
// Define the table editor JTable
table = new CcddJTableHandler(ModifiableSizeInfo.INIT_VIEWABLE_DATA_TABLE_ROWS.getSize()) {
/**
************************************************************************************
* Highlight any macros or special flags in the table cells
*
* @param component
* reference to the table cell renderer component
*
* @param text
* cell text
*
* @param isSelected
* true if the cell is to be rendered with the selection highlighted
*
* @param int
* row cell row, view coordinates
*
* @param column
* cell column, view coordinates
************************************************************************************
*/
@Override
protected void doSpecialRendering(Component component, String text, boolean isSelected, int row, int column) {
// Highlight any macro names in the table cell. Adjust the highlight color to
// account for the cell selection highlighting so that the macro is easily readable
macroHandler.highlightMacro(component, text, isSelected ? ModifiableColorInfo.INPUT_TEXT.getColor() : ModifiableColorInfo.TEXT_HIGHLIGHT.getColor());
// Highlight 'sizeof(data type)' instances
CcddDataTypeHandler.highlightSizeof(component, text, isSelected ? ModifiableColorInfo.INPUT_TEXT.getColor() : ModifiableColorInfo.TEXT_HIGHLIGHT.getColor());
// Highlight the flag that indicates the custom value for this cell is to be
// removed and the prototype's value used instead. Create a highlighter painter
DefaultHighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(isSelected ? ModifiableColorInfo.INPUT_TEXT.getColor() : Color.MAGENTA);
// Create the match pattern
Pattern pattern = Pattern.compile("^" + Pattern.quote(REPLACE_INDICATOR));
// Create the pattern matcher from the pattern
Matcher matcher = pattern.matcher(text);
// Check if there is a match in the cell value
if (matcher.find()) {
try {
// Highlight the matching text. Adjust the highlight color to account for
// the cell selection highlighting so that the search text is easily
// readable
((JTextComponent) component).getHighlighter().addHighlight(matcher.start(), matcher.end(), painter);
} catch (BadLocationException ble) {
// Ignore highlighting failure
}
}
}
/**
************************************************************************************
* Get the tool tip text for a table cell, showing any macro name replaced with its
* corresponding macro value
************************************************************************************
*/
@Override
public String getToolTipText(MouseEvent me) {
String toolTipText = null;
// Get the row and column of the cell over which the mouse pointer is hovering
Point point = me.getPoint();
int row = rowAtPoint(point);
int column = columnAtPoint(point);
// Check if a cell is beneath the mouse pointer
if (row != -1 && column != -1) {
// Expand any macros in the cell text and display this as the cell's tool tip
// text
toolTipText = macroHandler.getMacroToolTipText(getValueAt(row, column).toString());
}
return toolTipText;
}
/**
************************************************************************************
* Return true if the table data, column order, description, or a data field changes.
* If the table isn't open in and editor (as when a macro is changed) then the table
* description and data fields are not applicable
************************************************************************************
*/
@Override
protected boolean isTableChanged(Object[][] previousData, List<Integer> ignoreColumns) {
boolean isFieldChanged = false;
// and/or value change)
if (editorDialog != null) {
// Update the field information with the current text field values
updateCurrentFieldValues(tableInfo.getFieldHandler().getFieldInformation());
// Set the flag if the number of fields, field attributes, or field contents
// have changed
isFieldChanged = CcddFieldHandler.isFieldChanged(tableInfo.getFieldHandler().getFieldInformation(), committedInfo.getFieldHandler().getFieldInformation(), false);
}
return super.isTableChanged(previousData, ignoreColumns) || isFieldChanged || !getColumnOrder().equals(committedInfo.getColumnOrder()) || (editorDialog != null && !committedInfo.getDescription().equals(getDescription()));
}
/**
************************************************************************************
* Allow multiple line display in all columns
************************************************************************************
*/
@Override
protected boolean isColumnMultiLine(int column) {
return true;
}
/**
************************************************************************************
* Hide the the specified columns
************************************************************************************
*/
@Override
protected boolean isColumnHidden(int column) {
return column == primaryKeyIndex || column == rowIndex;
}
/**
************************************************************************************
* Override isCellEditable to determine which cells can be edited
************************************************************************************
*/
@Override
public boolean isCellEditable(int row, int column) {
// Initialize the flag to the table edit flag (based on the table edit flag this
// enables normal editing or disables editing any cell)
boolean isEditable = isEditEnabled;
// one row
if (isEditable && (isDisplayable() || editorDialog == null) && tableModel != null && tableModel.getRowCount() != 0) {
// Convert the view row and column indices to model coordinates
int modelRow = convertRowIndexToModel(row);
int modelColumn = convertColumnIndexToModel(column);
// Check if the cell is editable
isEditable = isDataAlterable(((List<?>) tableModel.getDataVector().elementAt(modelRow)).toArray(new String[0]), modelRow, modelColumn);
}
return isEditable;
}
/**
************************************************************************************
* Override isDataAlterable to determine which table data values can be changed
*
* @param rowData
* array containing the table row data
*
* @param row
* table row index in model coordinates
*
* @param column
* table column index in model coordinates
*
* @return true if the data value can be changed
************************************************************************************
*/
@Override
protected boolean isDataAlterable(Object[] rowData, int row, int column) {
boolean isAlterable = true;
// Check if the table data has at least one row
if (rowData != null && rowData.length != 0) {
// Copy the row of table data. This prevents the macro expansions for array
// size and bit length below from changing the cell contents
Object[] rowCopy = Arrays.copyOf(rowData, rowData.length);
// Check if the array size column is present in this table
if (arraySizeIndex != -1) {
// Expand any macros in the array size column
rowCopy[arraySizeIndex] = newMacroHandler.getMacroExpansion(rowCopy[arraySizeIndex].toString());
}
// Check if the array size column is present in this table
if (bitLengthIndex != -1) {
// Expand any macros in the array size column
rowCopy[bitLengthIndex] = newMacroHandler.getMacroExpansion(rowCopy[bitLengthIndex].toString());
}
// Flag that is true if the row represents an array definition
boolean isArrayDefinition = arraySizeIndex != -1 && variableNameIndex != -1 && !rowCopy[arraySizeIndex].toString().isEmpty() && !ArrayVariable.isArrayMember(rowCopy[variableNameIndex]);
// Check if the cell is non-alterable based on the following criteria:
if (// this is not a prototype table
((column == variableNameIndex || column == dataTypeIndex || column == arraySizeIndex || column == bitLengthIndex) && !tableInfo.isPrototype()) || // displays an array member
((column == variableNameIndex || column == dataTypeIndex || column == arraySizeIndex) && ArrayVariable.isArrayMember(rowCopy[variableNameIndex])) || // isn't valid for structures
(dataTypeIndex != -1 && !dataTypeHandler.isPrimitive(rowCopy[dataTypeIndex].toString()) && !typeDefn.isStructureAllowed()[column]) || // This data type is a pointer and the column isn't valid for pointers
(dataTypeIndex != -1 && dataTypeHandler.isPointer(rowCopy[dataTypeIndex].toString()) && !typeDefn.isPointerAllowed()[column]) || // This is the enumeration or rate cell in a row displaying an array definition
((isArrayDefinition && enumerationIndex.contains(column) && rateIndex.contains(column))) || // type is not an integer (signed or unsigned)
(column == bitLengthIndex && ((arraySizeIndex != -1 && !rowCopy[arraySizeIndex].toString().isEmpty()) || (dataTypeIndex != -1 && !dataTypeHandler.isInteger(rowCopy[dataTypeIndex].toString())))) || // length is present
(column == arraySizeIndex && ((variableNameIndex != -1 && rowCopy[variableNameIndex].toString().isEmpty()) || (bitLengthIndex != -1 && !rowCopy[bitLengthIndex].toString().isEmpty()))) || // This is a rate cell, and a data type exists that is not a primitive
(rateIndex.contains(column) && dataTypeIndex != -1 && !rowCopy[dataTypeIndex].toString().isEmpty() && !dataTypeHandler.isPrimitive(rowCopy[dataTypeIndex].toString())) || // first array member
(variableNameIndex != -1 && dataTypeIndex != -1 && dataTypeHandler.isString(rowCopy[dataTypeIndex].toString()) && ArrayVariable.isArrayMember(rowCopy[variableNameIndex]) && !rowCopy[variableNameIndex].toString().endsWith("[0]")) || // the variable path
(isArrayDefinition && (typeDefn.getInputTypes()[column].equals(InputDataType.MESSAGE_ID) || column == variablePathIndex)) || // variables in a non-root prototype structure
(column == variablePathIndex && rowCopy[variablePathIndex].toString().isEmpty())) {
// Set the flag to prevent altering the data value
isAlterable = false;
} else // Check the column groupings
{
// Step through each column grouping
for (AssociatedColumns colGrp : associatedColumns) {
// Check if the cell is non-alterable based on the following criteria:
if ((// isn't an integer type (signed or unsigned)
column == colGrp.getEnumeration() && !dataTypeHandler.isInteger(rowCopy[colGrp.getDataType()].toString())) || // defined
((column == colGrp.getMinimum() || column == colGrp.getMaximum()) && rowCopy[colGrp.getDataType()].toString().isEmpty())) {
// Set the flag to prevent altering the data value and stop
// searching
isAlterable = false;
break;
}
}
// Check if no command argument pairing reset the flag
if (isAlterable) {
// Step through each non-command argument minimum/maximum pairing
for (MinMaxPair minMax : minMaxPair) {
// is missing, empty, or isn't a primitive type
if (dataTypeIndex != -1 && (rowCopy[dataTypeIndex].toString().isEmpty() || !dataTypeHandler.isPrimitive(rowCopy[dataTypeIndex].toString())) && (column == minMax.getMinimum() || column == minMax.getMaximum())) {
// Set the flag to prevent altering the data value and stop
// searching
isAlterable = false;
break;
}
}
}
}
}
return isAlterable;
}
/**
************************************************************************************
* Override getCellEditor so that for a data type column cell in a row where the
* enumeration cell isn't empty the combo box editor that displays only integer data
* types (signed and unsigned) is returned; for all other cells return the normal cell
* editor
*
* @param row
* table view row number
*
* @param column
* table view column number
*
* @return The cell editor for the specified row and column
************************************************************************************
*/
@Override
public TableCellEditor getCellEditor(int row, int column) {
// Get the editor for this cell
TableCellEditor cellEditor = super.getCellEditor(row, column);
// Convert the row and column indices to the model coordinates
int modelRow = convertRowIndexToModel(row);
int modelColumn = convertColumnIndexToModel(column);
// column and the bit length cell is not empty
if (modelColumn == dataTypeIndex && bitLengthIndex != -1 && !getExpandedValueAt(modelRow, bitLengthIndex).isEmpty()) {
// Select the combo box cell editor that displays only integer data types
// (signed and unsigned)
cellEditor = enumDataTypeCellEditor;
} else // Check if this is a data type and enumeration pairing or a command argument
// column grouping
{
// Step through each column grouping
for (AssociatedColumns colGrp : associatedColumns) {
// type column, and that the associated enumeration cell isn't blank
if (modelColumn == colGrp.getDataType() && colGrp.getEnumeration() != -1 && !getExpandedValueAt(modelRow, colGrp.getEnumeration()).isEmpty()) {
// Select the combo box cell editor that displays only integer data
// types (signed and unsigned) and stop searching
cellEditor = enumDataTypeCellEditor;
break;
}
}
}
return cellEditor;
}
/**
************************************************************************************
* Validate changes to the editable cells; e.g., verify cell content and, if found
* invalid, revert to the original value. Update array members if needed
*
* @param tableData
* list containing the table data row arrays
*
* @param row
* table model row index
*
* @param column
* table model column index
*
* @param oldValue
* original cell contents
*
* @param newValue
* new cell contents
*
* @param showMessage
* true to display the invalid input dialog, if applicable
*
* @param isMultiple
* true if this is one of multiple cells to be entered and checked; false if
* only a single input is being entered
*
* @return true to indicate that subsequent errors should be displayed; false if
* subsequent errors should not be displayed; null if the operation should be
* canceled
************************************************************************************
*/
@Override
protected Boolean validateCellContent(List<Object[]> tableData, int row, int column, Object oldValue, Object newValue, Boolean showMessage, boolean isMultiple) {
// Reset the flag that indicates the last edited cell's content is invalid
setLastCellValid(true);
try {
// Set the parameters that govern recalculating packed variables to begin with
// the first row in the table and to use the first variable in the pack to set
// the rates for other variables in the same pack
int startRow = 0;
boolean useRowRate = false;
// Create a string version of the new value, replacing any macro in the text
// with its corresponding value
String newValueS = newMacroHandler.getMacroExpansion(newValue.toString(), validDataTypes);
// to this structure's prototype or the prototype of one of its children
if (variableHandler.isInvalidReference()) {
throw new CCDDException("Invalid input value in column '</b>" + typeDefn.getColumnNamesUser()[column] + "<b>'; data type invalid or unknown in sizeof() call");
}
// Check if the cell is flagged for replacement by the prototype value
if (newValueS.startsWith(REPLACE_INDICATOR)) {
// Remove the flag so that the updated value is stored as a custom value
newValueS = newValueS.replaceFirst("^" + REPLACE_INDICATOR, "");
}
// Check that the new value isn't blank
if (!newValueS.isEmpty()) {
// Check if the values in this column must not be duplicated
if (typeDefn.isRowValueUnique()[column]) {
// Step through each row in the table
for (int otherRow = 0; otherRow < tableData.size(); otherRow++) {
// matches the one being added (case insensitive)
if (otherRow != row && newValueS.equalsIgnoreCase(getExpandedValueAt(tableData, otherRow, column))) {
throw new CCDDException("Invalid input value for column '</b>" + typeDefn.getColumnNamesUser()[column] + "<b>'; value must be unique");
}
}
}
// Step through each column grouping
for (AssociatedColumns colGrp : associatedColumns) {
// Check if this is a name column
if (column == colGrp.getName()) {
// Step through the column groupings
for (AssociatedColumns otherColGrp : associatedColumns) {
// name matches the name of another command argument
if (!colGrp.equals(otherColGrp) && newValueS.equals(getExpandedValueAt(tableData, row, otherColGrp.getName()))) {
throw new CCDDException("Invalid input value for column '</b>" + typeDefn.getColumnNamesUser()[column] + "<b>'; command argument names must be unique for a command");
}
}
} else // Check if this is the minimum or maximum value columns
if (column == colGrp.getMinimum() || column == colGrp.getMaximum()) {
// Verify that the minimum/maximum value is valid for the
// argument's data type, and stop searching
validateMinMaxContent(tableData, row, column, newValueS, colGrp.getDataType(), colGrp.getMinimum(), colGrp.getMaximum());
break;
}
}
// Step through each minimum/maximum pairing
for (MinMaxPair minMax : minMaxPair) {
// Check if this is the minimum or maximum value columns
if (column == minMax.getMinimum() || column == minMax.getMaximum()) {
// Verify that the minimum/maximum value is valid for the
// argument's data type, and stop searching
validateMinMaxContent(tableData, row, column, newValueS, dataTypeIndex, minMax.getMinimum(), minMax.getMaximum());
break;
}
}
// Check if the value doesn't match the expected input type
if (!newValueS.matches(typeDefn.getInputTypes()[column].getInputMatch())) {
throw new CCDDException("Invalid characters in column '</b>" + typeDefn.getColumnNamesUser()[column] + "<b>'; characters consistent with input type '" + typeDefn.getInputTypes()[column].getInputName() + "' expected");
}
// Check if this is a message ID name column
if (msgIDNameIndex.contains(column)) {
// The message ID, which is included with the ID name in the combo box
// list, doesn't appear when the item is selected from the list, so
// remove the ID
newValueS = newValueS.replaceFirst(" \\(.*", "");
}
}
// Flag that indicates that the new cell value contains a macro and/or a
// sizeof() call
boolean hasMacroSizeof = CcddMacroHandler.hasMacro(newValue.toString()) || CcddVariableSizeAndConversionHandler.hasSizeof(newValue.toString());
// prevents the macro reference from being lost
if (!hasMacroSizeof) {
// Store the new value in the table data array after formatting the cell
// value per its input type. This is needed primarily to clean up numeric
// formatting
newValueS = typeDefn.getInputTypes()[column].formatInput(newValueS);
newValue = newValueS;
tableData.get(row)[column] = newValueS;
}
// Replace any macro in the original text with its corresponding value
String oldValueS = macroHandler.getMacroExpansion(oldValue.toString());
// original text with its corresponding value
if (!newValueS.equals(oldValueS)) {
String variableName = null;
String dataType = null;
String arraySize = null;
String bitLength = null;
// Check if the variable name column exists
if (variableNameIndex != -1) {
// Get the variable name for the current row, expanding macros in the
// name (if present)
variableName = getExpandedValueAt(tableData, row, variableNameIndex);
}
// Check if the data type column exists
if (dataTypeIndex != -1) {
// Get the data type for the current row
dataType = tableData.get(row)[dataTypeIndex].toString();
}
// Check if the array size column exists
if (arraySizeIndex != -1) {
// Get the array size for the current row, expanding macros in the
// value (if present)
arraySize = getExpandedValueAt(tableData, row, arraySizeIndex);
}
// Check if the bit length column exists
if (bitLengthIndex != -1) {
// Get the bit length for the current row, expanding macros in the
// value (if present)
bitLength = getExpandedValueAt(tableData, row, bitLengthIndex);
}
// Check if the variable name or data type has been changed
if (column == variableNameIndex || column == dataTypeIndex) {
// if a data type is pasted into the cell
if (invalidDataTypes != null && invalidDataTypes.contains(dataType)) {
throw new CCDDException("Data type '</b>" + dataType + "<b>' invalid; structure cannot reference itself or an ancestor");
}
// Check if the variable is an array
if (arraySize != null) {
// and the bit length exceeds the size of the data type in bits
if (column == dataTypeIndex && !newValueS.isEmpty() && bitLength != null && !bitLength.isEmpty() && Integer.valueOf(bitLength) > newDataTypeHandler.getSizeInBits(dataType)) {
throw new CCDDException("Bit length exceeds the size of the data type");
}
// Get the array index values from the array size column and update
// array members if this is an array definition
int[] arrayDims = ArrayVariable.getArrayIndexFromSize(arraySize);
adjustArrayMember(tableData, arrayDims, arrayDims, row, column);
}
// manually set
if (variablePathIndex != -1 && tableData.get(row)[variablePathIndex].toString().equals(getVariablePath((column == variableNameIndex ? oldValueS : variableName), (column == dataTypeIndex ? oldValueS : dataType), true))) {
// Update the variable path with the new variable name and/or data
// type
tableData.get(row)[variablePathIndex] = getVariablePath(variableName, dataType, true);
}
} else // Check if this is the array size column
if (column == arraySizeIndex) {
// Get the original and updated array index values
int[] arraySizeOld = ArrayVariable.getArrayIndexFromSize(oldValueS);
int[] arraySizeNew = ArrayVariable.getArrayIndexFromSize(newValueS);
// Set the flag that indicates the array index values changed based on
// the number of index values changing
boolean isDifferent = arraySizeOld.length != arraySizeNew.length;
// individual array index values must be compared
if (!isDifferent) {
// Step through each index value
for (int index = 0; index < arraySizeOld.length; index++) {
// Check if the original and updated values differ
if (arraySizeOld[index] != arraySizeNew[index]) {
// Set the flag to indicate an index value changed and stop
// searching
isDifferent = true;
break;
}
}
}
// Check if the original and updated values differ
if (isDifferent) {
// Add or remove array members to match the new array size
adjustArrayMember(tableData, arraySizeOld, arraySizeNew, row, column);
}
} else // Check if this is the rate column and the row is an array definition
if (rateIndex.contains(column) && arraySize != null && variableName != null && !arraySize.isEmpty() && !ArrayVariable.isArrayMember(variableName)) {
// Get the array index value(s)
int[] arrayDims = ArrayVariable.getArrayIndexFromSize(arraySize);
// Update the array members with the new rate
adjustArrayMember(tableData, arrayDims, arrayDims, row, column);
} else // Check if this is the rate column and the variable has a bit length value
if (rateIndex.contains(column) && bitLength != null && dataType != null && !bitLength.isEmpty()) {
// Adjust the rates of any other bit-wise variables that are packed
// together with this variable, using this row's rate
startRow = row;
useRowRate = true;
} else // Check if this is the bit length column
if (column == bitLengthIndex) {
// data type
if (bitLength != null && !bitLength.isEmpty() && dataType != null && Integer.valueOf(bitLength) > newDataTypeHandler.getSizeInBits(dataType)) {
throw new CCDDException("Bit length exceeds the size of the data type");
}
// Adjust the rates of any other bit-wise variables that are packed
// together with this variable, using the first packed variable's rate
startRow = row;
} else // Check if this is the variable path column
if (column == variablePathIndex && variableName != null && !variableName.isEmpty() && dataType != null && !dataType.isEmpty()) {
// entered
if (!newValueS.isEmpty()) {
// another structure table
if (variableHandler.isVariablePathInUse(tableInfo.getTablePath() + "," + dataType + "." + variableName, newValueS)) {
throw new CCDDException("Variable path already in use in another structure");
}
} else // The cell has been blanked
{
// Build the variable path from the variable name and data type
tableData.get(row)[variablePathIndex] = getVariablePath(variableName, dataType, false);
}
} else // array
if (variableName != null && dataType != null && arraySize != null && column != variableNameIndex && column != dataTypeIndex && column != arraySizeIndex && column != variablePathIndex && !arraySize.isEmpty() && (!ArrayVariable.isArrayMember(variableName) || newDataTypeHandler.isString(dataType))) {
// Propagate the value to all members of this array/string
propagateArrayValues(tableData, row, column);
}
// Clear the contents of any cells that are no longer valid in this row
clearInvalidCells(tableData.get(row), row);
// Adjust the rates of the bit-wise variables that are packed together,
// beginning at the indicated row
setAllPackedVariableRates(tableData, startRow, useRowRate);
// Check if the new value contains any macros
if (hasMacroSizeof) {
// Store the new value, with the macro(s) restored, into the table data
// array
tableData.get(row)[column] = newValue;
}
} else // vice versa)
if (!newValue.equals(oldValue)) {
// Store the new value in the table data array
tableData.get(row)[column] = newValue;
// Check if the column is the array size
if (column == arraySizeIndex) {
// Propagate the value to all members of this array/string
propagateArrayValues(tableData, row, column);
}
} else // The cell value didn't change
{
// Pop the edit from the stack
table.getUndoManager().undoRemoveEdit();
}
} catch (CCDDException ce) {
// Set the flag that indicates the last edited cell's content is invalid
setLastCellValid(false);
// Check if the error message dialog should be displayed
if (showMessage) {
// Check if this is a single cell insert
if (!isMultiple) {
// Inform the user that the input value is invalid
new CcddDialogHandler().showMessageDialog(editorDialog, "<html><b>" + ce.getMessage(), "Invalid Input", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
} else // This is one of multiple cells being inserted
{
// Inform the user that the input value is invalid
CcddDialogHandler validityDlg = new CcddDialogHandler();
int buttonSelected = validityDlg.showIgnoreCancelDialog(editorDialog, "<html><b>" + ce.getMessage(), "Invalid Input", "Ignore this invalid input", "Ignore this and any remaining invalid inputs for this table", "Cease inputting values");
// Check if the Ignore All button was pressed
if (buttonSelected == IGNORE_BUTTON) {
// Set the flag to ignore subsequent input errors
showMessage = false;
} else // Check if the Cancel button was pressed
if (buttonSelected == CANCEL_BUTTON) {
// Set the flag to cancel updating the cells
showMessage = null;
}
}
}
// Restore the cell contents to its original value and pop the edit from the
// stack
tableData.get(row)[column] = oldValue;
table.getUndoManager().undoRemoveEdit();
}
return showMessage;
}
/**
************************************************************************************
* Clear the contents of cells in the specified row that are no longer valid due to the
* contents of other cells
*
* @param tableData
* list containing the table data row arrays
*
* @param row
* table model row index
************************************************************************************
*/
private void clearInvalidCells(Object[] rowData, int row) {
// Step through each visible column
for (int column = 0; column < getColumnCount(); column++) {
// Get the column index in model coordinates
int modelColumn = convertColumnIndexToModel(column);
if (// rate, or variable path column, and that the cell is not alterable
(modelColumn != variableNameIndex && modelColumn != dataTypeIndex && modelColumn != arraySizeIndex && modelColumn != bitLengthIndex && modelColumn != variablePathIndex && !rateIndex.contains(modelColumn) && !isDataAlterable(rowData, row, modelColumn)) || // (i.e., it's a structure), and structures are not allowed for this column
(dataTypeIndex != -1 && !newDataTypeHandler.isPrimitive(rowData[dataTypeIndex].toString()) && !typeDefn.isStructureAllowed()[modelColumn]) || // pointers are not allowed for this column
(dataTypeIndex != -1 && newDataTypeHandler.isPointer(rowData[dataTypeIndex].toString()) && !typeDefn.isPointerAllowed()[modelColumn]) || // data type isn't a primitive
(dataTypeIndex != -1 && modelColumn == bitLengthIndex && !newDataTypeHandler.isPrimitive(rowData[dataTypeIndex].toString()))) {
// Clear the contents of the cell
rowData[modelColumn] = "";
}
}
}
/**
************************************************************************************
* Load the database values into the table and format the table cells
************************************************************************************
*/
@Override
protected void loadAndFormatData() {
// Place the data into the table model along with the column names, set up the
// editors and renderers for the table cells, set up the table grid lines, and
// calculate the minimum width required to display the table information
int totalWidth = setUpdatableCharacteristics(committedInfo.getData(), typeDefn.getColumnNamesUser(), committedInfo.getColumnOrder(), toolTips, true, true, true);
// editor dialog
if (editorDialog != null) {
// Get the minimum width needed to display all columns, but no wider than the
// display
int width = Math.min(totalWidth + LAF_SCROLL_BAR_WIDTH, GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth());
// Check if the editor's width is less than the minimum
if (editorDialog.getTableWidth() < width) {
// Set the initial and preferred editor size
editorDialog.setTableWidth(width);
editorDialog.setPreferredSize(new Dimension(width, editorDialog.getPreferredSize().height));
}
}
// Create the drop-down combo box for the column with the name 'data type' that
// displays the available data types, including primitive types and the names of
// tables that represent structures, and add a mouse listener to handle mouse click
// events. Set up any command argument data type, argument name, enumeration,
// minimum, and maximum groupings
setUpDataTypeColumns(null, null);
// Set up any minimum and maximum pairings (excluding those associated with command
// argument groupings)
setUpMinMaxColumns();
// Create drop-down combo boxes that display the available sample rates for the
// "Rate" column
setUpSampleRateColumn();
// Create drop-down combo boxes that display the available message ID names and
// values
setUpMsgNamesAndIDsColumn(null);
// Create the mouse listener for the data type column
createDataTypeColumnMouseListener();
}
/**
************************************************************************************
* Override prepareRenderer to allow adjusting the background colors of table cells
************************************************************************************
*/
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
JComponent comp = (JComponent) super.prepareRenderer(renderer, row, column);
// highlight colors override the invalid highlight color
if (comp.getBackground() != ModifiableColorInfo.FOCUS_BACK.getColor() && comp.getBackground() != ModifiableColorInfo.SELECTED_BACK.getColor()) {
// contain an item in the list
if (!isCellValueFound(row, column)) {
// Change the cell's background color
comp.setBackground(ModifiableColorInfo.REQUIRED_BACK.getColor());
} else // Check if this cell is protected from changes
if (!isCellEditable(row, column)) {
// Change the cell's text and background colors
comp.setForeground(ModifiableColorInfo.PROTECTED_TEXT.getColor());
comp.setBackground(ModifiableColorInfo.PROTECTED_BACK.getColor());
} else // variable
if (variableNameIndex != -1 && getExpandedValueAt(table.convertRowIndexToModel(row), variableNameIndex).toString().matches(PAD_VARIABLE + "[0-9]+(?:\\[[0-9]+\\])?$")) {
// Change the cell's background color
comp.setBackground(ModifiableColorInfo.PADDING_BACK.getColor());
}
}
return comp;
}
/**
************************************************************************************
* Override the CcddJTableHandler method to handle right double click events on the
* array size cells in order to show/hide the array index column and array member rows,
* and to handle sorting of columns based on their input type
************************************************************************************
*/
@Override
protected void setTableSortable() {
super.setTableSortable();
// Get the table's row sorter
TableRowSorter<?> sorter = (TableRowSorter<?>) getRowSorter();
// Create a runnable object to be executed
SwingUtilities.invokeLater(new Runnable() {
/**
****************************************************************************
* Execute after all pending Swing events are finished. This allows the number
* of viewable columns to catch up with the column model when a column is
* removed
****************************************************************************
*/
@Override
public void run() {
// Issue a table change event so that the new row is displayed properly
// when the array view is collapsed. Can't use tableModel here since it
// isn't set when the first call to this method is made
((UndoableTableModel) table.getModel()).fireTableStructureChanged();
}
});
// Check if the table has a sorter (i.e., has at least one row)
if (sorter != null) {
// filter
if (sorter.getRowFilter() == null && rowFilter != null) {
// Apply the row filter that shows/hides the array members
sorter.setRowFilter(rowFilter);
}
// Step through each table column
for (int column = 0; column < table.getModel().getColumnCount(); column++) {
// Get the input type format for this column
final InputTypeFormat inputFormat = typeDefn.getInputTypes()[column].getInputFormat();
// Add a column sort comparator
sorter.setComparator(column, new Comparator<String>() {
/**
********************************************************************
* Override the comparison when sorting columns to account for the
* column's input type format. Note that macros aren't expanded when
* sorting. Though expansion provides an accurate sort, visually it's
* confusing since the macro values aren't readily apparent. For
* columns with a numeric input type that contain macros then initial
* numeric portion (if any) if used when sorting
********************************************************************
*/
@Override
public int compare(String cell1, String cell2) {
Integer result = 0;
// Check if either cell is empty
if (cell1.isEmpty() || cell2.isEmpty()) {
// Compare as text (alphabetically)
result = cell1.compareTo(cell2);
} else // Neither cell is empty
{
// type
switch(inputFormat) {
case TEXT:
case DATA_TYPE:
case ENUMERATION:
case PAGE_FORMAT:
case VARIABLE_PATH:
case BOOLEAN:
// Compare as text (alphabetically)
result = cell1.compareTo(cell2);
break;
default:
// number
if (cell1.matches(InputDataType.INTEGER.getInputMatch() + ".*") && cell2.matches(InputDataType.INTEGER.getInputMatch() + ".*")) {
switch(inputFormat) {
case INTEGER:
// Compare the two cell values as integers
result = Integer.compare(Integer.valueOf(cell1.replaceAll("(" + InputDataType.INTEGER.getInputMatch() + ").*", "$1")), Integer.valueOf(cell2.replaceAll("(" + InputDataType.INTEGER.getInputMatch() + ").*", "$1")));
break;
case HEXADECIMAL:
// Compare the two cell values as integers
result = Integer.compare(Integer.decode(cell1.replaceAll("(" + InputDataType.HEXADECIMAL.getInputMatch() + ").*", "$1")), Integer.decode(cell2.replaceAll("(" + InputDataType.HEXADECIMAL.getInputMatch() + ").*", "$1")));
break;
case FLOAT:
case MINIMUM:
case MAXIMUM:
// Compare the two cell values as floating
// points
result = Double.compare(Double.valueOf(cell1.replaceAll("(" + InputDataType.FLOAT.getInputMatch() + ").*", "$1")), Double.valueOf(cell2.replaceAll("(" + InputDataType.FLOAT.getInputMatch() + ").*", "$1")));
break;
case RATE:
// Calculate the value of the cells'
// expressions, then compare the results as
// floating point values
result = Double.compare(CcddMathExpressionHandler.evaluateExpression(cell1), CcddMathExpressionHandler.evaluateExpression(cell2));
break;
case ARRAY:
// Array sizes are in the format #<,#<...>.
// Each cell's array dimensions are first
// separated, then the first dimension is
// compared between the two cells, then the
// second, and so on until a mismatch is
// found; the sort is performed based on
// the mismatch (e.g., '1, 2' follows '1'
// when sorted in ascending order)
String[] dim1 = cell1.split("\\s*,\\s*");
String[] dim2 = cell2.split("\\s*,\\s*");
// same dimensions than the second
if (dim1.length == dim2.length) {
// long as there's no mismatch
for (int index = 0; index < dim1.length && result == 0; index++) {
// sizeof() call)
if (dim1[index].matches(InputDataType.INTEGER.getInputMatch()) && dim2[index].matches(InputDataType.INTEGER.getInputMatch())) {
// Compare the two array
// dimensions
result = Integer.compare(Integer.valueOf(dim1[index]), Integer.valueOf(dim2[index]));
} else // One or both dimension values
// isn't a number
{
// Compare as text
// (alphabetically)
result = dim1[index].compareTo(dim2[index]);
}
}
} else // fewer dimensions than the second
if (dim1.length < dim2.length) {
// long as there's no mismatch
for (int index = 0; index < dim1.length && result == 0; index++) {
// sizeof() call)
if (dim1[index].matches(InputDataType.INTEGER.getInputMatch()) && dim2[index].matches(InputDataType.INTEGER.getInputMatch())) {
// Compare the two array
// dimensions
result = Integer.compare(Integer.valueOf(dim1[index]), Integer.valueOf(dim2[index]));
} else // One or both dimension values
// isn't a number
{
// Compare as text
// (alphabetically)
result = dim1[index].compareTo(dim2[index]);
}
}
// dimension values are identical
if (result == 0) {
// Set the result to indicate the
// first cell comes before the
// second since the second has more
// dimensions
result = -1;
}
} else // The first array size has the more
// dimensions than the second
{
// long as there's no mismatch
for (int index = 0; index < dim2.length && result == 0; index++) {
// sizeof() call)
if (dim1[index].matches(InputDataType.INTEGER.getInputMatch()) && dim2[index].matches(InputDataType.INTEGER.getInputMatch())) {
// Compare the two array
// dimensions
result = Integer.compare(Integer.valueOf(dim1[index]), Integer.valueOf(dim2[index]));
} else // One or both dimension values
// isn't a number
{
// Compare as text
// (alphabetically)
result = dim1[index].compareTo(dim2[index]);
}
}
// dimension values are identical
if (result == 0) {
// Set the result to indicate the
// first cell comes after the
// second since the second has
// fewer dimensions
result = 1;
}
}
break;
default:
break;
}
} else // One or both cells doesn't begin with a number (this
// is the case if the cell begins with a macro or
// sizeof() call)
{
// Compare as text (alphabetically)
result = cell1.compareTo(cell2);
}
}
}
return result;
}
});
}
}
}
/**
************************************************************************************
* Move the selected row(s) in the specified direction if possible. Account for if the
* selection or target is an array definition or member
*
* @param rowDelta
* row move direction (-1 for up, +1 for down)
************************************************************************************
*/
private void adjustAndMoveSelectedRows(int rowDelta) {
int modelStartRow;
int modelEndRow;
boolean isCanMove = false;
// Set the selected start and end rows
MoveCellSelection selected = new MoveCellSelection();
// Set the selected start and end rows (model coordinates), and the direction to
// move
modelStartRow = selected.getStartRow();
modelEndRow = selected.getEndRow();
// Check if the selected row(s) can be moved in the desired direction
if ((rowDelta < 0 && modelStartRow > 0) || (rowDelta > 0 && modelEndRow < tableModel.getRowCount() - 1)) {
// Check if the table can display arrays
if (isCanHaveArrays()) {
// While the start row references an array member
while (ArrayVariable.isArrayMember(getExpandedValueAt(modelStartRow, variableNameIndex))) {
// Decrement the start index to get to the array definition row
modelStartRow--;
}
// Check if the selected ending row references an array definition
if (!getExpandedValueAt(modelEndRow, arraySizeIndex).isEmpty() && !ArrayVariable.isArrayMember(getExpandedValueAt(modelEndRow, variableNameIndex))) {
// Increment the end row so that the members will be included below
modelEndRow++;
}
boolean isIncludeMember = false;
// model hasn't been reached
while (modelEndRow < tableModel.getRowCount() && ArrayVariable.isArrayMember(getExpandedValueAt(modelEndRow, variableNameIndex))) {
// Increment the end index to get to the end of the array
modelEndRow++;
isIncludeMember = true;
}
// Check if the ending row was adjusted to include an array member
if (isIncludeMember) {
// Decrement the row index since the row selection is inclusive
modelEndRow--;
}
// Check if the selected row(s) can be moved in the desired direction
if ((rowDelta < 0 && modelStartRow > 0) || (rowDelta > 0 && modelEndRow < tableModel.getRowCount() - 1)) {
// Get the array size column value for the target row
String arraySize = getExpandedValueAt((rowDelta < 0 ? modelStartRow : modelEndRow) + rowDelta, arraySizeIndex);
// Check if the array size is present on this row
if (!arraySize.isEmpty()) {
// Get the total number of array members
int totalSize = ArrayVariable.getNumMembersFromArraySize(arraySize);
// Adjust the number of rows to move based on the number of array
// members
rowDelta += totalSize * rowDelta;
}
// Set the flag to indicate the selected row(s) can be moved
isCanMove = true;
}
} else // The table can't have an array
{
// Set the flag to indicate the selected row(s) can be moved
isCanMove = true;
}
// Calculate the row that the selected row(s) will be moved to
int modelToRow = modelStartRow + rowDelta;
// Check if the selected row(s) can be moved
if (isCanMove) {
// Move the row(s) in the specified direction and update the cell selection
performRowMove(modelStartRow, modelEndRow, modelToRow, selected, rowDelta);
}
}
}
/**
************************************************************************************
* Override the CcddJTableHandler method for moving the selected row(s) up one row in
* order to prevent moving a row within an array definition and its member rows;
* instead skip past the array
************************************************************************************
*/
@Override
protected void moveRowUp() {
// Move the selected row(s) up if possible
adjustAndMoveSelectedRows(-1);
}
/**
************************************************************************************
* Override the CcddJTableHandler method for moving the selected row(s) down one row in
* order to prevent moving a row within an array definition and its member rows;
* instead skip past the array
************************************************************************************
*/
@Override
protected void moveRowDown() {
// Move the selected row(s) down if possible
adjustAndMoveSelectedRows(1);
}
/**
************************************************************************************
* Override the CcddJTableHandler method for moving the selected row(s) so that
* adjustments can be made to the rates for any packed variables
*
* @param startRow
* selected starting row, in model coordinates
*
* @param endRow
* selected ending row, in model coordinates
*
* @param toRow
* target row to move the selected row(s) to, in model coordinates
*
* @param selected
* cell selection class
*
* @param rowDelta
* row move direction and magnitude
************************************************************************************
*/
@Override
protected void performRowMove(int startRow, int endRow, int toRow, MoveCellSelection selected, int rowDelta) {
// Move the row(s)
super.performRowMove(startRow, endRow, toRow, selected, rowDelta);
// Check if this is a parent structure table
if (tableInfo.isRootStructure()) {
// Load the table data into a list
List<Object[]> tableData = getTableDataList(false);
// Adjust the rate for any packed variables, beginning with the lowest affected
// row index
setAllPackedVariableRates(tableData, Math.min(startRow, toRow), false);
// Check if a rate value changed
if (isRateChange) {
// Load the array of data into the table
loadDataArrayIntoTable(tableData.toArray(new Object[0][0]), true);
}
}
}
/**
************************************************************************************
* Override the CcddJTableHandler method for putting data into a new row inserted below
* the specified row in order to adjust the insertion index based on the presence of
* array members
*
* @param targetRow
* index of the row in model coordinates below which to insert the new row
*
* @param data
* data to place in the inserted row
*
* @return The new row's index, in model coordinates, adjusted as needed to account for
* array member visibility
************************************************************************************
*/
@Override
protected int insertRowData(int targetRow, Object[] data) {
// Check if table has rows, and has variable name and array size columns
if (targetRow != -1 && isCanHaveArrays()) {
// Get the array size value
String arraySize = getExpandedValueAt(targetRow, arraySizeIndex);
// (i.e., this is the array definition row)
if (!arraySize.isEmpty() && !ArrayVariable.isArrayMember(getExpandedValueAt(targetRow, variableNameIndex))) {
// Adjust the row index past the array definition and member rows
targetRow += ArrayVariable.getNumMembersFromArraySize(arraySize);
} else // Check if the array members are set to be displayed
if (isShowArrayMembers) {
boolean isIndex = false;
// While the selection row is on an array member
while (targetRow < tableModel.getRowCount() && ArrayVariable.isArrayMember(getExpandedValueAt(targetRow, variableNameIndex))) {
// Skip the array member row
targetRow++;
isIndex = true;
}
// Check if an array member was skipped
if (isIndex) {
// Decrement the row index
targetRow--;
}
}
}
// Insert the supplied data below the selected row
return super.insertRowData(targetRow, data);
}
/**
************************************************************************************
* Override the CcddJTableHandler method for removing a row from the table. Array
* member rows are ignored unless the array definition row is also deleted; for this
* case the entire array is removed
*
* @param tableData
* list containing the table data row arrays
*
* @param modelRow
* row to remove (model coordinates)
*
* @return The index of the row prior to the last deleted row's index
************************************************************************************
*/
@Override
protected int removeRow(List<Object[]> tableData, int modelRow) {
boolean isArray = false;
// Check if the table has array size and variable name columns
if (isCanHaveArrays()) {
// Extract the array size cell value
String arraySize = getExpandedValueAt(modelRow, arraySizeIndex);
// Check if an array size is present
if (!arraySize.isEmpty()) {
// Set the flag indicating that an array row is being removed
isArray = true;
// Perform while this row is an array member
while (ArrayVariable.isArrayMember(tableData.get(modelRow)[variableNameIndex])) {
// Move the row index up
modelRow--;
}
// Get the row index of the last array member
int arrayRow = modelRow + ArrayVariable.getNumMembersFromArraySize(arraySize);
// Step through each member of the array
while (arrayRow >= modelRow) {
// Delete the row
tableData.remove(modelRow);
// Go to the next array member row to remove
arrayRow--;
}
}
}
// Check if the row does not represent an array definition or member
if (!isArray) {
// Delete the row
super.removeRow(tableData, modelRow);
}
// Adjust the rate for any packed variables, beginning with this row
setAllPackedVariableRates(tableData, convertRowIndexToView(modelRow), false);
return modelRow - 1;
}
/**
************************************************************************************
* Override the CcddJTableHandler method for getting the special replacement character
* when deleting the contents of a cell. Get the corresponding cell value from the
* table's prototype
*
* @param row
* cell row index in model coordinates
*
* @param column
* cell column index in model coordinates
*
* @return The corresponding cell value from the tables' prototype
************************************************************************************
*/
@Override
protected String getSpecialReplacement(int row, int column) {
return dbTable.queryTableCellValue(tableInfo.getPrototypeName(), committedInfo.getData()[row][primaryKeyIndex], typeDefn.getColumnNamesDatabase()[column], editorDialog);
}
/**
************************************************************************************
* Override the CcddJTableHandler method for deleting a cell. Set the special character
* flag to false if the table is a prototype - prototypes can't have an entry in the
* custom values table so no special handling is needed for this case
*
* @param isReplaceSpecial
* false to replace the cell value with a blank; true to replace the cell
* contents with the prototype's corresponding cell value
************************************************************************************
*/
@Override
protected void deleteCell(boolean isReplaceSpecial) {
super.deleteCell(isReplaceSpecial && !tableInfo.isPrototype());
}
/**
************************************************************************************
* Adjust the starting row index to the next row during a paste (insert) operation. If
* the insertion point falls within an array, skip to the row immediately following the
* array's members
*
* @param startRow
* starting row index in view coordinates
*
* @return Starting row index, in model coordinates, at which to insert a new row
************************************************************************************
*/
protected int adjustPasteStartRow(int startRow) {
// Check if the starting row index references a valid row
if (startRow >= 0 && startRow < getRowCount()) {
// Convert the row index to model coordinates and adjust the starting row index
// to the next row
startRow = convertRowIndexToModel(startRow) + 1;
} else // The starting index is not a valid row
{
// Set the starting row index to the end of the table
startRow = tableModel.getRowCount();
}
// variable size and array name columns, and an array size is present
if (startRow < tableModel.getRowCount() && isCanHaveArrays() && !getExpandedValueAt(startRow, arraySizeIndex).isEmpty()) {
// been reached
while (startRow < tableModel.getRowCount() && ArrayVariable.isArrayMember(getExpandedValueAt(startRow, variableNameIndex))) {
// Adjust the row index to the next row
startRow++;
}
}
return startRow;
}
/**
************************************************************************************
* Determine if a row insertion is required during a paste operation. Array member rows
* are inserted automatically when an array is defined, so if an array member is being
* inserted no row needs to be inserted by the paste operation
*
* @param index
* current index into the cell data array
*
* @param cellData
* array containing the cell data being inserted
*
* @param startColumn
* data insertion starting column index
*
* @param endColumn
* data insertion ending column index
*
* @return true if a row should be inserted; false otherwise
************************************************************************************
*/
protected boolean isInsertRowRequired(int index, Object[] cellData, int startColumn, int endColumn) {
boolean isNotArrayMember = true;
// Get the variable name column index in view coordinates
int variableNameIndexView = convertColumnIndexToView(variableNameIndex);
// Step through the row of data being inserted
for (int column = startColumn; column <= endColumn; column++, index++) {
// Check if the column index matches the variable name column
if (column == variableNameIndexView) {
// Check if the variable name cell has a value and is an array member
if (cellData[index] == null || ArrayVariable.isArrayMember(cellData[index])) {
// Set the flag to indicate a new row doesn't need to be inserted
isNotArrayMember = false;
}
// Stop searching
break;
}
}
return isNotArrayMember;
}
/**
************************************************************************************
* Override the paste method so that hidden rows (array members) are displayed prior to
* pasting in new data
************************************************************************************
*/
@Override
protected boolean pasteData(Object[] cellData, int numColumns, boolean isInsert, boolean isAddIfNeeded, boolean startFirstColumn, boolean combineAsSingleEdit) {
Boolean showMessage = true;
// Check if the pasted data should be combined into a single edit operation
if (combineAsSingleEdit) {
// End any active edit sequence, then disable auto-ending so that the paste
// operation can be handled as a single edit for undo/redo purposes
getUndoManager().endEditSequence();
getUndoHandler().setAutoEndEditSequence(false);
}
// Get the table data array
List<Object[]> tableData = getTableDataList(false);
// Calculate the number of rows to be pasted in
int numRows = cellData.length / numColumns;
// Initialize the starting row to the first row, which is the default if no row is
// selected
int startRow = 0;
// Check if no row is selected
if (getSelectedRow() == -1) {
// Clear the column selection. The column selection can remain in effect after
// an undo action that clears the row selection. It needs to be cleared if
// invalid so that the starting column index is correctly calculated below
getColumnModel().getSelectionModel().clearSelection();
} else // A row is selected
{
// Determine the starting row for pasting the data based on the selected row
startRow = convertRowIndexToModel(getSelectedRow()) + getSelectedRowCount() - 1;
}
// Determine the starting column and ending column for pasting the data. If no
// column is selected then default to the first column. Data pasted outside of the
// column range is ignored
int startColumn = startFirstColumn ? 0 : Math.max(Math.max(getSelectedColumn(), 0), getSelectedColumn() + getSelectedColumnCount() - 1);
int endColumn = startColumn + numColumns - 1;
int endColumnSelect = Math.min(endColumn, getColumnCount() - 1);
// members are hidden
if (isCanHaveArrays() && !isShowArrayMembers) {
// Show the array members. All rows must be visible in order for the pasted
// data to be inserted correctly. The model and view row coordinates are the
// same after expanding the array members. Note that this clears the row and
// column selection
showHideArrayMembers();
}
// Check if the data is to be inserted versus overwriting existing cells
if (isInsert) {
// Adjust the starting row index to the one after the selected row, and account
// for hidden rows, if applicable
startRow = adjustPasteStartRow(startRow);
} else // contains no rows
if (startRow == -1) {
// Set the start row to the first row
startRow = 0;
}
// Determine the ending row for pasting the data
int endRow = startRow + numRows;
// Clear the cell selection
clearSelection();
// Counters for the number of array member rows added (due to pasting in an array
// definition) and the number of rows ignored (due to the first pasted row(s) being
// an array member)
int arrayRowsAdded = 0;
int totalAddedRows = 0;
int skippedRows = 0;
boolean isIgnoreRow = false;
// Step through each new row
for (int index = 0, row = startRow; row < endRow && showMessage != null; row++) {
boolean skipRow = false;
// Calculate the row in the table data where the values are to be pasted. This
// must be adjusted to account for pasting in arrays
int adjustedRow = row + totalAddedRows - skippedRows;
// member
for (int column = startColumn; column <= endColumn && column < getColumnCount() && showMessage != null; column++) {
// Get the index into the cell data for this column
int tempIndex = index + column - startColumn;
// Check if rows were removed due to an array size reduction or removal
if (arrayRowsAdded < 0) {
// Set the flag indicating that this row of data is to be skipped and
// increment the skipped row counter
skipRow = true;
skippedRows++;
// Adjust the row counters so that all array member rows are skipped
arrayRowsAdded++;
totalAddedRows++;
} else // and that the value is an array member
if (variableNameIndex == convertColumnIndexToModel(column) && tempIndex < cellData.length && cellData[tempIndex] != null && ArrayVariable.isArrayMember(cellData[tempIndex])) {
// the array members
if (arrayRowsAdded > 0) {
// Move the row index back so that the array member data is pasted
// in the proper row
adjustedRow -= arrayRowsAdded;
arrayRowsAdded--;
totalAddedRows--;
} else // No rows were added for this array member
{
// member has no definition
if (row == startRow) {
// Set the flag indicating that array member rows are ignored
isIgnoreRow = true;
}
// Set the flag indicating that this row of data is to be skipped
// and increment the skipped row counter
skipRow = true;
skippedRows++;
// Update the cell data index so that this row is skipped
index += numColumns;
}
break;
}
}
// Check that this row is not to be ignored
if (!skipRow) {
// Check if inserting is in effect and the cell value is null
if (isInsert && index < cellData.length && cellData[index] == null) {
// Replace the null with a blank
cellData[index] = "";
}
// Check if a row needs to be inserted to contain the cell data
if ((isInsert || (isAddIfNeeded && adjustedRow == tableData.size())) && isInsertRowRequired(index, cellData, startColumn, endColumn)) {
// Insert a row at the selection point
tableData.add(adjustedRow, getEmptyRow());
}
// Store the index into the array of data to be pasted
int indexSave = index;
// are pasted, then the cells that are not empty are pasted
for (int pass = 1; pass <= 2; pass++) {
// Check if this is the second pass through the row's columns
if (pass == 2) {
// Reset the index into the array of data to be pasted so that the
// non-blank cells can be processed
index = indexSave;
}
// Step through the columns, beginning at the one with the focus
for (int column = startColumn; column <= endColumn && showMessage != null; column++) {
// outside the bounds or protected then discard the value
if (column < getColumnCount()) {
// Convert the column coordinate from view to model
int columnModel = convertColumnIndexToModel(column);
// Get the value to be pasted into the cell, cleaning up the
// value if needed. If the number of cells to be filled exceeds
// the stored values then insert a blank. A null paste value
// indicates that the current cell's value won't be overwritten
Object newValue = index < cellData.length ? (cellData[index] != null ? cleanUpCellValue(cellData[index], adjustedRow, columnModel) : (isInsert ? "" : null)) : "";
// alterable
if (newValue != null && ((pass == 1 && newValue.toString().isEmpty()) || (pass == 2 && !newValue.toString().isEmpty())) && isDataAlterable(tableData.get(adjustedRow), adjustedRow, columnModel)) {
// Get the original cell value
Object oldValue = tableData.get(adjustedRow)[columnModel];
// being inserted, that the value isn't blank
if (!oldValue.equals(newValue) && !(isInsert && newValue.toString().isEmpty())) {
// Insert the value into the cell
tableData.get(adjustedRow)[columnModel] = newValue;
// Get the number of rows in the table prior to
// inserting the new value
int previousRows = tableData.size();
// Validate the new cell contents
showMessage = validateCellContent(tableData, adjustedRow, columnModel, oldValue, newValue, showMessage, cellData.length > 1);
// following an invalid input
if (showMessage == null) {
// Stop pasting data
continue;
}
// Get the number of rows added due to pasting in the
// new value. This is non-zero if an array definition
// is pasted in or if an existing array's size is
// altered
int deltaRows = tableData.size() - previousRows;
// Check if the row count changed
if (deltaRows > 0) {
// Store the number of added/deleted rows and
// update the total number of added/deleted rows
arrayRowsAdded = deltaRows;
totalAddedRows += arrayRowsAdded;
}
}
}
}
// Increment the index to the next value to paste
index++;
}
}
}
}
// Check if the user hasn't selected the Cancel button following an invalid input
if (showMessage != null) {
// Load the array of data into the table
loadDataArrayIntoTable(tableData.toArray(new Object[0][0]), true);
// Check if automatic edit sequence ending is in effect
if (getUndoHandler().isAutoEndEditSequence()) {
// Flag the end of the editing sequence for undo/redo purposes
getUndoManager().endEditSequence();
}
// Check if there are rows left to be selected
if (endRow - 1 - skippedRows > 0) {
// Select all of the rows into which the data was pasted
setRowSelectionInterval(startRow, endRow - 1 - skippedRows);
}
// Select all of the columns into which the data was pasted
setColumnSelectionInterval(startColumn, endColumnSelect);
// Select the pasted cells and force the table to be redrawn so that the
// changes are displayed
setSelectedCells(startRow, endRow - 1, startColumn, endColumnSelect);
repaint();
// Check if any rows were ignored
if (isIgnoreRow) {
// Inform the user how many rows were skipped
new CcddDialogHandler().showMessageDialog(editorDialog, "<html><b>" + skippedRows + " array member row(s) ignored due " + "to missing array definition(s)", "Rows Ignored", JOptionPane.WARNING_MESSAGE, DialogOption.OK_OPTION);
}
}
// Set the flag that indicates the last edited cell's content is valid (if an
// invalid input set the flag to false then it can prevent closing the editor)
setLastCellValid(true);
// Check if the pasted data should be combined into a single edit operation
if (combineAsSingleEdit) {
// Re-enable auto-ending of the edit sequence and end the sequence. The pasted
// data can be removed with a single undo if desired
getUndoHandler().setAutoEndEditSequence(true);
getUndoManager().endEditSequence();
}
return showMessage == null;
}
/**
************************************************************************************
* Override the method for cleaning-up of the cell value. The default is to remove any
* leading and trailing white space characters. This method skips removal of white
* space characters for cells having input types that allow it
*
* @param value
* new cell value
*
* @param row
* table row, model coordinates
*
* @param column
* table column, model coordinates
*
* @return Cell value following clean-up
************************************************************************************
*/
@Override
protected Object cleanUpCellValue(Object value, int row, int column) {
// string (i.e., it isn't boolean, etc.)
if (!table.isEditing() && value instanceof String) {
// Get the input type for this column
InputDataType inputType = typeDefn.getInputTypes()[column];
// space characters
if (inputType != InputDataType.TEXT_WHT_SPC && inputType != InputDataType.TEXT_MULTI_WHT_SPC) {
// Perform the default clean-up (remove leading and trailing white space
// characters)
value = super.cleanUpCellValue(value, row, column);
}
}
return value;
}
/**
************************************************************************************
* Handle a change to the table's content
************************************************************************************
*/
@Override
protected void processTableContentChange() {
// and/or value change)
if (editorDialog != null) {
// Update the change indicator for the table
editorDialog.updateChangeIndicator(CcddTableEditorHandler.this);
}
}
};
// Place the table into a scroll pane
JScrollPane scrollPane = new JScrollPane(table);
// Disable storage of edit operations during table creation
table.getUndoHandler().setAllowUndo(false);
// Set common table parameters and characteristics
table.setFixedCharacteristics(scrollPane, tableInfo.isPrototype(), ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, TableSelectionMode.SELECT_BY_CELL, true, ModifiableColorInfo.TABLE_BACK.getColor(), true, true, ModifiableFontInfo.DATA_TABLE_CELL.getFont(), true);
// Get a reference to the table model to shorten later calls
tableModel = (UndoableTableModel) table.getModel();
// Re-enable storage of edit operations
table.getUndoHandler().setAllowUndo(true);
// Set the reference to the editor's data field handler in the undo handler so that data
// field value changes can be undone/redone correctly
table.getUndoHandler().setFieldHandler(tableInfo.getFieldHandler());
// Set the undo/redo manager and handler for the description and data field values
setEditPanelUndo(table.getUndoManager(), table.getUndoHandler());
// Set the mouse listener to expand and collapse arrays
setArrayExpansionListener();
// Get the variable path separators and create the variable path column content, if present
updateVariablePaths();
// change)
if (editorDialog != null) {
// Create the input field panel to contain the table editor
createDescAndDataFieldPanel(editorDialog, scrollPane, tableInfo.getProtoVariableName(), tableInfo.getDescription(), tableInfo.getFieldHandler());
// Set the dialog name so that this dialog can be recognized as being open by the table
// selection dialog, and the JTable name so that table change events can be identified
// with this table
setTableName();
// Store the current data field information in the event an undo/redo operation occurs
storeCurrentFieldInformation();
}
}
use of javax.swing.text.JTextComponent in project freeplane by freeplane.
the class EditNodeWYSIWYG method show.
public void show(final RootPaneContainer frame) {
try {
HTMLDialog htmlEditorWindow = createHtmlEditor(frame);
htmlEditorWindow.setBase(this);
final String titleText;
titleText = TextUtils.getText(title);
htmlEditorWindow.getDialog().setTitle(titleText);
htmlEditorWindow.setSplitEnabled(getEditControl().canSplit());
final SHTMLPanel htmlEditorPanel = (htmlEditorWindow).getHtmlEditorPanel();
final StringBuilder ruleBuilder = new StringBuilder(100);
ruleBuilder.append("body {");
ruleBuilder.append(new CssRuleBuilder().withCSSFont(font, UITools.FONT_SCALE_FACTOR).withColor(textColor).withBackground(getBackground()).withAlignment(horizontalAlignment));
ruleBuilder.append("}\n");
ruleBuilder.append("p {margin-top:0;}\n");
final HTMLDocument document = htmlEditorPanel.getDocument();
final JEditorPane editorPane = htmlEditorPanel.getEditorPane();
if (textColor != null) {
editorPane.setForeground(textColor);
editorPane.setCaretColor(textColor);
}
final StyleSheet styleSheet = document.getStyleSheet();
styleSheet.removeStyle("p");
styleSheet.removeStyle("body");
styleSheet.addRule(ruleBuilder.toString());
final URL url = node.getMap().getURL();
if (url != null) {
document.setBase(url);
} else {
document.setBase(new URL("file: "));
}
htmlEditorPanel.setContentPanePreferredSize(preferredSize);
htmlEditorWindow.getDialog().pack();
if (ResourceController.getResourceController().getBooleanProperty("el__position_window_below_node")) {
UITools.setDialogLocationUnder(htmlEditorWindow.getDialog(), node);
} else {
UITools.setDialogLocationRelativeTo(htmlEditorWindow.getDialog(), node);
}
String content = text;
if (!HtmlUtils.isHtmlNode(content)) {
content = HtmlUtils.plainToHTML(content);
}
htmlEditorPanel.setCurrentDocumentContent(content);
final KeyEvent firstKeyEvent = MTextController.getController().getEventQueue().getFirstEvent();
final JTextComponent currentPane = htmlEditorPanel.getEditorPane();
if (currentPane == htmlEditorPanel.getMostRecentFocusOwner()) {
redispatchKeyEvents(currentPane, firstKeyEvent);
if (firstKeyEvent == null) {
editorPane.setCaretPosition(htmlEditorPanel.getDocument().getLength());
}
} else {
final EventBuffer keyEventDispatcher = MTextController.getController().getEventQueue();
keyEventDispatcher.deactivate();
}
htmlEditorPanel.getMostRecentFocusOwner().requestFocus();
htmlEditorWindow.show();
} catch (final Exception ex) {
LogUtils.severe("Loading of WYSIWYG HTML editor failed. Use the other editors instead.", ex);
}
}
Aggregations