mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 05:45:06 +08:00
Merge remote-tracking branch 'origin/GP-910_ghidra1_BitViewHexDisplay--SQUASHED'
This commit is contained in:
@@ -1273,7 +1273,8 @@
|
|||||||
<P>While the Bitfield Editor is displayed local popup menu actions
|
<P>While the Bitfield Editor is displayed local popup menu actions
|
||||||
are provided which can facilitate additional component manipulations (e.g., <B>Add Bitfield</B>,
|
are provided which can facilitate additional component manipulations (e.g., <B>Add Bitfield</B>,
|
||||||
<B>Edit Bitfield</B>, <B>Delete</B>). These actions relate to the component at the current
|
<B>Edit Bitfield</B>, <B>Delete</B>). These actions relate to the component at the current
|
||||||
mouse cursor location. Invoking either the <B>Add Bitfield</B> or
|
mouse cursor location. An addition popup menu toggle action available over the bitfield
|
||||||
|
viewer is <B>Show Byte Offsets in Hexadecimal</B>. Invoking either the <B>Add Bitfield</B> or
|
||||||
<B>Edit Bitfield</B> local popup menu actions will immediately cancel the current bitfield
|
<B>Edit Bitfield</B> local popup menu actions will immediately cancel the current bitfield
|
||||||
operation if one is active.</P>
|
operation if one is active.</P>
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -54,7 +54,8 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
|
|||||||
|
|
||||||
BitFieldEditorDialog dlg =
|
BitFieldEditorDialog dlg =
|
||||||
new BitFieldEditorDialog(editorModel.viewComposite, provider.dtmService,
|
new BitFieldEditorDialog(editorModel.viewComposite, provider.dtmService,
|
||||||
-(rowIndex + 1), ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
-(rowIndex + 1), model.showHexNumbers,
|
||||||
|
ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
||||||
Component c = provider.getComponent();
|
Component c = provider.getComponent();
|
||||||
DockingWindowManager.showDialog(c, dlg);
|
DockingWindowManager.showDialog(c, dlg);
|
||||||
requestTableFocus();
|
requestTableFocus();
|
||||||
|
|||||||
+93
-10
@@ -17,13 +17,12 @@ package ghidra.app.plugin.core.compositeeditor;
|
|||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.*;
|
||||||
import javax.swing.JComponent;
|
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.*;
|
||||||
import docking.DialogComponentProvider;
|
import docking.action.*;
|
||||||
import docking.action.DockingAction;
|
import docking.menu.DockingCheckboxMenuItemUI;
|
||||||
import docking.action.MenuData;
|
import docking.widgets.OptionDialog;
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
@@ -42,7 +41,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
private BitFieldEditorPanel bitFieldEditorPanel; // for unaligned use case
|
private BitFieldEditorPanel bitFieldEditorPanel; // for unaligned use case
|
||||||
|
|
||||||
BitFieldEditorDialog(Composite composite, DataTypeManagerService dtmService, int editOrdinal,
|
BitFieldEditorDialog(Composite composite, DataTypeManagerService dtmService, int editOrdinal,
|
||||||
CompositeChangeListener listener) {
|
boolean showOffsetsInHex, CompositeChangeListener listener) {
|
||||||
super("Edit " + getCompositeType(composite) + " Bitfield");
|
super("Edit " + getCompositeType(composite) + " Bitfield");
|
||||||
this.composite = composite;
|
this.composite = composite;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
@@ -52,6 +51,8 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
setRememberLocation(false);
|
setRememberLocation(false);
|
||||||
setRememberSize(false);
|
setRememberSize(false);
|
||||||
|
|
||||||
|
bitFieldEditorPanel.setShowOffsetsInHex(showOffsetsInHex);
|
||||||
|
|
||||||
addActions();
|
addActions();
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Bitfield_Editor"));
|
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Bitfield_Editor"));
|
||||||
@@ -79,6 +80,27 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean startEditAllowed() {
|
||||||
|
if (bitFieldEditorPanel.isEditing()) {
|
||||||
|
int option = OptionDialog.showOptionDialog(rootPanel, "Edit in Progress",
|
||||||
|
"Apply or Discard current changes before starting new edit?", "Apply", "Discard",
|
||||||
|
OptionDialog.QUESTION_MESSAGE);
|
||||||
|
if (option == OptionDialog.OPTION_ONE) {
|
||||||
|
if (!bitFieldEditorPanel.apply(listener)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setApplyEnabled(false);
|
||||||
|
}
|
||||||
|
else if (option == OptionDialog.CANCEL_OPTION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!bitFieldEditorPanel.endCurrentEdit()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private class EditBitFieldAction extends DockingAction {
|
private class EditBitFieldAction extends DockingAction {
|
||||||
|
|
||||||
EditBitFieldAction() {
|
EditBitFieldAction() {
|
||||||
@@ -90,7 +112,10 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
DataTypeComponent bitfieldDtc = getEditComponent(context, true);
|
DataTypeComponent bitfieldDtc = getEditComponent(context, true);
|
||||||
if (bitfieldDtc == null || !bitFieldEditorPanel.endCurrentEdit()) {
|
if (bitfieldDtc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!startEditAllowed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initEdit(bitfieldDtc.getOrdinal(), true);
|
initEdit(bitfieldDtc.getOrdinal(), true);
|
||||||
@@ -112,9 +137,10 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
if (!bitFieldEditorPanel.endCurrentEdit()) {
|
if (!startEditAllowed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitFieldEditorPanel.BitFieldEditorContext editorContext =
|
BitFieldEditorPanel.BitFieldEditorContext editorContext =
|
||||||
(BitFieldEditorPanel.BitFieldEditorContext) context;
|
(BitFieldEditorPanel.BitFieldEditorContext) context;
|
||||||
|
|
||||||
@@ -135,6 +161,7 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
DeleteComponentAction() {
|
DeleteComponentAction() {
|
||||||
super("Delete", "BitFieldEditorDialog");
|
super("Delete", "BitFieldEditorDialog");
|
||||||
setPopupMenuData(new MenuData(new String[] { getName() }, DELETE_ICON));
|
setPopupMenuData(new MenuData(new String[] { getName() }, DELETE_ICON));
|
||||||
|
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Bitfield_Editor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -157,10 +184,56 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ToggleHexUseAction extends DockingAction implements ToggleDockingActionIf {
|
||||||
|
|
||||||
|
private boolean isSelected;
|
||||||
|
|
||||||
|
ToggleHexUseAction() {
|
||||||
|
super("Show Byte Offsets in Hexadecimal", "BitFieldEditorDialog");
|
||||||
|
setEnabled(true);
|
||||||
|
setSelected(bitFieldEditorPanel.isShowOffsetsInHex());
|
||||||
|
setPopupMenuData(new MenuData(new String[] { getName() }));
|
||||||
|
setHelpLocation(new HelpLocation("DataTypeEditors", "Structure_Bitfield_Editor"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionContext context) {
|
||||||
|
bitFieldEditorPanel.setShowOffsetsInHex(isSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected() {
|
||||||
|
return isSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(boolean newValue) {
|
||||||
|
if (isSelected == newValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isSelected = newValue;
|
||||||
|
firePropertyChanged(SELECTED_STATE_PROPERTY, !isSelected, isSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JMenuItem doCreateMenuItem() {
|
||||||
|
DockingCheckBoxMenuItem menuItem = new DockingCheckBoxMenuItem(isSelected);
|
||||||
|
menuItem.setUI(
|
||||||
|
(DockingCheckboxMenuItemUI) DockingCheckboxMenuItemUI.createUI(menuItem));
|
||||||
|
return menuItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addActions() {
|
private void addActions() {
|
||||||
addAction(new AddBitFieldAction());
|
addAction(new AddBitFieldAction());
|
||||||
addAction(new EditBitFieldAction());
|
addAction(new EditBitFieldAction());
|
||||||
addAction(new DeleteComponentAction());
|
addAction(new DeleteComponentAction());
|
||||||
|
addAction(new ToggleHexUseAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -196,7 +269,9 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private JComponent buildWorkPanel(int editOrdinal) {
|
private JComponent buildWorkPanel(int editOrdinal) {
|
||||||
bitFieldEditorPanel = new BitFieldEditorPanel(composite, dtmService);
|
bitFieldEditorPanel = new BitFieldEditorPanel(composite, dtmService, dt -> {
|
||||||
|
return baseDataTypeChanged(dt);
|
||||||
|
});
|
||||||
if (editOrdinal < 0) {
|
if (editOrdinal < 0) {
|
||||||
initAdd(-editOrdinal - 1);
|
initAdd(-editOrdinal - 1);
|
||||||
}
|
}
|
||||||
@@ -206,6 +281,14 @@ public class BitFieldEditorDialog extends DialogComponentProvider {
|
|||||||
return bitFieldEditorPanel;
|
return bitFieldEditorPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean baseDataTypeChanged(DataType bitfieldBaseDataType) {
|
||||||
|
// BitFieldEditorPanel checks should be adequate
|
||||||
|
boolean allowed = bitfieldBaseDataType != null;
|
||||||
|
setOkEnabled(allowed);
|
||||||
|
setApplyEnabled(allowed);
|
||||||
|
return allowed;
|
||||||
|
}
|
||||||
|
|
||||||
private static String getCompositeType(Composite composite) {
|
private static String getCompositeType(Composite composite) {
|
||||||
// currently supports unaligned case only!
|
// currently supports unaligned case only!
|
||||||
if (composite.isInternallyAligned()) {
|
if (composite.isInternallyAligned()) {
|
||||||
|
|||||||
+141
-20
@@ -22,9 +22,12 @@ import javax.swing.*;
|
|||||||
import javax.swing.event.CellEditorListener;
|
import javax.swing.event.CellEditorListener;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.widgets.DropDownSelectionTextField;
|
import docking.widgets.DropDownSelectionTextField;
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
|
import docking.widgets.label.GDLabel;
|
||||||
import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitAttributes;
|
import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitAttributes;
|
||||||
import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitFieldAllocation;
|
import ghidra.app.plugin.core.compositeeditor.BitFieldPlacementComponent.BitFieldAllocation;
|
||||||
import ghidra.app.services.DataTypeManagerService;
|
import ghidra.app.services.DataTypeManagerService;
|
||||||
@@ -32,7 +35,6 @@ import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
|||||||
import ghidra.app.util.datatype.NavigationDirection;
|
import ghidra.app.util.datatype.NavigationDirection;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Composite;
|
import ghidra.program.model.data.Composite;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||||
import ghidra.util.layout.*;
|
import ghidra.util.layout.*;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
@@ -46,10 +48,9 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
private static final Icon DECREMENT_ICON = ResourceManager.loadImage("images/Minus.png");
|
private static final Icon DECREMENT_ICON = ResourceManager.loadImage("images/Minus.png");
|
||||||
private static final Icon INCREMENT_ICON = ResourceManager.loadImage("images/Plus.png");
|
private static final Icon INCREMENT_ICON = ResourceManager.loadImage("images/Plus.png");
|
||||||
|
|
||||||
private static final String ENTRY_ERROR_DIALOG_TITLE = "Bitfield Entry Error";
|
|
||||||
|
|
||||||
private DataTypeManagerService dtmService;
|
private DataTypeManagerService dtmService;
|
||||||
private Composite composite;
|
private Composite composite;
|
||||||
|
private Predicate<DataType> dataTypeValidator;
|
||||||
|
|
||||||
private JLabel allocationOffsetLabel;
|
private JLabel allocationOffsetLabel;
|
||||||
JButton decrementButton;
|
JButton decrementButton;
|
||||||
@@ -68,11 +69,15 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
private SpinnerNumberModel bitSizeModel;
|
private SpinnerNumberModel bitSizeModel;
|
||||||
private JSpinnerWithMouseWheel bitSizeInput;
|
private JSpinnerWithMouseWheel bitSizeInput;
|
||||||
|
|
||||||
|
private GDLabel statusTextField;
|
||||||
|
|
||||||
private BitSelectionHandler bitSelectionHandler;
|
private BitSelectionHandler bitSelectionHandler;
|
||||||
|
|
||||||
|
|
||||||
private boolean updating = false;
|
private boolean updating = false;
|
||||||
|
|
||||||
BitFieldEditorPanel(Composite composite, DataTypeManagerService dtmService) {
|
BitFieldEditorPanel(Composite composite, DataTypeManagerService dtmService,
|
||||||
|
Predicate<DataType> dataTypeValidator) {
|
||||||
super();
|
super();
|
||||||
this.composite = composite;
|
this.composite = composite;
|
||||||
|
|
||||||
@@ -85,8 +90,9 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
setFocusTraversalKeysEnabled(true);
|
setFocusTraversalKeysEnabled(true);
|
||||||
|
|
||||||
this.dtmService = dtmService;
|
this.dtmService = dtmService;
|
||||||
|
this.dataTypeValidator = dataTypeValidator;
|
||||||
|
|
||||||
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
|
||||||
|
|
||||||
if (composite instanceof Structure) {
|
if (composite instanceof Structure) {
|
||||||
add(createAllocationOffsetPanel());
|
add(createAllocationOffsetPanel());
|
||||||
@@ -94,10 +100,20 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
add(createPlacementPanel());
|
add(createPlacementPanel());
|
||||||
add(createLegendPanel());
|
add(createLegendPanel());
|
||||||
add(createEntryPanel());
|
add(createEntryPanel());
|
||||||
|
add(createStatusPanel());
|
||||||
|
|
||||||
enableControls(false);
|
enableControls(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setShowOffsetsInHex(boolean useHex) {
|
||||||
|
placementComponent.setShowOffsetsInHex(useHex);
|
||||||
|
updateAllocationOffsetLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isShowOffsetsInHex() {
|
||||||
|
return placementComponent.isShowOffsetsInHex();
|
||||||
|
}
|
||||||
|
|
||||||
private JPanel createLegendPanel() {
|
private JPanel createLegendPanel() {
|
||||||
JPanel legendPanel = new JPanel(new BorderLayout());
|
JPanel legendPanel = new JPanel(new BorderLayout());
|
||||||
legendPanel.add(new BitFieldPlacementComponent.BitFieldLegend(null), BorderLayout.WEST);
|
legendPanel.add(new BitFieldPlacementComponent.BitFieldLegend(null), BorderLayout.WEST);
|
||||||
@@ -139,8 +155,16 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
|
|
||||||
private void updateAllocationOffsetLabel() {
|
private void updateAllocationOffsetLabel() {
|
||||||
if (composite instanceof Structure) {
|
if (composite instanceof Structure) {
|
||||||
|
int allocOffset = placementComponent.getAllocationOffset();
|
||||||
|
String allocOffsetStr;
|
||||||
|
if (placementComponent.isShowOffsetsInHex()) {
|
||||||
|
allocOffsetStr = "0x" + Integer.toHexString(allocOffset);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
allocOffsetStr = Integer.toString(allocOffset);
|
||||||
|
}
|
||||||
String text =
|
String text =
|
||||||
"Structure Offset of Allocation Unit: " + placementComponent.getAllocationOffset();
|
"Structure Offset of Allocation Unit: " + allocOffsetStr;
|
||||||
allocationOffsetLabel.setText(text);
|
allocationOffsetLabel.setText(text);
|
||||||
|
|
||||||
int offset = placementComponent.getAllocationOffset();
|
int offset = placementComponent.getAllocationOffset();
|
||||||
@@ -150,6 +174,31 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Component createStatusPanel() {
|
||||||
|
JPanel statusPanel = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
statusTextField = new GDLabel(" ");
|
||||||
|
statusTextField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
statusTextField.setForeground(Color.red);
|
||||||
|
|
||||||
|
// use a strut panel so the size of the message area does not change if we make
|
||||||
|
// the message label not visible
|
||||||
|
int height = statusTextField.getPreferredSize().height;
|
||||||
|
|
||||||
|
statusPanel.add(Box.createVerticalStrut(height), BorderLayout.WEST);
|
||||||
|
statusPanel.add(statusTextField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
return statusPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setStatus(String text) {
|
||||||
|
statusTextField.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearStatus() {
|
||||||
|
statusTextField.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
private JPanel createEntryPanel() {
|
private JPanel createEntryPanel() {
|
||||||
|
|
||||||
JComponent baseDataTypeEditor = createDataTypeChoiceEditor();
|
JComponent baseDataTypeEditor = createDataTypeChoiceEditor();
|
||||||
@@ -211,7 +260,7 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
|
|
||||||
final DropDownSelectionTextField<DataType> dtChoiceTextField =
|
final DropDownSelectionTextField<DataType> dtChoiceTextField =
|
||||||
dtChoiceEditor.getDropDownTextField();
|
dtChoiceEditor.getDropDownTextField();
|
||||||
dtChoiceTextField.setBorder(UIManager.getBorder("TextField.border"));
|
dtChoiceTextField.setBorder((new JTextField()).getBorder());
|
||||||
|
|
||||||
dtChoiceEditor.addFocusListener(new FocusAdapter() {
|
dtChoiceEditor.addFocusListener(new FocusAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@@ -242,10 +291,6 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
dtChoiceTextField.requestFocus();
|
dtChoiceTextField.requestFocus();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
baseDataType = dtChoiceEditor.getCellEditorValueAsDataType();
|
|
||||||
if (baseDataType != null) {
|
|
||||||
baseDataType = baseDataType.clone(composite.getDataTypeManager());
|
|
||||||
}
|
|
||||||
updateBitSizeModel();
|
updateBitSizeModel();
|
||||||
NavigationDirection direction = dtChoiceEditor.getNavigationDirection();
|
NavigationDirection direction = dtChoiceEditor.getNavigationDirection();
|
||||||
if (direction == NavigationDirection.FORWARD) {
|
if (direction == NavigationDirection.FORWARD) {
|
||||||
@@ -271,12 +316,57 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
private boolean selectionActive = false;
|
private boolean selectionActive = false;
|
||||||
private int startBit;
|
private int startBit;
|
||||||
private int lastBit;
|
private int lastBit;
|
||||||
|
private int lastX;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if (bitOffsetInput.isEnabled() || e.isConsumed() || e.getClickCount() != 2 ||
|
||||||
|
!placementComponent.isWithinBitCell(e.getPoint())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BitAttributes bitAttributes = placementComponent.getBitAttributes(e.getPoint());
|
||||||
|
if (bitAttributes != null) {
|
||||||
|
DataTypeComponent dtc = bitAttributes.getDataTypeComponent(true);
|
||||||
|
if (dtc == null || !dtc.isBitFieldComponent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.consume();
|
||||||
|
initEdit(dtc, placementComponent.getAllocationOffset(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
if (!selectionActive && bitOffsetInput.isEnabled()) {
|
||||||
|
boolean inBounds = placementComponent.isWithinBitCell(e.getPoint());
|
||||||
|
setCursor(Cursor.getPredefinedCursor(
|
||||||
|
inBounds ? Cursor.HAND_CURSOR : Cursor.DEFAULT_CURSOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEntered(MouseEvent e) {
|
||||||
|
if (!selectionActive && bitOffsetInput.isEnabled() &&
|
||||||
|
placementComponent.isWithinBitCell(e.getPoint())) {
|
||||||
|
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExited(MouseEvent e) {
|
||||||
|
if (!selectionActive) {
|
||||||
|
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed(MouseEvent e) {
|
public void mousePressed(MouseEvent e) {
|
||||||
if (e.isConsumed()) {
|
if (e.isConsumed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!placementComponent.isWithinBitCell(e.getPoint())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||||
e.consume();
|
e.consume();
|
||||||
selectionActive = false;
|
selectionActive = false;
|
||||||
@@ -285,6 +375,10 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
startBit = setBitFieldOffset(e.getPoint());
|
startBit = setBitFieldOffset(e.getPoint());
|
||||||
lastBit = startBit;
|
lastBit = startBit;
|
||||||
selectionActive = startBit >= 0;
|
selectionActive = startBit >= 0;
|
||||||
|
if (selectionActive) {
|
||||||
|
lastX = e.getPoint().x;
|
||||||
|
setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,6 +392,15 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
e.consume();
|
e.consume();
|
||||||
|
|
||||||
Point p = e.getPoint();
|
Point p = e.getPoint();
|
||||||
|
|
||||||
|
if (p.x == lastX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Cursor cursor = Cursor.getPredefinedCursor(
|
||||||
|
p.x < lastX ? Cursor.W_RESIZE_CURSOR : Cursor.E_RESIZE_CURSOR);
|
||||||
|
setCursor(cursor);
|
||||||
|
lastX = p.x;
|
||||||
|
|
||||||
int bitOffset = placementComponent.getBitOffset(p);
|
int bitOffset = placementComponent.getBitOffset(p);
|
||||||
if (bitOffset == lastBit) {
|
if (bitOffset == lastBit) {
|
||||||
return;
|
return;
|
||||||
@@ -328,6 +431,11 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
if (selectionActive && !e.isConsumed()) {
|
if (selectionActive && !e.isConsumed()) {
|
||||||
e.consume();
|
e.consume();
|
||||||
selectionActive = false;
|
selectionActive = false;
|
||||||
|
|
||||||
|
Point p = e.getPoint();
|
||||||
|
boolean inBounds = placementComponent.getVisibleRect().contains(p);
|
||||||
|
setCursor(Cursor.getPredefinedCursor(
|
||||||
|
inBounds ? Cursor.HAND_CURSOR : Cursor.DEFAULT_CURSOR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +453,7 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
|
|
||||||
JPanel bitViewPanel = new JPanel(new PairLayout(0, 5));
|
JPanel bitViewPanel = new JPanel(new PairLayout(0, 5));
|
||||||
|
|
||||||
JPanel labelPanel = new JPanel(new VerticalLayout(7));
|
JPanel labelPanel = new JPanel(new VerticalLayout(5));
|
||||||
labelPanel.setBorder(BorderFactory.createEmptyBorder(7, 5, 0, 0));
|
labelPanel.setBorder(BorderFactory.createEmptyBorder(7, 5, 0, 0));
|
||||||
JLabel byteOffsetLabel = new JLabel("Byte Offset:", SwingConstants.RIGHT);
|
JLabel byteOffsetLabel = new JLabel("Byte Offset:", SwingConstants.RIGHT);
|
||||||
labelPanel.add(byteOffsetLabel);
|
labelPanel.add(byteOffsetLabel);
|
||||||
@@ -365,20 +473,32 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
private boolean checkValidBaseDataType() {
|
private boolean checkValidBaseDataType() {
|
||||||
DropDownSelectionTextField<DataType> textField = dtChoiceEditor.getDropDownTextField();
|
DropDownSelectionTextField<DataType> textField = dtChoiceEditor.getDropDownTextField();
|
||||||
String dtName = textField.getText().trim();
|
String dtName = textField.getText().trim();
|
||||||
|
boolean isValid = true;
|
||||||
try {
|
try {
|
||||||
if (dtName.length() == 0 || !dtChoiceEditor.validateUserSelection()) {
|
if (dtName.length() == 0 || !dtChoiceEditor.validateUserSelection()) {
|
||||||
Msg.showError(BitFieldEditorPanel.class, textField, ENTRY_ERROR_DIALOG_TITLE,
|
setStatus("Valid bitfield base datatype entry required");
|
||||||
"Valid bitfield base datatype entry required");
|
isValid = false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InvalidDataTypeException e) {
|
catch (InvalidDataTypeException e) {
|
||||||
Msg.showError(BitFieldEditorPanel.class, textField, ENTRY_ERROR_DIALOG_TITLE,
|
setStatus("Invalid bitfield base datatype: " + e.getMessage());
|
||||||
"Invalid bitfield base datatype: " + e.getMessage());
|
isValid = false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (isValid) {
|
||||||
return true;
|
DataType dt = dtChoiceEditor.getCellEditorValueAsDataType();
|
||||||
|
if (!dataTypeValidator.apply(baseDataType)) {
|
||||||
|
setStatus("Valid bitfield base datatype entry required");
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
baseDataType = dt.clone(composite.getDataTypeManager());
|
||||||
|
clearStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dataTypeValidator.apply(null); // affects button enablement
|
||||||
|
}
|
||||||
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initAdd(DataType initialBaseDataType, int allocationOffset, int bitOffset,
|
void initAdd(DataType initialBaseDataType, int allocationOffset, int bitOffset,
|
||||||
@@ -449,6 +569,7 @@ public class BitFieldEditorPanel extends JPanel {
|
|||||||
updating = true;
|
updating = true;
|
||||||
try {
|
try {
|
||||||
baseDataType = initialBaseDataType;
|
baseDataType = initialBaseDataType;
|
||||||
|
dataTypeValidator.apply(baseDataType);
|
||||||
dtChoiceEditor.setCellEditorValue(initialBaseDataType);
|
dtChoiceEditor.setCellEditorValue(initialBaseDataType);
|
||||||
fieldNameTextField.setText(initialFieldName);
|
fieldNameTextField.setText(initialFieldName);
|
||||||
fieldCommentTextField.setText(initialComment);
|
fieldCommentTextField.setText(initialComment);
|
||||||
|
|||||||
+30
-1
@@ -38,6 +38,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
|||||||
private static final int BYTE_SEPARATOR_THICKNESS = 2;
|
private static final int BYTE_SEPARATOR_THICKNESS = 2;
|
||||||
private static final int SCROLLBAR_THICKNESS = 15;
|
private static final int SCROLLBAR_THICKNESS = 15;
|
||||||
private static final int MY_HEIGHT = (2 * CELL_HEIGHT) + (3 * BYTE_SEPARATOR_THICKNESS);
|
private static final int MY_HEIGHT = (2 * CELL_HEIGHT) + (3 * BYTE_SEPARATOR_THICKNESS);
|
||||||
|
private static final int BYTE_ROW_HEIGHT = CELL_HEIGHT + (2 * BYTE_SEPARATOR_THICKNESS);
|
||||||
|
|
||||||
private static final int LENEND_BOX_SIZE = 16;
|
private static final int LENEND_BOX_SIZE = 16;
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
|||||||
private EditMode editMode = EditMode.NONE;
|
private EditMode editMode = EditMode.NONE;
|
||||||
private int editOrdinal = -1;
|
private int editOrdinal = -1;
|
||||||
private DataTypeComponent editComponent;
|
private DataTypeComponent editComponent;
|
||||||
|
private boolean showOffsetsInHex = false;
|
||||||
|
|
||||||
public static class BitFieldLegend extends JPanel {
|
public static class BitFieldLegend extends JPanel {
|
||||||
|
|
||||||
@@ -161,6 +163,18 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
|||||||
init(null);
|
init(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setShowOffsetsInHex(boolean useHex) {
|
||||||
|
this.showOffsetsInHex = useHex;
|
||||||
|
if (bitFieldAllocation != null) {
|
||||||
|
bitFieldAllocation.refresh(true);
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShowOffsetsInHex() {
|
||||||
|
return showOffsetsInHex;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredScrollableViewportSize() {
|
public Dimension getPreferredScrollableViewportSize() {
|
||||||
return getPreferredSize();
|
return getPreferredSize();
|
||||||
@@ -248,6 +262,15 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
|||||||
return MY_HEIGHT + SCROLLBAR_THICKNESS;
|
return MY_HEIGHT + SCROLLBAR_THICKNESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if specified point is within bit cell region
|
||||||
|
* @param p point within this component's bounds
|
||||||
|
* @return true if p is within bit cell region
|
||||||
|
*/
|
||||||
|
public boolean isWithinBitCell(Point p) {
|
||||||
|
return p.y < MY_HEIGHT && p.y > BYTE_ROW_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
private int getPreferredWidth() {
|
private int getPreferredWidth() {
|
||||||
int extraLineSpace = BYTE_SEPARATOR_THICKNESS - BIT_SEPARATOR_THICKNESS;
|
int extraLineSpace = BYTE_SEPARATOR_THICKNESS - BIT_SEPARATOR_THICKNESS;
|
||||||
return (allocationByteSize * byteWidth) + BYTE_SEPARATOR_THICKNESS + extraLineSpace;
|
return (allocationByteSize * byteWidth) + BYTE_SEPARATOR_THICKNESS + extraLineSpace;
|
||||||
@@ -658,7 +681,13 @@ public class BitFieldPlacementComponent extends JPanel implements Scrollable {
|
|||||||
|
|
||||||
g.setColor(TEXT_COLOR);
|
g.setColor(TEXT_COLOR);
|
||||||
|
|
||||||
String offsetStr = Integer.toString(offset);
|
String offsetStr;
|
||||||
|
if (showOffsetsInHex) {
|
||||||
|
offsetStr = "0x" + Integer.toHexString(offset);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
offsetStr = Integer.toString(offset);
|
||||||
|
}
|
||||||
FontMetrics fontMetrics = g.getFontMetrics();
|
FontMetrics fontMetrics = g.getFontMetrics();
|
||||||
int textY = y + (CELL_HEIGHT + fontMetrics.getMaxAscent() - BYTE_SEPARATOR_THICKNESS) / 2;
|
int textY = y + (CELL_HEIGHT + fontMetrics.getMaxAscent() - BYTE_SEPARATOR_THICKNESS) / 2;
|
||||||
int textX = x + (width - BYTE_SEPARATOR_THICKNESS - fontMetrics.stringWidth(offsetStr)) / 2;
|
int textX = x + (width - BYTE_SEPARATOR_THICKNESS - fontMetrics.stringWidth(offsetStr)) / 2;
|
||||||
|
|||||||
+4
@@ -118,6 +118,9 @@ public class CompEditorPanel extends CompositeEditorPanel {
|
|||||||
@Override
|
@Override
|
||||||
public void compositeInfoChanged() {
|
public void compositeInfoChanged() {
|
||||||
adjustCompositeInfo();
|
adjustCompositeInfo();
|
||||||
|
if (model.showHexNumbers != bitViewComponent.isShowOffsetsInHex()) {
|
||||||
|
bitViewComponent.setShowOffsetsInHex(model.showHexNumbers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,6 +159,7 @@ public class CompEditorPanel extends CompositeEditorPanel {
|
|||||||
protected JPanel createBitViewerPanel() {
|
protected JPanel createBitViewerPanel() {
|
||||||
|
|
||||||
bitViewComponent = new BitFieldPlacementComponent(model.viewComposite, false);
|
bitViewComponent = new BitFieldPlacementComponent(model.viewComposite, false);
|
||||||
|
bitViewComponent.setShowOffsetsInHex(model.showHexNumbers);
|
||||||
model.addCompositeViewerModelListener(new CompositeEditorModelAdapter() {
|
model.addCompositeViewerModelListener(new CompositeEditorModelAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void selectionChanged() {
|
public void selectionChanged() {
|
||||||
|
|||||||
+1
-1
@@ -161,7 +161,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||||||
table.getCellEditor().cancelCellEditing();
|
table.getCellEditor().cancelCellEditing();
|
||||||
|
|
||||||
BitFieldEditorDialog dlg = new BitFieldEditorDialog(model.viewComposite,
|
BitFieldEditorDialog dlg = new BitFieldEditorDialog(model.viewComposite,
|
||||||
provider.dtmService, editingRow, ordinal -> {
|
provider.dtmService, editingRow, model.showHexNumbers, ordinal -> {
|
||||||
model.notifyCompositeChanged();
|
model.notifyCompositeChanged();
|
||||||
});
|
});
|
||||||
Component c = provider.getComponent();
|
Component c = provider.getComponent();
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ public class EditBitFieldAction extends CompositeEditorTableAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BitFieldEditorDialog dlg = new BitFieldEditorDialog(editorModel.viewComposite,
|
BitFieldEditorDialog dlg = new BitFieldEditorDialog(editorModel.viewComposite,
|
||||||
provider.dtmService, dtComponent.getOrdinal(),
|
provider.dtmService, dtComponent.getOrdinal(), model.showHexNumbers,
|
||||||
ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
ordinal -> refreshTableAndSelection(editorModel, ordinal));
|
||||||
Component c = provider.getComponent();
|
Component c = provider.getComponent();
|
||||||
DockingWindowManager.showDialog(c, dlg);
|
DockingWindowManager.showDialog(c, dlg);
|
||||||
|
|||||||
Reference in New Issue
Block a user