mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
GT-2844 - Data Type Preview - fixed bug that cased rendering failure in
table
This commit is contained in:
parent
c4bbff8195
commit
85a1017102
@ -51,6 +51,7 @@ class DataTypePreview implements Preview {
|
||||
return dt.getRepresentation(mb, new SettingsImpl(), length);
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
return "ERROR: unable to create preview";
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,9 @@ import ghidra.util.HelpLocation;
|
||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||
import ghidra.util.table.GhidraTable;
|
||||
import ghidra.util.task.SwingUpdateManager;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import resources.ResourceManager;
|
||||
import util.CollectionUtils;
|
||||
|
||||
//@formatter:off
|
||||
@PluginInfo(
|
||||
@ -56,7 +57,8 @@ import resources.ResourceManager;
|
||||
packageName = CorePluginPackage.NAME,
|
||||
category = PluginCategoryNames.CODE_VIEWER,
|
||||
shortDescription = "Data Type Preview Plugin",
|
||||
description = "This plugin provides a preview of bytes at an address based on data types that you choose to view."
|
||||
description = "This plugin provides a preview of bytes at an address based on data types " +
|
||||
"that you choose to view."
|
||||
)
|
||||
//@formatter:on
|
||||
public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
@ -66,10 +68,10 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
private DTPPTable table;
|
||||
private DTPPScrollPane component;
|
||||
private Address currentAddress;
|
||||
private GoToService gotoService;
|
||||
private GoToService goToService;
|
||||
private DockingAction addAction;
|
||||
private DockingAction deleteAction;
|
||||
private DataTypeManager dataTypeMgr;
|
||||
private DataTypeManager dataTypeManager;
|
||||
private Program activeProgram;
|
||||
|
||||
private SwingUpdateManager updateManager = new SwingUpdateManager(650, () -> updatePreview());
|
||||
@ -83,7 +85,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
}
|
||||
|
||||
GoToService getGoToService() {
|
||||
return gotoService;
|
||||
return goToService;
|
||||
}
|
||||
|
||||
DTPPComponentProvider getProvider() {
|
||||
@ -94,12 +96,12 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
gotoService = tool.getService(GoToService.class);
|
||||
goToService = tool.getService(GoToService.class);
|
||||
|
||||
model = new DTPPTableModel();
|
||||
table = new DTPPTable(model);
|
||||
component = new DTPPScrollPane(table);
|
||||
dataTypeMgr = new LayeredDataTypeManager();
|
||||
dataTypeManager = new LayeredDataTypeManager();
|
||||
|
||||
addDataType(new ByteDataType());
|
||||
addDataType(new WordDataType());
|
||||
@ -117,6 +119,20 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
createActions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(Class<?> interfaceClass, Object service) {
|
||||
if (interfaceClass == GoToService.class) {
|
||||
goToService = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceAdded(Class<?> interfaceClass, Object service) {
|
||||
if (interfaceClass == GoToService.class) {
|
||||
goToService = (GoToService) service;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
updateManager.dispose();
|
||||
@ -141,9 +157,9 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
}
|
||||
|
||||
void updateModel() {
|
||||
int transactionId = dataTypeMgr.startTransaction("realign");
|
||||
int transactionId = dataTypeManager.startTransaction("realign");
|
||||
try {
|
||||
Iterator<Composite> allComposites = dataTypeMgr.getAllComposites();
|
||||
Iterator<Composite> allComposites = dataTypeManager.getAllComposites();
|
||||
while (allComposites.hasNext()) {
|
||||
Composite composite = allComposites.next();
|
||||
if (composite.isInternallyAligned()) {
|
||||
@ -154,7 +170,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
}
|
||||
}
|
||||
finally {
|
||||
dataTypeMgr.endTransaction(transactionId, true);
|
||||
dataTypeManager.endTransaction(transactionId, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,9 +220,10 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
@Override
|
||||
public void readConfigState(SaveState saveState) {
|
||||
String[] names = saveState.getNames();
|
||||
if (names == null || names.length == 0) {
|
||||
if (CollectionUtils.isBlank(names)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuiltInDataTypeManager builtInMgr = BuiltInDataTypeManager.getDataTypeManager();
|
||||
try {
|
||||
for (String element : names) {
|
||||
@ -214,12 +231,9 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
if (path == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DataType dt = builtInMgr.getDataType(new CategoryPath(path), element);
|
||||
if (dt != null) {
|
||||
if (!model.contains(dt)) {
|
||||
addDataType(dt);
|
||||
}
|
||||
}
|
||||
addDataType(dt);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@ -233,9 +247,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
while (iter.hasNext()) {
|
||||
Preview preview = iter.next();
|
||||
DataType dt = preview.getDataType();
|
||||
if (dt instanceof BuiltIn) {
|
||||
saveState.putString(dt.getName(), dt.getCategoryPath().getPath());
|
||||
}
|
||||
saveState.putString(dt.getName(), dt.getCategoryPath().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,32 +297,38 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
AllowedDataTypes.FIXED_LENGTH);
|
||||
tool.showDialog(d, provider);
|
||||
DataType dt = d.getUserChosenDataType();
|
||||
if (dt != null) {
|
||||
addDataType(dt);
|
||||
}
|
||||
addDataType(dt);
|
||||
}
|
||||
|
||||
void addDataType(DataType dt) {
|
||||
int transactionID = dataTypeMgr.startTransaction("Add dataType");
|
||||
|
||||
if (dt == null || model.contains(dt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int transactionID = dataTypeManager.startTransaction("Add dataType");
|
||||
try {
|
||||
DataType resolvedDt = dataTypeMgr.resolve(dt, null);
|
||||
DataType resolvedDt = dataTypeManager.resolve(dt, null);
|
||||
model.add(resolvedDt);
|
||||
}
|
||||
finally {
|
||||
dataTypeMgr.endTransaction(transactionID, true);
|
||||
dataTypeManager.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeDataType(DataType dt) {
|
||||
int transactionID = dataTypeMgr.startTransaction("Remove dataType");
|
||||
int transactionID = dataTypeManager.startTransaction("Remove dataType");
|
||||
try {
|
||||
model.removeAll(dt);
|
||||
dataTypeMgr.remove(dt, null);
|
||||
|
||||
// Note: do not do this, as there may be user-added composites that are based on
|
||||
// the type being removed. For now, let the 'fake' DTM grow forever (this should
|
||||
// never become a problem).
|
||||
// dataTypeManager.remove(dt, null);
|
||||
}
|
||||
finally {
|
||||
dataTypeMgr.endTransaction(transactionID, true);
|
||||
dataTypeManager.endTransaction(transactionID, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void delete() {
|
||||
@ -431,8 +449,13 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
if (queryString == null) {
|
||||
return;
|
||||
}
|
||||
gotoService.goToQuery(currentAddress, new QueryData(queryString, false), null,
|
||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
|
||||
if (goToService == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
goToService.goToQuery(currentAddress, new QueryData(queryString, false), null,
|
||||
TaskMonitor.DUMMY);
|
||||
}
|
||||
table.handleTableSelection();
|
||||
}
|
||||
@ -442,7 +465,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
final static int NAME_COL = 0;
|
||||
final static int PREVIEW_COL = 1;
|
||||
|
||||
private ArrayList<Preview> data = new ArrayList<>();
|
||||
private List<Preview> data = new ArrayList<>();
|
||||
|
||||
String getPreviewAt(int row) {
|
||||
if (currentProgram == null) {
|
||||
@ -530,28 +553,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
return removed;
|
||||
}
|
||||
|
||||
boolean removeAll(CategoryPath deletedDataTypePath) {
|
||||
boolean removed = false;
|
||||
String dtName = deletedDataTypePath.getName();
|
||||
CategoryPath dtParent = deletedDataTypePath.getParent();
|
||||
ArrayList<Preview> clone = new ArrayList<>(data);
|
||||
Iterator<Preview> iter = clone.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Object obj = iter.next();
|
||||
Preview preview = (Preview) obj;
|
||||
DataType dt = preview.getDataType();
|
||||
if (dt.getName().equals(dtName) && dt.getCategoryPath().equals(dtParent)) {
|
||||
data.remove(preview);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
fireTableDataChanged();
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
boolean isValid(DataType dt) {
|
||||
private boolean isValid(DataType dt) {
|
||||
if (dt == null) {
|
||||
return false;
|
||||
}
|
||||
@ -571,7 +573,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean contains(DataType dt) {
|
||||
private boolean contains(DataType dt) {
|
||||
Iterator<Preview> iter = data.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Preview p = iter.next();
|
||||
@ -677,7 +679,7 @@ public class DataTypePreviewPlugin extends ProgramPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
public class LayeredDataTypeManager extends StandAloneDataTypeManager {
|
||||
private class LayeredDataTypeManager extends StandAloneDataTypeManager {
|
||||
|
||||
public LayeredDataTypeManager() {
|
||||
super("DataTypePreviewer");
|
||||
|
@ -23,6 +23,7 @@ import java.util.Objects;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import ghidra.util.SystemUtilities;
|
||||
import util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* A builder object that allows clients to launch tasks in the background, with a progress
|
||||
@ -137,7 +138,7 @@ public class TaskBuilder {
|
||||
* @return this builder
|
||||
*/
|
||||
public TaskBuilder setStatusTextAlignment(int alignment) {
|
||||
boolean isValid = SystemUtilities.isOneOf(alignment, LEADING, CENTER, TRAILING);
|
||||
boolean isValid = CollectionUtils.isOneOf(alignment, LEADING, CENTER, TRAILING);
|
||||
SystemUtilities.assertTrue(isValid, "Illegal alignment argument: " + alignment);
|
||||
|
||||
this.statusTextAlignment = alignment;
|
||||
|
@ -365,6 +365,27 @@ public class CollectionUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given array is null or has 0 length
|
||||
*
|
||||
* @param c the collection to check
|
||||
* @return true if blank
|
||||
*/
|
||||
public static <T> boolean isBlank(Collection<T> c) {
|
||||
return c == null || c.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given array is null or has 0 length
|
||||
*
|
||||
* @param t the items to check
|
||||
* @return true if blank
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> boolean isBlank(T... t) {
|
||||
return t == null || t.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the given item into an iterable
|
||||
* @param t the object from which to create an iterable
|
||||
|
@ -341,23 +341,6 @@ public class SystemUtilities {
|
||||
return Objects.equals(o1, o2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given element is equals to one of the provided elements.
|
||||
*
|
||||
* @param o the element to test
|
||||
* @param others the potential matches
|
||||
* @return true if the given element is equals to one of the provided elements.
|
||||
*/
|
||||
@SafeVarargs // we are not using the provided type, so there is no pollution
|
||||
public static <T> boolean isOneOf(T o, T... others) {
|
||||
for (T t : others) {
|
||||
if (o.equals(t)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compareTo(T c1, T c2) {
|
||||
if (c1 == null) {
|
||||
return c2 == null ? 0 : 1;
|
||||
|
Loading…
Reference in New Issue
Block a user