diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java index 24481bbc6c..7b0668e17b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java @@ -15,30 +15,33 @@ */ package ghidra.app.plugin.core.memory; +import java.awt.Cursor; import java.util.*; import java.util.stream.Collectors; import javax.swing.JTable; -import javax.swing.SwingUtilities; import javax.swing.table.TableCellEditor; +import org.apache.commons.lang3.exception.ExceptionUtils; + import docking.widgets.OptionDialog; import docking.widgets.dialogs.NumberInputDialog; import docking.widgets.table.AbstractSortedTableModel; - -/** - * Table Model for a Table where each entry represents a MemoryBlock - * from a Program's Memory. - */ - import ghidra.framework.model.DomainFile; import ghidra.framework.store.LockException; import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; import ghidra.program.model.mem.*; +import ghidra.program.util.ProgramLocation; +import ghidra.program.util.ProgramSelection; import ghidra.util.Msg; +import ghidra.util.Swing; +import ghidra.util.table.ProgramTableModel; -class MemoryMapModel extends AbstractSortedTableModel { +/** + * Table Model for a Table where each entry represents a MemoryBlock from a Program's Memory. + */ +class MemoryMapModel extends AbstractSortedTableModel implements ProgramTableModel { final static byte NAME = 0; final static byte START = 1; @@ -70,9 +73,11 @@ class MemoryMapModel extends AbstractSortedTableModel { final static String SOURCE_COL = "Source"; final static String COMMENT_COL = "Comment"; - private Program program; + private final static Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + private final static Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); - private ArrayList memList; + private Program program; + private List memList; private MemoryMapProvider provider; private final static String COLUMN_NAMES[] = @@ -81,9 +86,12 @@ class MemoryMapModel extends AbstractSortedTableModel { MemoryMapModel(MemoryMapProvider provider, Program program) { super(START); - this.program = program; this.provider = provider; + setProgram(program); + } + void setProgram(Program program) { + this.program = program; populateMap(); } @@ -91,6 +99,7 @@ class MemoryMapModel extends AbstractSortedTableModel { memList = new ArrayList<>(); if (program == null) { + fireTableDataChanged(); return; } @@ -141,12 +150,6 @@ class MemoryMapModel extends AbstractSortedTableModel { return COLUMN_NAMES[column]; } - /** - * Convenience method for locating columns by name. - * Implementation is naive so this should be overridden if - * this method is to be called often. This method is not - * in the TableModel interface and is not used by the JTable. - */ @Override public int findColumn(String columnName) { for (int i = 0; i < COLUMN_NAMES.length; i++) { @@ -157,9 +160,6 @@ class MemoryMapModel extends AbstractSortedTableModel { return 0; } - /** - * Returns Object.class by default - */ @Override public Class getColumnClass(int columnIndex) { if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE || @@ -169,9 +169,6 @@ class MemoryMapModel extends AbstractSortedTableModel { return String.class; } - /** - * Return whether this column is editable. - */ @Override public boolean isCellEditable(int rowIndex, int columnIndex) { @@ -195,15 +192,6 @@ class MemoryMapModel extends AbstractSortedTableModel { } } - /** - * Returns the number of records managed by the data source object. A - * JTable uses this method to determine how many rows it - * should create and display. This method should be quick, as it - * is call by JTable quite frequently. - * - * @return the number or rows in the model - * @see #getColumnCount - */ @Override public int getRowCount() { return memList.size(); @@ -226,157 +214,134 @@ class MemoryMapModel extends AbstractSortedTableModel { if (rowIndex < 0 || rowIndex >= memList.size()) { return null; } - MemoryBlock block = memList.get(rowIndex); - try { - // make sure block is still valid - block.getStart(); - } - catch (ConcurrentModificationException e) { - update(); - } return memList.get(rowIndex); } - /** - * This empty implementation is provided so users don't have to implement - * this method if their data model is not editable. - */ @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - provider.setCursor(MemoryMapPlugin.WAIT_CURSOR); + public void setValueAt(Object aValue, int row, int column) { + provider.setCursor(WAIT_CURSOR); try { - MemoryBlock block = getBlockAt(rowIndex); + MemoryBlock block = getBlockAt(row); if (block == null) { // this can happen when the tool is closing while an edit is open return; } - switch (columnIndex) { - case NAME: - String name = ((String) aValue).trim(); - if (!verifyRenameAllowed(block, name)) { - return; - } - if (name.length() == 0) { - Msg.showError(this, provider.getComponent(), "Enter Block Label", - "Please enter a label name."); - break; - } - if (name.equals(block.getName())) { - break; - } - if (!Memory.isValidMemoryBlockName(name)) { - Msg.showError(this, provider.getComponent(), "Invalid Name", - "Invalid Memory Block Name: " + name); - break; - } - if (!name.equals(block.getName())) { - - program.withTransaction("Rename Memory Block", () -> { - try { - block.setName(name); - } - catch (LockException e) { - provider.setStatusText(e.getMessage()); - } - }); - - } - break; - case READ: { - - program.withTransaction("Set Read State", () -> { - boolean value = ((Boolean) aValue).booleanValue(); - block.setRead(value); - provider.setStatusText(""); - }); - - break; - } - case WRITE: { - - program.withTransaction("Set Write State", () -> { - boolean value = ((Boolean) aValue).booleanValue(); - block.setWrite(value); - provider.setStatusText(""); - }); - - break; - } - case EXECUTE: { - int id = program.startTransaction("Set Execute State"); - try { - boolean value = ((Boolean) aValue).booleanValue(); - block.setExecute(value); - provider.setStatusText(""); - program.endTransaction(id, true); - } - catch (RuntimeException e) { - program.endTransaction(id, false); - throw e; - } - break; - } - case VOLATILE: { - int id = program.startTransaction("Set Volatile State"); - try { - boolean value = ((Boolean) aValue).booleanValue(); - block.setVolatile(value); - provider.setStatusText(""); - program.endTransaction(id, true); - } - catch (RuntimeException e) { - program.endTransaction(id, false); - throw e; - } - break; - } - case INIT: - MemoryBlockType blockType = block.getType(); - if (blockType == MemoryBlockType.BIT_MAPPED || - blockType == MemoryBlockType.BYTE_MAPPED) { - - showMessage("Cannot change intialized memory state of a mapped Block"); - return; - } - provider.setStatusText(""); - boolean booleanValue = ((Boolean) aValue).booleanValue(); - if (booleanValue) { - initializeBlock(block); - } - else { - revertBlockToUninitialized(block); - } - return; - - case SOURCE: - break; - case COMMENT: - String cmt = block.getComment(); - if (cmt == null || !cmt.equals(aValue)) { - String value = (String) aValue; - if (value.length() == 0) { - value = null; - } - int id = program.startTransaction("Set Comment State"); - try { - block.setComment(value); - program.endTransaction(id, true); - } - catch (RuntimeException e) { - program.endTransaction(id, false); - throw e; - } - } - break; - default: - break; - } - fireTableRowsUpdated(rowIndex, rowIndex); + doSetValueAt(aValue, row, column, block); } finally { - provider.setCursor(MemoryMapPlugin.NORM_CURSOR); + provider.setCursor(DEFAULT_CURSOR); + } + } + + private void doSetValueAt(Object aValue, int row, int column, MemoryBlock block) { + + switch (column) { + case NAME: + setName(block, (String) aValue); + break; + case READ: { + program.withTransaction("Set Read State", () -> { + boolean value = ((Boolean) aValue).booleanValue(); + block.setRead(value); + provider.setStatusText(""); + }); + break; + } + case WRITE: { + program.withTransaction("Set Write State", () -> { + boolean value = ((Boolean) aValue).booleanValue(); + block.setWrite(value); + provider.setStatusText(""); + }); + break; + } + case EXECUTE: { + program.withTransaction("Set Execute State", () -> { + boolean value = ((Boolean) aValue).booleanValue(); + block.setExecute(value); + provider.setStatusText(""); + }); + break; + } + case VOLATILE: { + program.withTransaction("Set Volatile State", () -> { + boolean value = ((Boolean) aValue).booleanValue(); + block.setVolatile(value); + provider.setStatusText(""); + }); + break; + } + case INIT: + MemoryBlockType blockType = block.getType(); + if (blockType == MemoryBlockType.BIT_MAPPED || + blockType == MemoryBlockType.BYTE_MAPPED) { + showMessage("Cannot change intialized memory state of a mapped Block"); + break; + } + provider.setStatusText(""); + boolean booleanValue = ((Boolean) aValue).booleanValue(); + if (booleanValue) { + initializeBlock(block); + } + else { + revertBlockToUninitialized(block); + } + break; + case SOURCE: + break; + case COMMENT: + setComment(block, (String) aValue); + break; + default: + break; + } + fireTableRowsUpdated(row, column); + } + + private void setComment(MemoryBlock block, String aValue) { + + String cmt = block.getComment(); + if (cmt == null || !cmt.equals(aValue)) { + if (aValue.length() == 0) { + aValue = null; + } + + String newValue = aValue; + program.withTransaction("Set Comment", () -> { + block.setComment(newValue); + }); + } + } + + private void setName(MemoryBlock block, String name) { + name = name.trim(); + if (!verifyRenameAllowed(block, name)) { + return; + } + if (name.length() == 0) { + Msg.showError(this, provider.getComponent(), "Enter Block Label", + "Please enter a label name."); + return; + } + if (name.equals(block.getName())) { + return; + } + if (!Memory.isValidMemoryBlockName(name)) { + Msg.showError(this, provider.getComponent(), "Invalid Name", + "Invalid Memory Block Name: " + name); + return; + } + + try { + String newName = name; + program.withTransaction("Rename Memory Block", () -> { + block.setName(newName); + }); + } + catch (LockException e) { + this.provider.setStatusText(e.getMessage()); } } @@ -438,15 +403,14 @@ class MemoryMapModel extends AbstractSortedTableModel { } catch (Throwable t) { program.endTransaction(id, false); - String msg = t.getMessage(); - msg = msg == null ? t.toString() : msg; + String msg = ExceptionUtils.getMessage(t); Msg.showError(this, provider.getComponent(), "Block Initialization Failed", msg, t); } } - private void showMessage(final String msg) { + private void showMessage(String msg) { // mouse listeners wipe out the message so show it later... - SwingUtilities.invokeLater(() -> provider.setStatusText(msg)); + Swing.runLater(() -> provider.setStatusText(msg)); } @Override @@ -530,6 +494,44 @@ class MemoryMapModel extends AbstractSortedTableModel { return new MemoryMapComparator(columnIndex); } + @Override + public ProgramLocation getProgramLocation(int row, int column) { + + MemoryBlock block = getRowObject(row); + Address address = block.getStart(); + if (column == END) { + address = block.getEnd(); + } + + return new ProgramLocation(program, address); + } + + @Override + public ProgramSelection getProgramSelection(int[] rows) { + + if (rows.length == 0) { + return null; + } + + AddressSet addressSet = new AddressSet(); + for (int row : rows) { + + MemoryBlock block = getRowObject(row); + Address start = block.getStart(); + Address end = block.getEnd(); + + if (start.isMemoryAddress() && end.isMemoryAddress()) { + addressSet.addRange(start, end); + } + } + return new ProgramSelection(addressSet); + } + + @Override + public Program getProgram() { + return program; + } + private class MemoryMapComparator implements Comparator { private final int sortColumn; @@ -607,4 +609,5 @@ class MemoryMapModel extends AbstractSortedTableModel { } } } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java index 8c580ea169..e3686f353e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java @@ -15,8 +15,6 @@ */ package ghidra.app.plugin.core.memory; -import java.awt.Cursor; - import ghidra.app.CorePluginPackage; import ghidra.app.events.ProgramLocationPluginEvent; import ghidra.app.plugin.PluginCategoryNames; @@ -51,9 +49,6 @@ import ghidra.program.util.ProgramLocation; //@formatter:on public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListener { - final static Cursor WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR); - final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); - private MemoryMapProvider provider; private GoToService goToService; private MemoryMapManager memManager; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java index 9a0e161390..05cab82a3f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java @@ -26,7 +26,6 @@ import javax.swing.table.TableModel; import docking.ActionContext; import docking.action.DockingAction; import docking.action.ToolBarData; -import docking.widgets.label.GLabel; import docking.widgets.table.*; import docking.widgets.textfield.GValidatedTextField.MaxLengthField; import generic.theme.GIcon; @@ -41,18 +40,19 @@ import ghidra.program.model.mem.MemoryBlockType; import ghidra.util.HelpLocation; import ghidra.util.Msg; import ghidra.util.table.GhidraTable; +import ghidra.util.table.GhidraTableFilterPanel; +import ghidra.util.table.actions.MakeProgramSelectionAction; /** * Provider for the memory map Component. - * */ class MemoryMapProvider extends ComponentProviderAdapter { private final static int MAX_SIZE = 256; private JPanel mainPanel; - private GTable memTable; - private JScrollPane memPane; - private MemoryMapModel mapModel; + private MemoryMapModel tableModel; + private GhidraTable table; + private GTableFilterPanel filterPanel; private DockingAction addAction; private DockingAction moveAction; @@ -84,6 +84,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { @Override public void componentShown() { updateMap(); + contextChanged(); } @Override @@ -96,7 +97,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { if (program == null) { return null; } - return new ProgramActionContext(this, program); + return new ProgramActionContext(this, program, table); } void setStatusText(String msg) { @@ -105,7 +106,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { void dispose() { removeFromTool(); - memTable.dispose(); + filterPanel.dispose(); plugin = null; program = null; tool = null; @@ -113,7 +114,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { void setProgram(Program program) { this.program = program; - updateMap(program); + updateProgram(program); arrangeTable(); } @@ -121,69 +122,67 @@ class MemoryMapProvider extends ComponentProviderAdapter { return memManager; } - /** - * Creates the Main Panel for the Memory Map Dialog - */ private JPanel buildMainPanel() { JPanel memPanel = new JPanel(new BorderLayout()); - mapModel = new MemoryMapModel(this, null); - memTable = new MemoryMapTable(mapModel); + tableModel = new MemoryMapModel(this, null); + table = new MemoryMapTable(tableModel); + filterPanel = new GhidraTableFilterPanel<>(table, tableModel); - memTable.setAutoCreateColumnsFromModel(false); + table.setAutoCreateColumnsFromModel(false); GTableCellRenderer monoRenderer = new GTableCellRenderer(); monoRenderer.setFont(monoRenderer.getFixedWidthFont()); - TableColumn column = memTable.getColumn(MemoryMapModel.START_COL); + TableColumn column = table.getColumn(MemoryMapModel.START_COL); column.setCellRenderer(monoRenderer); - column = memTable.getColumn(MemoryMapModel.END_COL); + column = table.getColumn(MemoryMapModel.END_COL); column.setCellRenderer(monoRenderer); - column = memTable.getColumn(MemoryMapModel.LENGTH_COL); + column = table.getColumn(MemoryMapModel.LENGTH_COL); column.setCellRenderer(monoRenderer); - column = memTable.getColumn(MemoryMapModel.READ_COL); + column = table.getColumn(MemoryMapModel.READ_COL); column.setCellRenderer(new GBooleanCellRenderer()); - column = memTable.getColumn(MemoryMapModel.WRITE_COL); + column = table.getColumn(MemoryMapModel.WRITE_COL); column.setCellRenderer(new GBooleanCellRenderer()); - column = memTable.getColumn(MemoryMapModel.EXECUTE_COL); + column = table.getColumn(MemoryMapModel.EXECUTE_COL); column.setCellRenderer(new GBooleanCellRenderer()); - column = memTable.getColumn(MemoryMapModel.VOLATILE_COL); + column = table.getColumn(MemoryMapModel.VOLATILE_COL); column.setCellRenderer(new GBooleanCellRenderer()); - column = memTable.getColumn(MemoryMapModel.OVERLAY_COL); + column = table.getColumn(MemoryMapModel.OVERLAY_COL); column.setCellRenderer(new GBooleanCellRenderer()); - column = memTable.getColumn(MemoryMapModel.INIT_COL); + column = table.getColumn(MemoryMapModel.INIT_COL); column.setCellRenderer(new GBooleanCellRenderer()); - memTable.setDefaultEditor(String.class, + table.setDefaultEditor(String.class, new GTableTextCellEditor(new MaxLengthField(MAX_SIZE))); - memPane = new JScrollPane(memTable); - memTable.setPreferredScrollableViewportSize(new Dimension(700, 105)); + table.setPreferredScrollableViewportSize(new Dimension(700, 105)); - memTable.addMouseListener(new MouseHandler()); + table.addMouseListener(new MouseHandler()); - memTable.addKeyListener(new KeyHandler()); + table.addKeyListener(new KeyHandler()); - memTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - ListSelectionModel lsm = memTable.getSelectionModel(); + table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + ListSelectionModel lsm = table.getSelectionModel(); lsm.addListSelectionListener(e -> { - // Ignore extra messages. if (e.getValueIsAdjusting()) { return; } ListSelectionModel model = (ListSelectionModel) e.getSource(); enableOptions(model); + contextChanged(); }); - memPanel.add(new GLabel("Memory Blocks", SwingConstants.CENTER), BorderLayout.NORTH); - memPanel.add(memPane, BorderLayout.CENTER); + memPanel.add(new JScrollPane(table), BorderLayout.CENTER); + memPanel.add(filterPanel, BorderLayout.SOUTH); return memPanel; } private void addLocalActions() { + Icon addImage = new GIcon("icon.plugin.memorymap.add"); addAction = new MemoryMapAction("Add Block", addImage) { @@ -294,6 +293,11 @@ class MemoryMapProvider extends ComponentProviderAdapter { setBaseAction.setDescription("Set Image Base"); tool.addLocalAction(this, setBaseAction); + + MakeProgramSelectionAction action = + new MakeProgramSelectionAction(plugin, table); + action.getToolBarData().setToolBarGroup("B"); // the other actions are in group 'A' + tool.addLocalAction(this, action); } private void setBase() { @@ -332,12 +336,6 @@ class MemoryMapProvider extends ComponentProviderAdapter { } } - /** - * Enable/disable the expand up/down actions according to the selected - * block. - * - * @param numSelected number of blocks selected - */ private void enableExpandActions(int numSelected) { if (numSelected != 1) { expandUpAction.setEnabled(false); @@ -368,7 +366,11 @@ class MemoryMapProvider extends ComponentProviderAdapter { } JTable getTable() { - return memTable; + return table; + } + + MemoryMapModel getModel() { + return tableModel; } /** @@ -376,7 +378,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { */ void updateMap() { if (isVisible()) { - mapModel.update(); + tableModel.update(); arrangeTable(); updateTitle(); } @@ -385,7 +387,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { void updateData() { if (isVisible()) { updateTitle(); - memTable.repaint(); + table.repaint(); } } @@ -398,9 +400,9 @@ class MemoryMapProvider extends ComponentProviderAdapter { /** * Update the memory map with the new program's memory */ - private void updateMap(Program updateProgram) { + private void updateProgram(Program updatedProgram) { enableOptions(null); - if (updateProgram == null) { + if (updatedProgram == null) { addAction.setEnabled(false); setBaseAction.setEnabled(false); } @@ -408,8 +410,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { setBaseAction.setEnabled(true); } - mapModel = new MemoryMapModel(this, updateProgram); - memTable.setModel(mapModel); + tableModel.setProgram(updatedProgram); updateTitle(); } @@ -420,48 +421,48 @@ class MemoryMapProvider extends ComponentProviderAdapter { // memTable.setRowHeight(20); TableColumn column; - column = memTable.getColumn(MemoryMapModel.READ_COL); + column = table.getColumn(MemoryMapModel.READ_COL); if (column != null) { column.setMaxWidth(25); column.setMinWidth(25); column.setResizable(false); } - column = memTable.getColumn(MemoryMapModel.WRITE_COL); + column = table.getColumn(MemoryMapModel.WRITE_COL); if (column != null) { column.setMaxWidth(25); column.setMinWidth(25); column.setResizable(false); } - column = memTable.getColumn(MemoryMapModel.EXECUTE_COL); + column = table.getColumn(MemoryMapModel.EXECUTE_COL); if (column != null) { column.setMaxWidth(25); column.setMinWidth(25); column.setResizable(false); } - column = memTable.getColumn(MemoryMapModel.VOLATILE_COL); + column = table.getColumn(MemoryMapModel.VOLATILE_COL); if (column != null) { column.setMaxWidth(65); column.setMinWidth(65); column.setResizable(false); } - column = memTable.getColumn(MemoryMapModel.OVERLAY_COL); + column = table.getColumn(MemoryMapModel.OVERLAY_COL); if (column != null) { column.setMaxWidth(65); column.setMinWidth(65); column.setResizable(false); } - column = memTable.getColumn(MemoryMapModel.BLOCK_TYPE_COL); + column = table.getColumn(MemoryMapModel.BLOCK_TYPE_COL); if (column != null) { column.setMinWidth(60); // column.setResizable(true); } - column = memTable.getColumn(MemoryMapModel.INIT_COL); + column = table.getColumn(MemoryMapModel.INIT_COL); if (column != null) { column.setMaxWidth(80); column.setMinWidth(80); @@ -484,7 +485,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { if (!e.isPopupTrigger()) { if ((e.getModifiersEx() & (InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) == 0) { - selectAddress(); + navigateToAddress(); } } } @@ -499,30 +500,30 @@ class MemoryMapProvider extends ComponentProviderAdapter { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { - selectAddress(); + navigateToAddress(); e.consume(); } } } - private void selectAddress() { - int row = memTable.getSelectedRow(); - int viewColumn = memTable.getSelectedColumn(); - int col = memTable.convertColumnIndexToModel(viewColumn); - MemoryBlock block = mapModel.getBlockAt(row); - if (block != null && (col == 1 || col == 2)) { - Address addr = (col == 1 ? block.getStart() : block.getEnd()); + private void navigateToAddress() { + int viewRow = table.getSelectedRow(); + int viewColumn = table.getSelectedColumn(); + int modelColumn = table.convertColumnIndexToModel(viewColumn); + MemoryBlock block = tableModel.getBlockAt(viewRow); + if (block != null && (modelColumn == 1 || modelColumn == 2)) { + Address addr = (modelColumn == 1 ? block.getStart() : block.getEnd()); plugin.blockSelected(block, addr); - memTable.setRowSelectionInterval(row, row); + table.setRowSelectionInterval(viewRow, viewRow); } } private MemoryBlock getSelectedBlock() { - int row = memTable.getSelectedRow(); + int row = table.getSelectedRow(); if (row < 0) { return null; } - return mapModel.getBlockAt(row); + return tableModel.getBlockAt(row); } /** @@ -534,12 +535,12 @@ class MemoryMapProvider extends ComponentProviderAdapter { return; } ArrayList delBlocks = new ArrayList<>(); - int delRows[] = memTable.getSelectedRows(); + int delRows[] = table.getSelectedRows(); for (int element : delRows) { - MemoryBlock block = mapModel.getBlockAt(element); + MemoryBlock block = tableModel.getBlockAt(element); delBlocks.add(block); } - memTable.clearSelection(); + table.clearSelection(); deleteBlock(delBlocks); } @@ -642,12 +643,12 @@ class MemoryMapProvider extends ComponentProviderAdapter { */ private void mergeBlocks() { ArrayList blocks = new ArrayList<>(); - int rows[] = memTable.getSelectedRows(); + int rows[] = table.getSelectedRows(); for (int element : rows) { - MemoryBlock block = mapModel.getBlockAt(element); + MemoryBlock block = tableModel.getBlockAt(element); blocks.add(block); } - memTable.clearSelection(); + table.clearSelection(); memManager.mergeBlocks(blocks); } @@ -670,9 +671,9 @@ class MemoryMapProvider extends ComponentProviderAdapter { return plugin.getTool(); } -// ================================================================================================== +//================================================================================================== // Inner Classes -// ================================================================================================== +//================================================================================================== private class MemoryMapTable extends GhidraTable { MemoryMapTable(TableModel model) { @@ -691,7 +692,7 @@ class MemoryMapProvider extends ComponentProviderAdapter { private abstract class MemoryMapAction extends DockingAction { MemoryMapAction(String name, Icon icon) { super(name, plugin.getName()); - this.setToolBarData(new ToolBarData(icon, null)); + this.setToolBarData(new ToolBarData(icon, "A")); } public boolean checkExclusiveAccess() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/table/ProgramTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/util/table/ProgramTableModel.java index 15e98926a0..db47a012a8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/util/table/ProgramTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/util/table/ProgramTableModel.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,31 +20,28 @@ import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; /** - * An interface for translating table rows and columns - * into program locations and selections. + * An interface for translating table rows and columns into program locations and selections. */ public interface ProgramTableModel { - /** - * Returns a program location corresponding the given row and column. - * Motivation: - * Given a table that has a column that contains addresses. - * If the user clicks on this column, then it would be nice - * to have the CodeBrowser navigate to this address. - * @param row the row - * @param column the column - * @return a program location corresponding the given row and column - */ - public ProgramLocation getProgramLocation(int row, int column); + /** + * Returns a program location corresponding the given row and column. + *

+ * Motivation: Given a table that has a column that contains addresses. If the user clicks on + * this column, then it would be nice to have the CodeBrowser navigate to this address. + * @param row the row + * @param modelColumn the column in the model's index + * @return a program location corresponding the given row and column + */ + public ProgramLocation getProgramLocation(int row, int modelColumn); /** - * Returns a program selection corresponding to the - * specified row index array. This array will contain - * the currently selected rows. + * Returns a program selection corresponding to the specified row index array. This array will + * contain the currently selected rows. * @param rows the currently selected rows. * @return a program selection */ public ProgramSelection getProgramSelection(int[] rows); - + /** * Returns the program associated with this ProgramTableModel. * @return the program associated with this ProgramTableModel. diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java index 7d5411aedb..14609c3524 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java @@ -673,8 +673,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest waitForSwing(); provider = plugin.getMemoryMapProvider(); table = provider.getTable(); - model = (MemoryMapModel) table.getModel(); - + model = provider.getModel(); } private Address getAddr(long offset) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java index ee68c99661..67c3eeaf81 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java @@ -109,7 +109,8 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement private static final Icon ICON_HOME = new GIcon("icon.filechooser.places.home"); private static final Icon ICON_RECENT = new GIcon("icon.filechooser.places.recent"); - // base and overlay? + private final static Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + private final static Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); /** Instruction to display only files. */ public static final int FILES_ONLY = 0; @@ -464,13 +465,13 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement @Override public void mouseEntered(MouseEvent e) { - waitPanel.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + waitPanel.setCursor(WAIT_CURSOR); e.consume(); } @Override public void mouseExited(MouseEvent e) { - waitPanel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + waitPanel.setCursor(DEFAULT_CURSOR); } }); waitPanel.addMouseMotionListener(new MouseMotionAdapter() { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeArchiveTransformerPanel.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeArchiveTransformerPanel.java index 3d27079373..f39a68704b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeArchiveTransformerPanel.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeArchiveTransformerPanel.java @@ -32,8 +32,8 @@ import ghidra.util.task.TaskMonitor; public class DataTypeArchiveTransformerPanel extends JPanel { - private final static Cursor WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR); - private final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); + private final static Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + private final static Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); private JPanel filePanel; private JTextField oldFileTextField; @@ -85,7 +85,7 @@ public class DataTypeArchiveTransformerPanel extends JPanel { oldBrowseButton.addActionListener(e -> { setCursor(WAIT_CURSOR); File file = chooseFile("Choose old data type archive"); - setCursor(NORM_CURSOR); + setCursor(DEFAULT_CURSOR); if (file != null) { oldFileTextField.setText(file.getAbsolutePath()); } @@ -119,7 +119,7 @@ public class DataTypeArchiveTransformerPanel extends JPanel { newBrowseButton.addActionListener(e -> { setCursor(WAIT_CURSOR); File file = chooseFile("Choose new data type archive"); - setCursor(NORM_CURSOR); + setCursor(DEFAULT_CURSOR); if (file != null) { newFileTextField.setText(file.getAbsolutePath()); } @@ -148,7 +148,7 @@ public class DataTypeArchiveTransformerPanel extends JPanel { destinationBrowseButton.addActionListener(e -> { setCursor(WAIT_CURSOR); File file = chooseFile("Choose destination file"); - setCursor(NORM_CURSOR); + setCursor(DEFAULT_CURSOR); if (file != null) { destinationFileTextField.setText(file.getAbsolutePath()); }