GT-2844 - Data Type Preview - fixed bug that cased rendering failure in

table
This commit is contained in:
dragonmacher 2019-05-02 10:42:44 -04:00
parent c4bbff8195
commit 85a1017102
5 changed files with 82 additions and 74 deletions

View File

@ -51,6 +51,7 @@ class DataTypePreview implements Preview {
return dt.getRepresentation(mb, new SettingsImpl(), length);
}
catch (Exception e) {
return "ERROR: unable to create preview";
}
}

View File

@ -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");

View File

@ -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;

View File

@ -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

View File

@ -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;