Merge remote-tracking branch 'origin/GP-3049_ghidragon_fixing_improving_register_manager--SQUASHED'

This commit is contained in:
Ryan Kurtz
2026-04-21 10:48:36 -04:00
39 changed files with 2029 additions and 1094 deletions
@@ -127,8 +127,7 @@ public class BSimSearchDialog extends AbstractBSimSearchDialog {
maxResultsField = new IntegerTextField(10);
maxResultsField.setValue(100);
maxResultsField.setMinValue(BigInteger.ONE);
maxResultsField.setAllowNegativeValues(false);
maxResultsField.setAllowsHexPrefix(false);
maxResultsField.setUseNumberPrefix(false);
maxResultsField.setShowNumberMode(false);
JComponent maxResultsComponent = maxResultsField.getComponent();
@@ -71,24 +71,27 @@
</BLOCKQUOTE>
<BLOCKQUOTE>
<H3><A name="tool_buttons"></A>Tool Buttons</H3>
</BLOCKQUOTE>
<H3><A name="tool_buttons"></A>Toolbar Buttons</H3>
<BLOCKQUOTE>
<BLOCKQUOTE>
<P><IMG src="images/locationIn.gif">Toggles whether or not to select the row in the
<P><IMG src="images/locationIn.gif">&nbsp;Toggles whether or not to select the row in the
currently selected register value table whose address range contains the current address
of the cursor in the listing view. For example, in the Register Manager image show above,
if the user clicks on any address between 804c12 and 804c24, then the first row of the
table will be selected if this action toggle is on.</P>
<P><IMG src="images/edit-delete.png">Deletes the register value associations for all the
<P><IMG src="Icons.ADD_ICON">&nbsp;Brings up the <I>Add Register Value Range</I> dialog for setting a
value over an address range for the selected register. See the
<A href="">Edit Address Range</A> section below for dialog details as this action shares the
same dialog as the edit range action.</P>
<P><IMG src="images/edit-delete.png">&nbsp;Deletes the register value associations for all the
selected ranges in the table.</P>
<P><IMG src="Icons.MAKE_SELECTION_ICON">Creates a selection in the browser for all the address
<P><IMG src="Icons.MAKE_SELECTION_ICON">&nbsp;Creates a selection in the browser for all the address
ranges selected in the register values table.</P>
<P><IMG src="images/view-filter.png">Filters out all registers in the register tree that
<P><IMG src="images/view-filter.png">&nbsp;Filters out all registers in the register tree that
don't have any associated values (default or otherwise).</P>
<H3><BR>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

@@ -33,6 +33,7 @@ import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.dialogs.StringChoices;
import docking.widgets.table.*;
import docking.widgets.textfield.IntegerTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import ghidra.docking.settings.*;
import ghidra.framework.preferences.Preferences;
import ghidra.util.BigEndianDataConverter;
@@ -783,7 +784,8 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
}
private void updateHexMode() {
intHexModeMap.put(rowobject.definition.getName(), intTextField.isHexMode());
intHexModeMap.put(rowobject.definition.getName(),
intTextField.getFormat() == IntegerFormat.HEX);
}
private Number getNumber() {
@@ -854,14 +856,14 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
mode = NUMBER;
NumberSettingsDefinition def = (NumberSettingsDefinition) rowobject.definition;
if (def.isHexModePreferred() || isHexModeEnabled(def)) {
intTextField.setHexMode();
intTextField.setFormat(IntegerFormat.HEX);
}
else {
intTextField.setDecimalMode();
intTextField.setFormat(IntegerFormat.DEC);
}
intTextField.setMaxValue(def.getMaxValue());
intTextField.setAllowNegativeValues(def.allowNegativeValue());
intTextField.setMinValue(def.allowNegativeValue() ? null : BigInteger.ZERO);
if (value == null) {
intTextField.setValue(null);
@@ -31,6 +31,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.widgets.DropDownSelectionTextField;
import docking.widgets.table.FocusableEditor;
import docking.widgets.textfield.IntegerTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import generic.theme.GThemeDefaults.Colors.Palette;
import ghidra.app.util.AddressInput;
import ghidra.program.model.address.Address;
@@ -163,7 +164,7 @@ class VarnodeLocationCellEditor extends AbstractCellEditor
private Component createStackOffsetEditor(VarnodeInfo varnode) {
offsetInput = new IntegerTextField();
offsetInput.setHexMode();
offsetInput.setFormat(IntegerFormat.HEX);
Address address = varnode.getAddress();
if (address != null) {
offsetInput.setValue(address.getOffset());
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -24,6 +24,7 @@ import javax.swing.*;
import javax.swing.table.TableCellEditor;
import docking.widgets.textfield.IntegerTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import generic.theme.GThemeDefaults.Colors.Palette;
class VarnodeSizeCellEditor extends AbstractCellEditor implements TableCellEditor {
@@ -56,8 +57,8 @@ class VarnodeSizeCellEditor extends AbstractCellEditor implements TableCellEdito
int row, int column) {
input = new IntegerTextField();
input.setAllowNegativeValues(false);
input.setDecimalMode();
input.setMinValue(BigInteger.ZERO);
input.setFormat(IntegerFormat.DEC);
Integer size = (Integer) value;
if (size != null) {
input.setValue(size.longValue());
@@ -16,6 +16,7 @@
package ghidra.app.plugin.core.memory;
import java.awt.*;
import java.math.BigInteger;
import java.util.List;
import javax.swing.*;
@@ -28,6 +29,7 @@ import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.label.GDLabel;
import docking.widgets.label.GLabel;
import docking.widgets.textfield.IntegerTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import ghidra.app.plugin.core.memory.AddBlockModel.InitializedType;
import ghidra.app.plugin.core.misc.RegisterField;
import ghidra.app.util.AddressInput;
@@ -474,16 +476,16 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
JPanel schemePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
schemeDestByteCountField = new IntegerTextField(4, 1);
schemeDestByteCountField.setAllowNegativeValues(false);
schemeDestByteCountField.setAllowsHexPrefix(false);
schemeDestByteCountField.setDecimalMode();
schemeDestByteCountField.setMinValue(BigInteger.ZERO);
schemeDestByteCountField.setUseNumberPrefix(false);
schemeDestByteCountField.setFormat(IntegerFormat.DEC);
schemeDestByteCountField.addChangeListener(ev -> schemeDestByteCountChanged());
schemeDestByteCountField.setAccessibleName("Mapping Ratio: Destination Size");
schemeSrcByteCountField = new IntegerTextField(4, 1);
schemeSrcByteCountField.setAllowNegativeValues(false);
schemeSrcByteCountField.setAllowsHexPrefix(false);
schemeSrcByteCountField.setDecimalMode();
schemeSrcByteCountField.setMinValue(BigInteger.ZERO);
schemeSrcByteCountField.setUseNumberPrefix(false);
schemeSrcByteCountField.setFormat(IntegerFormat.DEC);
schemeSrcByteCountField.addChangeListener(ev -> schemeSrcByteCountChanged());
schemeSrcByteCountField.setAccessibleName("Mapping Ratio: Source Size");
@@ -22,8 +22,8 @@ import javax.swing.*;
import docking.DialogComponentProvider;
import docking.widgets.label.GLabel;
import docking.widgets.textfield.FixedSizeIntegerTextField;
import ghidra.app.util.AddressInput;
import ghidra.app.util.bean.FixedBitSizeValueField;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.lang.Register;
@@ -36,7 +36,7 @@ class EditRegisterValueDialog extends DialogComponentProvider {
private AddressInput startAddrField;
private AddressInput endAddrField;
private FixedBitSizeValueField registerValueField;
private FixedSizeIntegerTextField registerValueField;
private boolean wasCancelled = true;
EditRegisterValueDialog(Register register, Address start, Address end, BigInteger value,
@@ -61,10 +61,16 @@ class EditRegisterValueDialog extends DialogComponentProvider {
startAddrField = new AddressInput(program, addressChangeListener);
endAddrField = new AddressInput(program, addressChangeListener);
registerValueField = new FixedBitSizeValueField(register.getBitLength(), true, false);
registerValueField.getAccessibleContext().setAccessibleName("Register Value");
startAddrField.setAddress(start);
endAddrField.setAddress(end);
registerValueField = new FixedSizeIntegerTextField(16, register.getBitLength());
registerValueField.getComponent()
.getAccessibleContext()
.setAccessibleName("Register Value");
if (start != null) {
startAddrField.setAddress(start);
}
if (end != null) {
endAddrField.setAddress(end);
}
registerValueField.setValue(value);
JPanel panel = new JPanel(new PairLayout(5, 1));
@@ -77,7 +83,7 @@ class EditRegisterValueDialog extends DialogComponentProvider {
panel.add(new GLabel("End Address:"));
panel.add(endAddrField);
panel.add(new GLabel("Value:"));
panel.add(registerValueField);
panel.add(registerValueField.getComponent());
panel.getAccessibleContext().setAccessibleName("Edit Register Value");
return panel;
}
@@ -19,14 +19,19 @@ import static ghidra.framework.model.DomainObjectEvent.*;
import static ghidra.program.util.ProgramEvent.*;
import java.awt.event.MouseEvent;
import java.math.BigInteger;
import javax.swing.*;
import docking.ActionContext;
import docking.WindowPosition;
import docking.action.*;
import docking.action.ToggleDockingAction;
import docking.action.builder.ActionBuilder;
import docking.action.builder.ToggleActionBuilder;
import generic.theme.GIcon;
import ghidra.app.cmd.register.SetRegisterCmd;
import ghidra.app.context.ProgramActionContext;
import ghidra.framework.cmd.Command;
import ghidra.framework.model.DomainObjectChangedEvent;
import ghidra.framework.model.DomainObjectListener;
import ghidra.framework.plugintool.ComponentProviderAdapter;
@@ -52,16 +57,13 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
private RegisterTree tree;
private RegisterValuesPanel values;
private DockingAction deleteRegisterValuesAction;
private DockingAction selectRegisterValuesAction;
private ToggleDockingAction showDefaultRegisterValuesAction;
private ToggleDockingAction showDefaultValuesAction;
private DomainObjectListener domainObjectListener;
private ToggleDockingAction filterRegistersAction;
private SwingUpdateManager updateMgr;
private ToggleDockingAction followLocationToggleAction;
protected boolean followLocation;
private boolean followLocation = false;
private Address currentAddress;
RegisterManagerProvider(PluginTool tool, String owner) {
super(tool, "Register Manager", owner, ProgramActionContext.class);
@@ -86,9 +88,7 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
tree.addGTreeSelectionListener(e -> showRegister());
values.getTable().getSelectionModel().addListSelectionListener(e -> {
JTable table = values.getTable();
deleteRegisterValuesAction.setEnabled(table.getSelectedRowCount() > 0);
selectRegisterValuesAction.setEnabled(table.getSelectedRowCount() > 0);
contextChanged();
});
tree.setAccessibleNamePrefix("Register Manager");
@@ -100,80 +100,91 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
void createActions() {
HelpLocation helpLocation = new HelpLocation("RegisterPlugin", "tool_buttons");
deleteRegisterValuesAction = new DockingAction("Delete Register Value Ranges", getOwner()) {
@Override
public void actionPerformed(ActionContext context) {
values.deleteSelectedRanges();
}
};
deleteRegisterValuesAction.setEnabled(false);
deleteRegisterValuesAction.setToolBarData(new ToolBarData(DELETE_REGISTER_VALUES_ICON));
deleteRegisterValuesAction
.setPopupMenuData(new MenuData(new String[] { "Delete Register Value Ranges" }));
deleteRegisterValuesAction.setDescription("Delete Register Value Ranges");
deleteRegisterValuesAction.setHelpLocation(helpLocation);
tool.addLocalAction(this, deleteRegisterValuesAction);
selectRegisterValuesAction = new DockingAction("Select Register Value Ranges", getOwner()) {
@Override
public void actionPerformed(ActionContext context) {
values.selectedRanges();
}
};
selectRegisterValuesAction.setEnabled(false);
selectRegisterValuesAction.setToolBarData(new ToolBarData(SELECT_REGISTER_VALUES_ICON));
selectRegisterValuesAction
.setPopupMenuData(new MenuData(new String[] { "Select Register Value Ranges" }));
selectRegisterValuesAction.setDescription("Select Register Value Ranges");
selectRegisterValuesAction.setHelpLocation(helpLocation);
tool.addLocalAction(this, selectRegisterValuesAction);
new ActionBuilder("Add Register Value Range", getOwner())
.toolBarIcon(Icons.ADD_ICON)
.popupMenuPath("Add Value Range")
.popupMenuIcon(Icons.ADD_ICON)
.description("Add a new register value range")
.helpLocation(helpLocation)
.withContext(RegisterManagerContext.class)
.enabledWhen(c -> c.getSelectedRegister() != null)
.onAction(c -> addRange(c.getSelectedRegister()))
.buildAndInstallLocal(this);
showDefaultRegisterValuesAction =
new ToggleDockingAction("Show default register values", getOwner()) {
@Override
public void actionPerformed(ActionContext context) {
values.setShowDefaultValues(showDefaultRegisterValuesAction.isSelected());
}
};
showDefaultRegisterValuesAction.setSelected(false);
showDefaultRegisterValuesAction
.setDescription("Toggles showing of default register values");
showDefaultRegisterValuesAction
.setMenuBarData(new MenuData(new String[] { "Show Default Values" }));
showDefaultRegisterValuesAction
.setHelpLocation(new HelpLocation("RegisterPlugin", "menu_actions"));
tool.addLocalAction(this, showDefaultRegisterValuesAction);
new ActionBuilder("Delete Register Value Ranges", getOwner())
.toolBarIcon(DELETE_REGISTER_VALUES_ICON)
.popupMenuPath("Delete Register Value Ranges")
.popupMenuIcon(DELETE_REGISTER_VALUES_ICON)
.description("Delete selected register value ranges")
.helpLocation(helpLocation)
.withContext(RegisterManagerContext.class)
.enabledWhen(c -> c.hasSelectedRegisterValueRanges())
.onAction(c -> values.deleteSelectedRanges())
.buildAndInstallLocal(this);
filterRegistersAction = new ToggleDockingAction("Filter Registers", getOwner()) {
@Override
public void actionPerformed(ActionContext context) {
tree.setFiltered(filterRegistersAction.isSelected());
}
};
filterRegistersAction.setSelected(false);
filterRegistersAction.setDescription(
"Toggles filtering out registers that don't have values or default values.");
filterRegistersAction.setToolBarData(new ToolBarData(FILTER_ICON));
filterRegistersAction.setHelpLocation(helpLocation);
tool.addLocalAction(this, filterRegistersAction);
new ActionBuilder("Select Register Value Ranges", getOwner())
.toolBarIcon(SELECT_REGISTER_VALUES_ICON)
.popupMenuPath("Select Register Value Ranges")
.popupMenuIcon(SELECT_REGISTER_VALUES_ICON)
.helpLocation(helpLocation)
.description("Create a program selection from the selected rows")
.withContext(RegisterManagerContext.class)
.enabledWhen(c -> c.hasSelectedRegisterValueRanges())
.onAction(c -> values.selectRanges())
.buildAndInstallLocal(this);
followLocationToggleAction =
new ToggleDockingAction("Follow location changes", getOwner()) {
@Override
public void actionPerformed(ActionContext context) {
followLocation = followLocationToggleAction.isSelected();
}
};
followLocationToggleAction.setEnabled(true);
followLocationToggleAction.setHelpLocation(helpLocation);
followLocationToggleAction.setToolBarData(new ToolBarData(RECV_LOCATION_ICON, "NavAction"));
tool.addLocalAction(this, followLocationToggleAction);
showDefaultValuesAction =
new ToggleActionBuilder("Show Default Register Values", getOwner())
.menuPath("Show Default Values")
.description("Toggles showing of default register values")
.helpLocation(helpLocation)
.selected(false)
.onAction(c -> updateShowingDefaultRegisterValues())
.buildAndInstallLocal(this);
filterRegistersAction = new ToggleActionBuilder("Filter Registers", getOwner())
.toolBarIcon(FILTER_ICON)
.description("Toggles showing only registers with values or default values")
.helpLocation(helpLocation)
.selected(false)
.onAction(c -> tree.setFiltered(filterRegistersAction.isSelected()))
.buildAndInstallLocal(this);
new ToggleActionBuilder("Follow location changes", getOwner())
.toolBarIcon(RECV_LOCATION_ICON)
.toolBarGroup("NavAction")
.description(
"If selected, auto select register and value range from listing location")
.helpLocation(helpLocation)
.selected(false)
.onAction(c -> followLocation = !followLocation)
.buildAndInstallLocal(this);
}
private void updateShowingDefaultRegisterValues() {
values.setShowDefaultValues(showDefaultValuesAction.isSelected());
}
private void addRange(Register register) {
EditRegisterValueDialog dialog =
new EditRegisterValueDialog(register, currentAddress, currentAddress, null, program);
dialog.setTitle("Add Value Range");
tool.showDialog(dialog, this);
if (!dialog.wasCancelled()) {
Address start = dialog.getStartAddress();
Address end = dialog.getEndAddress();
BigInteger value = dialog.getValue();
Command<Program> command = new SetRegisterCmd(register, start, end, value);
tool.execute(command, program);
}
}
private void showRegister() {
Register register = tree.getSelectedRegister();
values.setRegister(register);
contextChanged();
}
@Override
@@ -191,7 +202,8 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
if (program == null) {
return null;
}
return new ProgramActionContext(this, program);
return new RegisterManagerContext(program, tree.getSelectedRegister(),
values.hasSelectedRows());
}
@Override
@@ -245,6 +257,7 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
}
public void setLocation(Register register, Address address) {
currentAddress = address;
if (!followLocation) {
return;
}
@@ -254,4 +267,23 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
values.setAddress(address);
}
private class RegisterManagerContext extends ProgramActionContext {
private Register register;
private boolean hasSelectedRows;
RegisterManagerContext(Program program, Register register, boolean hasSelectedRows) {
super(RegisterManagerProvider.this, program);
this.register = register;
this.hasSelectedRows = hasSelectedRows;
}
public boolean hasSelectedRegisterValueRanges() {
return hasSelectedRows;
}
public Register getSelectedRegister() {
return register;
}
}
}
@@ -358,15 +358,13 @@ public class RegisterPlugin extends ProgramPlugin {
@Override
protected void locationChanged(ProgramLocation loc) {
if (loc instanceof RegisterTransitionFieldLocation) {
RegisterTransitionFieldLocation regLoc = (RegisterTransitionFieldLocation) loc;
if (loc instanceof RegisterTransitionFieldLocation regLoc) {
Register reg = regLoc.getRegister();
if (reg != null) {
registerMgrProvider.setLocation(reg, regLoc.getAddress());
}
}
else if (loc instanceof RegisterFieldLocation) {
RegisterFieldLocation regLoc = (RegisterFieldLocation) loc;
else if (loc instanceof RegisterFieldLocation regLoc) {
Register reg = regLoc.getRegister();
if (reg != null) {
registerMgrProvider.setLocation(reg, regLoc.getAddress());
@@ -83,6 +83,10 @@ class RegisterValuesPanel extends JPanel {
}
boolean hasSelectedRows() {
return table.getSelectedRowCount() > 0;
}
private void editRow(int row) {
RegisterValueRange range = model.values.get(row);
Address start = range.getStartAddress();
@@ -275,7 +279,7 @@ class RegisterValuesPanel extends JPanel {
}
}
void selectedRanges() {
void selectRanges() {
int[] rows = table.getSelectedRows();
AddressSet set = new AddressSet();
for (int element : rows) {
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -15,11 +15,12 @@
*/
package ghidra.app.plugin.core.register;
import java.awt.*;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Iterator;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -28,19 +29,21 @@ import javax.swing.event.ChangeListener;
import docking.DialogComponentProvider;
import docking.widgets.combobox.GComboBox;
import docking.widgets.label.GLabel;
import docking.widgets.list.GListCellRenderer;
import docking.widgets.textfield.FixedSizeIntegerTextField;
import generic.theme.GThemeDefaults.Ids.Fonts;
import generic.theme.Gui;
import ghidra.app.util.bean.FixedBitSizeValueField;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.layout.VariableHeightPairLayout;
public class SetRegisterValueDialog extends DialogComponentProvider {
private JComboBox<RegisterWrapper> registerComboBox;
private FixedBitSizeValueField registerValueField;
private JList addressRangeList;
private FixedSizeIntegerTextField registerValueField;
private JList<String> addressRangeList;
private BigInteger registerValue;
private Register selectedRegister;
private boolean useValueField;
@@ -58,7 +61,7 @@ public class SetRegisterValueDialog extends DialogComponentProvider {
addOKButton();
addCancelButton();
if (useValueField) {
setFocusComponent(registerValueField.getTextComponent());
setFocusComponent(registerValueField.getComponent());
}
setSelectedRegister(register);
setAddressRanges(addrSet);
@@ -77,79 +80,72 @@ public class SetRegisterValueDialog extends DialogComponentProvider {
}
private JComponent buildWorkPanel(Register[] registers) {
registerComboBox = new GComboBox<>(wrapRegisters(registers));
registerValueField = new FixedBitSizeValueField(32, true, false);
GLabel registerLabel = new GLabel("Register:");
GLabel valueLabel = new GLabel("Value:");
GLabel addressLabel = new GLabel("Address(es):");
registerLabel.setHorizontalAlignment(SwingConstants.RIGHT);
valueLabel.setHorizontalAlignment(SwingConstants.RIGHT);
addressLabel.setHorizontalAlignment(SwingConstants.RIGHT);
addressLabel.setVerticalAlignment(SwingConstants.TOP);
JPanel panel = new JPanel(new VariableHeightPairLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
panel.add(registerLabel);
panel.add(buildRegisterComboBox(registers));
panel.add(valueLabel);
panel.add(buildValueField(registers));
panel.add(addressLabel);
panel.add(buildAddressPanel());
return panel;
}
private Component buildValueField(Register[] registers) {
registerValueField = new FixedSizeIntegerTextField(16, 16);
registerValueField.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
updateOkEnablement();
}
});
return registerValueField.getComponent();
}
private Component buildRegisterComboBox(Register[] registers) {
registerComboBox = new GComboBox<>(wrapRegisters(registers));
registerComboBox.setRenderer(new RegisterComboRenderer());
registerComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
registerChanged();
updateComboToolTip();
}
});
updateComboToolTip();
return registerComboBox;
}
addressRangeList = new JList();
private void updateComboToolTip() {
RegisterWrapper item = (RegisterWrapper) registerComboBox.getSelectedItem();
String tooltip = item == null ? "" : item.getToolTip();
registerComboBox.setToolTipText(tooltip);
}
private Component buildAddressPanel() {
addressRangeList = new JList<String>();
addressRangeList.setEnabled(false);
Gui.registerFont(addressRangeList, Fonts.MONOSPACED);
JScrollPane scrollPane = new JScrollPane(addressRangeList);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
Dimension d = scrollPane.getPreferredSize();
d.height = 120;
d.width = 180;
scrollPane.setPreferredSize(d);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 1, 5);
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(new GLabel("Register:"), gbc);
gbc.gridy = 1;
if (useValueField) {
panel.add(new GLabel("Value:"), gbc);
}
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(10, 5, 1, 5);
GLabel addressLabel = new GLabel("Address(es):");
addressLabel.setVerticalAlignment(SwingConstants.TOP);
panel.add(addressLabel, gbc);
gbc.insets = new Insets(5, 5, 1, 5);
gbc.weightx = 1.0;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 1;
gbc.gridy = 0;
panel.add(registerComboBox, gbc);
gbc.gridy = 1;
if (useValueField) {
panel.add(registerValueField, gbc);
}
gbc.gridy = 2;
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.BOTH;
panel.add(scrollPane, gbc);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
return panel;
return scrollPane;
}
private void registerChanged() {
RegisterWrapper wrapper = (RegisterWrapper) registerComboBox.getSelectedItem();
if (wrapper != null) {
registerValueField.setBitSize(wrapper.register.getBitLength());
int bitLength = wrapper.register.getBitLength();
registerValueField.setBitSize(bitLength);
updateOkEnablement();
}
updateValue();
@@ -232,6 +228,21 @@ public class SetRegisterValueDialog extends DialogComponentProvider {
return selectedRegister;
}
private static class RegisterComboRenderer extends GListCellRenderer<RegisterWrapper> {
@Override
public Component getListCellRendererComponent(JList<? extends RegisterWrapper> list,
RegisterWrapper value, int index, boolean isSelected, boolean hasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, hasFocus);
String toolTip = value.getToolTip();
setToolTipText(toolTip);
return this;
}
@Override
protected String getItemText(RegisterWrapper value) {
return value == null ? "" : value.toString();
}
}
}
class RegisterWrapper implements Comparable<RegisterWrapper> {
@@ -240,14 +251,24 @@ class RegisterWrapper implements Comparable<RegisterWrapper> {
RegisterWrapper(Register register) {
this.register = register;
displayName = register.getName() + " (" + register.getBitLength() + getAliases() + ")";
displayName = register.getName() + " (" + register.getBitLength() + ")";
}
private String getAliases() {
String getToolTip() {
StringBuffer buf = new StringBuffer();
for (String alias : register.getAliases()) {
buf.append(buf.length() == 0 ? "; " : ", ");
buf.append(alias);
buf.append(displayName);
buf.append(" Aliases: ");
Iterator<String> aliases = register.getAliases().iterator();
if (!aliases.hasNext()) {
buf.append("none");
}
else {
buf.append(aliases.next());
buf.append(", ");
}
while (aliases.hasNext()) {
buf.append(", ");
buf.append(aliases.next());
}
return buf.toString();
}
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -97,7 +97,7 @@ class SelectBlockDialog extends ReusableDialogComponentProvider {
numberInputField = new IntegerTextField(10);
numberInputField.getComponent().getAccessibleContext().setAccessibleName("Number Input");
numberInputField.setMaxValue(BigInteger.valueOf(Integer.MAX_VALUE));
numberInputField.setAllowNegativeValues(false);
numberInputField.setMinValue(BigInteger.ZERO);
main.add(numberInputField.getComponent());
main.getAccessibleContext().setAccessibleName("Block");
return main;
@@ -17,6 +17,7 @@ package ghidra.app.plugin.core.string;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
@@ -331,7 +332,7 @@ public class StringTableProvider extends ComponentProviderAdapter implements Dom
private Component buildOffsetPanel() {
offsetField = new IntegerTextField(4, 0L);
offsetField.setAllowNegativeValues(false);
offsetField.setMinValue(BigInteger.ZERO);
offsetField.addChangeListener(e -> updatePreview());
preview = new JTextField(5);
@@ -15,22 +15,22 @@
*/
package ghidra.app.util;
import static docking.widgets.textfield.integer.IntegerFormat.*;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Comparator;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import docking.widgets.combobox.GComboBox;
import docking.widgets.table.FocusableEditor;
import docking.widgets.textfield.HexDecimalModeTextField;
import docking.widgets.textfield.integer.MultiFormatTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import generic.expressions.ExpressionException;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
@@ -45,7 +45,7 @@ public class AddressInput extends JPanel implements FocusableEditor {
public final static Predicate<AddressSpace> ALL_MEMORY_SPACES = s -> s.isMemorySpace();
public final static Predicate<AddressSpace> LOADED_MEMORY_SPACES = s -> s.isLoadedMemorySpace();
private HexDecimalModeTextField textField;
private MultiFormatTextField textField;
private AddressSpaceField addressSpaceField;
AddressEvaluator addressEvaluator;
private Predicate<AddressSpace> addressSpaceFilter = LOADED_MEMORY_SPACES;
@@ -170,8 +170,9 @@ public class AddressInput extends JPanel implements FocusableEditor {
* @param hexMode true to assume numbers are hexadecimal.
*/
public void setAssumeHex(boolean hexMode) {
textField.setHexMode(hexMode);
hexModeChanged(hexMode);
IntegerFormat format = hexMode ? IntegerFormat.HEX : IntegerFormat.DEC;
textField.setFormat(format);
hexModeChanged(format);
}
/**
@@ -418,35 +419,17 @@ public class AddressInput extends JPanel implements FocusableEditor {
private void buildComponent() {
setLayout(new BorderLayout());
textField = new HexDecimalModeTextField(10, b -> hexModeChanged(b));
textField.setHexMode(true);
textField = new MultiFormatTextField(10, List.of(HEX, DEC), b -> hexModeChanged(b));
textField.setName("JTextField");//for JUnits...
addressSpaceField = new AddressSpaceField();
add(textField, BorderLayout.CENTER);
comboAdded = false;
textField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
notifyAddressChanged();
}
@Override
public void removeUpdate(DocumentEvent e) {
notifyAddressChanged();
}
@Override
public void changedUpdate(DocumentEvent e) {
notifyAddressChanged();
}
});
textField.addTextChangedCallback(this::notifyAddressChanged);
}
private void hexModeChanged(boolean hexMode) {
this.assumeHex = hexMode;
addressEvaluator.setAssumeHex(hexMode);
private void hexModeChanged(IntegerFormat format) {
this.assumeHex = format == HEX;
addressEvaluator.setAssumeHex(assumeHex);
notifyAddressChanged();
}
@@ -18,6 +18,7 @@ package ghidra.app.util.importer.options;
import java.awt.Component;
import docking.widgets.textfield.IntegerTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import ghidra.app.util.*;
import ghidra.framework.options.SaveState;
import ghidra.program.model.address.AddressFactory;
@@ -64,7 +65,7 @@ public class HexLongOption extends AbstractOption<HexLong> {
setValue(new HexLong(initialState));
IntegerTextField field = new IntegerTextField();
field.setValue(initialState);
field.setHexMode();
field.setFormat(IntegerFormat.HEX);
field.getComponent().setToolTipText(getDescription());
field.addChangeListener(e -> {
setValue(new HexLong(field.getLongValue()));
@@ -26,6 +26,7 @@ import docking.widgets.checkbox.GCheckBox;
import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.label.GDLabel;
import docking.widgets.textfield.IntegerTextField;
import docking.widgets.textfield.integer.IntegerFormat;
import ghidra.framework.options.CustomOptionsEditor;
import ghidra.util.HTMLUtilities;
import ghidra.util.layout.PairLayout;
@@ -101,8 +102,8 @@ public class AddressFieldOptionsPropertyEditor extends PropertyEditorSupport
panel.add(label);
minDigitsField = new IntegerTextField(2);
minDigitsField.setAllowNegativeValues(false);
minDigitsField.setDecimalMode();
minDigitsField.setMinValue(BigInteger.ZERO);
minDigitsField.setFormat(IntegerFormat.DEC);
minDigitsField.setMaxValue(BigInteger.valueOf(32));
minDigitsField.getComponent().setToolTipText(MIN_HEX_DIGITS_TOOLTIP);
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,6 +20,7 @@ import java.awt.Container;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyEditorSupport;
import java.math.BigInteger;
import javax.swing.*;
import javax.swing.border.TitledBorder;
@@ -97,7 +98,7 @@ public class ArrayElementPropertyEditor extends PropertyEditorSupport
Container parent) {
IntegerTextField textField = new IntegerTextField(10);
textField.setAllowNegativeValues(false);
textField.setMinValue(BigInteger.ZERO);
textField.setEnabled(true);
JPanel textFieldPanel = new JPanel();
@@ -132,7 +133,8 @@ public class ArrayElementPropertyEditor extends PropertyEditorSupport
}
private void setLocalValues(ArrayElementWrappedOption namespaceOption) {
if (namespaceOption.showMultipleArrayElementPerLine() != groupElementsCheckBox.isSelected()) {
if (namespaceOption.showMultipleArrayElementPerLine() != groupElementsCheckBox
.isSelected()) {
groupElementsCheckBox.setSelected(namespaceOption.showMultipleArrayElementPerLine());
}
if (namespaceOption.getArrayElementsPerLine() != elementsPerLineField.getIntValue()) {
@@ -64,7 +64,7 @@ public class ProgramByteSource implements AddressableByteSource {
long offset = location.getByteAddress().subtract(location.getProgram().getImageBase());
return getProgram().getImageBase().add(offset);
}
public Program getProgram() {
return memory.getProgram();
}