Skip to content

Commit 1a47a82

Browse files
committed
Merge branch 'GP-4270_dragonmacher'
2 parents 59972bb + 1cf7803 commit 1a47a82

File tree

22 files changed

+298
-186
lines changed

22 files changed

+298
-186
lines changed

Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompilerDisposer.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/* ###
22
* IP: GHIDRA
3-
* REVIEWED: YES
43
*
54
* Licensed under the Apache License, Version 2.0 (the "License");
65
* you may not use this file except in compliance with the License.
@@ -16,11 +15,11 @@
1615
*/
1716
package ghidra.app.decompiler;
1817

18+
import java.io.*;
19+
1920
import generic.concurrent.*;
2021
import ghidra.util.task.TaskMonitor;
2122

22-
import java.io.*;
23-
2423
public class DecompilerDisposer {
2524
private static String THREAD_POOL_NAME = "Decompiler Disposer";
2625
private static ConcurrentQ<AbstractDisposable, AbstractDisposable> queue;
@@ -38,7 +37,7 @@ private DecompilerDisposer() {
3837
/**
3938
* Disposes the given Process and related streams from a background thread. This is necessary
4039
* due to a low-probability deadlock that occurs in the JVM.
41-
*
40+
*
4241
* @param process The process to destroy.
4342
* @param ouputStream The output stream to close
4443
* @param inputStream The input stream to close
@@ -54,23 +53,24 @@ public static void dispose(Process process, OutputStream ouputStream, InputStrea
5453
* <p>
5554
* Note:<br>
5655
* A class to handle the rare case where the {@link DecompInterface}'s
57-
* synchronized methods are blocking
56+
* synchronized methods are blocking
5857
* while a decompile operation has died and maintained the lock. In that scenario, calling
59-
* dispose on this class will eventually try to enter a synchronized method that will
58+
* dispose on this class will eventually try to enter a synchronized method that will
6059
* remain blocked forever.
6160
* <p>
62-
* I examined the uses of dispose() on the {@link DecompInterface} and
61+
* I examined the uses of dispose() on the {@link DecompInterface} and
6362
* determined that calling dispose() is a
6463
* final operation, which means that you don't have to wait. Further, after calling
6564
* dispose() on this class, you should no longer use it.
65+
* @param decompiler the decompiler
6666
*/
6767
public static void dispose(DecompInterface decompiler) {
6868
DecompInterfaceDisposable disposable = new DecompInterfaceDisposable(decompiler);
6969
queue.add(disposable);
7070
}
7171

72-
private static class DisposeCallback implements
73-
QCallback<AbstractDisposable, AbstractDisposable> {
72+
private static class DisposeCallback
73+
implements QCallback<AbstractDisposable, AbstractDisposable> {
7474
@Override
7575
public AbstractDisposable process(AbstractDisposable disposable, TaskMonitor monitor) {
7676
disposable.dispose();
@@ -87,7 +87,8 @@ private static class RuntimeProcessDisposable extends AbstractDisposable {
8787
private OutputStream ouputStream;
8888
private InputStream inputStream;
8989

90-
RuntimeProcessDisposable(Process process, OutputStream ouputStream, InputStream inputStream) {
90+
RuntimeProcessDisposable(Process process, OutputStream ouputStream,
91+
InputStream inputStream) {
9192
this.process = process;
9293
this.ouputStream = ouputStream;
9394
this.inputStream = inputStream;

Ghidra/Framework/Docking/src/main/java/docking/PopupMenuContext.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
import java.awt.event.MouseEvent;
2121
import java.util.Objects;
2222

23+
import generic.json.Json;
24+
2325
/**
24-
* A class that holds information used to show a popup menu
26+
* A class that holds information used to show a popup menu
2527
*/
2628
public class PopupMenuContext {
2729

@@ -58,4 +60,9 @@ public Object getSource() {
5860
}
5961
return component;
6062
}
63+
64+
@Override
65+
public String toString() {
66+
return Json.toString(this);
67+
}
6168
}

Ghidra/Framework/Docking/src/main/java/docking/widgets/DefaultDropDownSelectionDataModel.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ public List<T> getMatchingData(String searchText) {
7474

7575
@Override
7676
public int getIndexOfFirstMatchingEntry(List<T> list, String text) {
77-
// The data are sorted such that lower-case is before upper-case and smaller length
78-
// matches come before longer matches. If we ever find a case-sensitive exact match,
79-
// use that. Otherwise, keep looking for a case-insensitive exact match. The
80-
// case-insensitive match is preferred over a non-matching item. Once we get to a
77+
// The data are sorted such that lower-case is before upper-case and smaller length
78+
// matches come before longer matches. If we ever find a case-sensitive exact match,
79+
// use that. Otherwise, keep looking for a case-insensitive exact match. The
80+
// case-insensitive match is preferred over a non-matching item. Once we get to a
8181
// non-matching item, we can quit.
8282
int lastPreferredMatchIndex = -1;
8383
for (int i = 0; i < list.size(); i++) {
@@ -118,7 +118,7 @@ public String getDisplayText(T value) {
118118

119119
//==================================================================================================
120120
// Inner Classes
121-
//==================================================================================================
121+
//==================================================================================================
122122

123123
private class ObjectStringComparator implements Comparator<Object> {
124124
Comparator<String> stringComparator = new CaseInsensitiveDuplicateStringComparator();

Ghidra/Framework/Docking/src/main/java/docking/widgets/ListSelectionDialog.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public class ListSelectionDialog<T> extends DialogComponentProvider {
3333

3434
private DropDownSelectionTextField<T> field;
3535
protected boolean cancelled;
36-
private RowObjectTableModel<T> userTableModel;
3736
private DataToStringConverter<T> searchConverter;
3837
private DataToStringConverter<T> descriptionConverter;
3938
private List<T> data;
@@ -61,8 +60,12 @@ public ListSelectionDialog(String title, String label, List<T> data,
6160
this.data = data;
6261
this.searchConverter = searchConverter;
6362
this.descriptionConverter = descriptionConverter;
63+
64+
// Use a separate list for the drop down widget, since it needs to sort its data and we do
65+
// not want to change the client data sort.
66+
List<T> dropDownData = new ArrayList<>(data);
6467
DefaultDropDownSelectionDataModel<T> model = new DefaultDropDownSelectionDataModel<>(
65-
new ArrayList<>(data), searchConverter, descriptionConverter) {
68+
dropDownData, searchConverter, descriptionConverter) {
6669

6770
// overridden to return all data for an empty search; this lets the down-arrow
6871
// show the full list
@@ -151,14 +154,18 @@ protected void browse() {
151154
}
152155

153156
private RowObjectTableModel<T> getTableModel() {
154-
if (userTableModel != null) {
155-
return userTableModel;
156-
}
157-
158-
return new DefaultTableModel();
157+
return new DefaultTableModel(data);
159158
}
160159

161160
private class DefaultTableModel extends AbstractGTableModel<T> {
161+
162+
private List<T> modelData;
163+
164+
DefaultTableModel(List<T> modelData) {
165+
// copy the data so that a call to dispose() will not clear the data in the outer class
166+
this.modelData = new ArrayList<>(modelData);
167+
}
168+
162169
@Override
163170
public String getColumnName(int columnIndex) {
164171
if (columnIndex == 0) {
@@ -184,7 +191,7 @@ public boolean isCellEditable(int rowIndex, int columnIndex) {
184191

185192
@Override
186193
public List<T> getModelData() {
187-
return data;
194+
return modelData;
188195
}
189196

190197
@Override

Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractDynamicTableColumn.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
* determines the appropriate cell object for use by the table column this field represents. It can
3030
* then return the appropriate object to display in the table cell for the indicated row object.
3131
*
32-
* Implementations of this interface must provide a public default constructor.
33-
*
3432
* @param <ROW_TYPE> The row object class supported by this column
3533
* @param <COLUMN_TYPE> The column object class supported by this column
3634
* @param <DATA_SOURCE> The object class type that will be passed to see
@@ -95,8 +93,8 @@ public Comparator<COLUMN_TYPE> getComparator(DynamicColumnTableModel<?> model,
9593
public Class<COLUMN_TYPE> getColumnClass() {
9694
@SuppressWarnings("rawtypes")
9795
Class<? extends AbstractDynamicTableColumn> implementationClass = getClass();
98-
List<Class<?>> typeArguments = ReflectionUtilities.getTypeArguments(
99-
AbstractDynamicTableColumn.class, implementationClass);
96+
List<Class<?>> typeArguments = ReflectionUtilities
97+
.getTypeArguments(AbstractDynamicTableColumn.class, implementationClass);
10098
return (Class<COLUMN_TYPE>) typeArguments.get(1);
10199
}
102100

@@ -106,8 +104,8 @@ public Class<COLUMN_TYPE> getColumnClass() {
106104
public Class<ROW_TYPE> getSupportedRowType() {
107105
@SuppressWarnings("rawtypes")
108106
Class<? extends AbstractDynamicTableColumn> implementationClass = getClass();
109-
List<Class<?>> typeArguments = ReflectionUtilities.getTypeArguments(
110-
AbstractDynamicTableColumn.class, implementationClass);
107+
List<Class<?>> typeArguments = ReflectionUtilities
108+
.getTypeArguments(AbstractDynamicTableColumn.class, implementationClass);
111109
return (Class<ROW_TYPE>) typeArguments.get(0);
112110
}
113111

@@ -193,7 +191,7 @@ public final int hashCode() {
193191
return getIdentifier().hashCode();
194192
}
195193

196-
// Note: this method is here because the default 'identifier' must be lazy loaded, as
194+
// Note: this method is here because the default 'identifier' must be lazy loaded, as
197195
// at construction time not all the variables needed are available.
198196
private String getIdentifier() {
199197
/*
@@ -202,7 +200,7 @@ private String getIdentifier() {
202200
-The case where 2 different column classes share the same column header value
203201
-The case where a single column class is used repeatedly, with a different
204202
column header value each time
205-
203+
206204
Thus, to be unique, we need to combine both the class name and the column header
207205
value. The only time this may be an issue is if the column header value changes
208206
dynamically--not sure if this actually happens anywhere in our system. If it did,

Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AbstractDynamicTableColumnStub.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
7-
*
7+
*
88
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
9+
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,14 +20,18 @@
2020

2121
/**
2222
* This class is meant to be used by DynamicTableColumn implementations that do not care about
23-
* the DATA_SOURCE parameter of DynamicTableColumn. This class will stub the default
23+
* the DATA_SOURCE parameter of DynamicTableColumn. This class will stub the default
2424
* {@link #getValue(Object, Settings, Object, ServiceProvider)} method and
2525
* call a version of the method that does not have the DATA_SOURCE parameter.
26+
* <p>
27+
* Subclasses are not discoverable. To create discoverable columns for the framework, you must
28+
* extends {@link DynamicTableColumnExtensionPoint}.
29+
*
2630
* @param <ROW_TYPE> the row type
2731
* @param <COLUMN_TYPE> the column type
2832
*/
29-
public abstract class AbstractDynamicTableColumnStub<ROW_TYPE, COLUMN_TYPE> extends
30-
AbstractDynamicTableColumn<ROW_TYPE, COLUMN_TYPE, Object> {
33+
public abstract class AbstractDynamicTableColumnStub<ROW_TYPE, COLUMN_TYPE>
34+
extends AbstractDynamicTableColumn<ROW_TYPE, COLUMN_TYPE, Object> {
3135

3236
@Override
3337
public COLUMN_TYPE getValue(ROW_TYPE rowObject, Settings settings, Object data,

Ghidra/Framework/Docking/src/main/java/docking/widgets/table/AnyObjectTableModel.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ private static char maybeToUpperCase(char c, boolean shouldBeUpper) {
156156
}
157157

158158
private class MethodColumn extends AbstractDynamicTableColumn<T, Object, Object> {
159-
private String name;
159+
private String methodName;
160160
private Method method;
161161
private Class<?> returnType;
162162

@@ -166,7 +166,7 @@ public MethodColumn(Class<T> dataClass, String methodName) {
166166
init(m);
167167
}
168168
catch (NoSuchMethodException | SecurityException e) {
169-
name = "No method: " + methodName;
169+
this.methodName = "No method: " + methodName;
170170
}
171171
}
172172

@@ -181,12 +181,12 @@ public String getColumnDescription() {
181181

182182
private void init(Method m) {
183183
this.method = m;
184-
name = method.getName();
185-
if (name.startsWith("get")) {
186-
name = name.substring(3);
184+
methodName = method.getName();
185+
if (methodName.startsWith("get")) {
186+
methodName = methodName.substring(3);
187187
}
188188

189-
name = fromCamelCase(name);
189+
methodName = fromCamelCase(methodName);
190190
returnType = method.getReturnType();
191191
}
192192

@@ -198,15 +198,15 @@ public Class<Object> getColumnClass() {
198198

199199
@Override
200200
public String getColumnName() {
201-
return name;
201+
return methodName;
202202
}
203203

204204
@Override
205205
public Object getValue(T rowObject, Settings settings, Object dataSource,
206206
ServiceProvider sp) throws IllegalArgumentException {
207207
if (method == null) {
208-
Msg.error(this,
209-
"No method '" + name + "' on class" + rowObject.getClass().getSimpleName());
208+
Msg.error(this, "No method '" + methodName + "' on class " +
209+
rowObject.getClass().getSimpleName());
210210
return null;
211211
}
212212
try {

Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GFilterTable.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ private void addTableSelectionListener(GTable gTable) {
7676
}
7777

7878
private void buildThreadedTable() {
79-
@SuppressWarnings("unchecked")
8079
GThreadedTablePanel<ROW_OBJECT> tablePanel =
8180
createThreadedTablePanel((ThreadedTableModel<ROW_OBJECT, ?>) model);
8281
table = tablePanel.getTable();

Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableWidget.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,20 @@ public int getSelectedRowCount() {
168168
return table.getSelectedRowCount();
169169
}
170170

171+
/**
172+
* Sets the selection mode of this table.
173+
*
174+
* @param mode the mode
175+
* @see ListSelectionModel#setSelectionMode(int)
176+
*/
177+
public void setSelectionMode(int mode) {
178+
table.getSelectionModel().setSelectionMode(mode);
179+
}
180+
181+
public int getSelectionMode() {
182+
return table.getSelectionModel().getSelectionMode();
183+
}
184+
171185
public void addSelectionListener(ObjectSelectedListener<T> l) {
172186
gFilterTable.addSelectionListener(l);
173187
}

0 commit comments

Comments
 (0)