mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 16:47:43 +08:00
GP-5720 - Drop Down Modes - Added modes to drop-down text fields to control how matches are found
This commit is contained in:
+55
-8
@@ -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,9 +15,10 @@
|
||||
*/
|
||||
package help.screenshot;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.util.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -25,6 +26,8 @@ import org.junit.Test;
|
||||
|
||||
import docking.ComponentProvider;
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.util.image.Callout;
|
||||
import docking.util.image.CalloutInfo;
|
||||
import docking.widgets.DropDownSelectionTextField;
|
||||
import docking.widgets.button.BrowseButton;
|
||||
import docking.widgets.tree.GTree;
|
||||
@@ -33,13 +36,12 @@ import ghidra.app.plugin.core.compositeeditor.*;
|
||||
import ghidra.app.plugin.core.datamgr.editor.EnumEditorProvider;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeChooserDialog;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionDialog;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionEditor;
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
|
||||
public DataTypeEditorsScreenShots() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDialog() {
|
||||
|
||||
@@ -48,6 +50,18 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
captureDialog();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDialog_SearchMode() {
|
||||
|
||||
positionListingTop(0x40D3B8);
|
||||
performAction("Choose Data Type", "DataPlugin", false);
|
||||
captureDialog();
|
||||
|
||||
createSearchModeCallout();
|
||||
|
||||
cropExcessSpace();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDialog_Multiple_Match() throws Exception {
|
||||
|
||||
@@ -142,6 +156,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
ComponentProvider structureEditor = getProvider(StructureEditorProvider.class);
|
||||
|
||||
// get structure table and select a row
|
||||
@SuppressWarnings("rawtypes")
|
||||
CompositeEditorPanel editorPanel =
|
||||
(CompositeEditorPanel) getInstanceField("editorPanel", structureEditor);
|
||||
JTable table = editorPanel.getTable();
|
||||
@@ -178,6 +193,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
ComponentProvider structureEditor = getProvider(StructureEditorProvider.class);
|
||||
|
||||
// get structure table and select a row
|
||||
@SuppressWarnings("rawtypes")
|
||||
CompositeEditorPanel editorPanel =
|
||||
(CompositeEditorPanel) getInstanceField("editorPanel", structureEditor);
|
||||
JTable table = editorPanel.getTable();
|
||||
@@ -203,6 +219,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
ComponentProvider structureEditor = getProvider(StructureEditorProvider.class);
|
||||
|
||||
// get structure table and select a row
|
||||
@SuppressWarnings("rawtypes")
|
||||
CompositeEditorPanel editorPanel =
|
||||
(CompositeEditorPanel) getInstanceField("editorPanel", structureEditor);
|
||||
JTable table = editorPanel.getTable();
|
||||
@@ -262,6 +279,7 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
ComponentProvider structureEditor = getProvider(StructureEditorProvider.class);
|
||||
|
||||
// get structure table and select a row
|
||||
@SuppressWarnings("rawtypes")
|
||||
CompositeEditorPanel editorPanel =
|
||||
(CompositeEditorPanel) getInstanceField("editorPanel", structureEditor);
|
||||
JTable table = editorPanel.getTable();
|
||||
@@ -404,4 +422,33 @@ public class DataTypeEditorsScreenShots extends GhidraScreenShotGenerator {
|
||||
tool.execute(createDataCmd, program);
|
||||
waitForBusyTool(tool);
|
||||
}
|
||||
|
||||
private void cropExcessSpace() {
|
||||
|
||||
// keep the hover area and callout in the image (trial and error)
|
||||
Rectangle area = new Rectangle();
|
||||
area.x = 200;
|
||||
area.y = 10;
|
||||
area.width = 450;
|
||||
area.height = 250;
|
||||
crop(area);
|
||||
}
|
||||
|
||||
private void createSearchModeCallout() {
|
||||
|
||||
DataTypeSelectionDialog dialog = waitForDialogComponent(DataTypeSelectionDialog.class);
|
||||
DataTypeSelectionEditor editor = dialog.getEditor();
|
||||
DropDownSelectionTextField<DataType> textField = editor.getDropDownTextField();
|
||||
DropDownSelectionTextField<DataType>.SearchModeBounds searchModeBounds =
|
||||
textField.getSearchModeBounds();
|
||||
|
||||
Rectangle hoverBounds = searchModeBounds.getHoverAreaBounds();
|
||||
Window destinationComponent = SwingUtilities.windowForComponent(dialog.getComponent());
|
||||
CalloutInfo calloutInfo =
|
||||
new CalloutInfo(destinationComponent, textField, hoverBounds);
|
||||
calloutInfo.setMagnification(2.75D); // make it a bit bigger than default
|
||||
Callout callout = new Callout();
|
||||
image = callout.createCalloutOnImage(image, calloutInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+54
-87
@@ -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.
|
||||
@@ -35,7 +35,7 @@ import docking.action.DockingAction;
|
||||
import docking.menu.ActionState;
|
||||
import docking.menu.MultiStateDockingAction;
|
||||
import docking.util.image.Callout;
|
||||
import docking.util.image.CalloutComponentInfo;
|
||||
import docking.util.image.CalloutInfo;
|
||||
import docking.widgets.dialogs.MultiLineInputDialog;
|
||||
import edu.uci.ics.jung.graph.Graph;
|
||||
import edu.uci.ics.jung.visualization.VisualizationServer;
|
||||
@@ -61,14 +61,18 @@ import ghidra.util.exception.AssertException;
|
||||
|
||||
public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
|
||||
static {
|
||||
|
||||
// Note: this is usually done by AbstractScreenShotGenerator. The following user name
|
||||
// setting needs to happen before the application is initialized. Since we don't extend
|
||||
// AbstractScreenShotGenerator, we have to do it ourselves.
|
||||
System.setProperty("user.name", AbstractScreenShotGenerator.SCREENSHOT_USER_NAME);
|
||||
}
|
||||
|
||||
private MyScreen screen;
|
||||
private int width = 400;
|
||||
private int height = 400;
|
||||
|
||||
public FunctionGraphPluginScreenShots() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -85,7 +89,7 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
|
||||
screen.program = program;
|
||||
|
||||
setLayout();
|
||||
setNestedLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -447,7 +451,7 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
return dc.getHeader();
|
||||
}
|
||||
|
||||
private void createCallout(JComponent parentComponent, CalloutComponentInfo calloutInfo) {
|
||||
private void createCallout(JComponent parentComponent, CalloutInfo calloutInfo) {
|
||||
// create image of parent with extra space for callout feature
|
||||
Image parentImage = screen.captureComponent(parentComponent);
|
||||
|
||||
@@ -459,7 +463,7 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
|
||||
private void createGroupButtonCallout(FGVertex v) {
|
||||
|
||||
JButton component = getToolbarButton(v, "Group Vertices");
|
||||
JButton button = getToolbarButton(v, "Group Vertices");
|
||||
FGProvider provider = screen.getProvider(FGProvider.class);
|
||||
JComponent parent = provider.getComponent();
|
||||
|
||||
@@ -467,22 +471,23 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
FGView view = controller.getView();
|
||||
VisualizationViewer<FGVertex, FGEdge> viewer = view.getPrimaryGraphViewer();
|
||||
|
||||
Rectangle bounds = component.getBounds();
|
||||
Dimension size = bounds.getSize();
|
||||
Point location = bounds.getLocation();
|
||||
Rectangle buttonBounds = button.getBounds();
|
||||
Point location = buttonBounds.getLocation();
|
||||
|
||||
JComponent vertexComponent = v.getComponent();
|
||||
Point newLocation =
|
||||
SwingUtilities.convertPoint(component.getParent(), location, vertexComponent);
|
||||
Point vertexRelativeLocation =
|
||||
SwingUtilities.convertPoint(button.getParent(), location, vertexComponent);
|
||||
|
||||
Point relativePoint = GraphViewerUtils.translatePointFromVertexRelativeSpaceToViewSpace(
|
||||
viewer, v, newLocation);
|
||||
Point buttonViewPoint = GraphViewerUtils.translatePointFromVertexRelativeSpaceToViewSpace(
|
||||
viewer, v, vertexRelativeLocation);
|
||||
Rectangle buttonArea = new Rectangle(buttonViewPoint, buttonBounds.getSize());
|
||||
|
||||
Point screenLocation = new Point(relativePoint);
|
||||
SwingUtilities.convertPointToScreen(screenLocation, parent);
|
||||
|
||||
CalloutComponentInfo calloutInfo = new FGCalloutComponentInfo(parent, component,
|
||||
screenLocation, relativePoint, size, viewer, v);
|
||||
// Use 'parent' for both source and destination. This has the effect of not moving any
|
||||
// locations, since the source and destination of the moves will be the same. For this use
|
||||
// case, the locations should all be where they need to be before creating the callout info.
|
||||
// It is done this way because the graph's vertices are painted as needed and are not
|
||||
// connected to a real display hierarchy.
|
||||
CalloutInfo calloutInfo = new CalloutInfo(parent, parent, buttonArea);
|
||||
|
||||
createCallout(parent, calloutInfo);
|
||||
}
|
||||
@@ -780,28 +785,6 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
return reference.get();
|
||||
}
|
||||
|
||||
private void setNestedLayout() {
|
||||
|
||||
Object actionManager = getInstanceField("actionManager", graphProvider);
|
||||
@SuppressWarnings("unchecked")
|
||||
final MultiStateDockingAction<Class<? extends FGLayoutProvider>> action =
|
||||
(MultiStateDockingAction<Class<? extends FGLayoutProvider>>) getInstanceField(
|
||||
"layoutAction", actionManager);
|
||||
runSwing(() -> {
|
||||
List<ActionState<Class<? extends FGLayoutProvider>>> states =
|
||||
action.getAllActionStates();
|
||||
for (ActionState<Class<? extends FGLayoutProvider>> state : states) {
|
||||
Class<? extends FGLayoutProvider> layoutClass = state.getUserData();
|
||||
if (layoutClass.getSimpleName().equals("DecompilerNestedLayoutProvider")) {
|
||||
action.setCurrentActionState(state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Could not find layout!!");
|
||||
});
|
||||
}
|
||||
|
||||
private void createGroupButtonCallout_PlayArea(final FGVertex v, final String imageName) {
|
||||
|
||||
FGProvider provider = screen.getProvider(FGProvider.class);
|
||||
@@ -833,32 +816,33 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
dialog.setVisible(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void setLayout() {
|
||||
private void setNestedLayout() {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Object actionManager = getInstanceField("actionManager", graphProvider);
|
||||
final MultiStateDockingAction<?> action =
|
||||
(MultiStateDockingAction<?>) getInstanceField("layoutAction", actionManager);
|
||||
@SuppressWarnings("unchecked")
|
||||
final MultiStateDockingAction<Class<? extends FGLayoutProvider>> action =
|
||||
(MultiStateDockingAction<Class<? extends FGLayoutProvider>>) getInstanceField(
|
||||
"layoutAction", actionManager);
|
||||
runSwing(() -> {
|
||||
List<ActionState<Class<? extends FGLayoutProvider>>> states =
|
||||
action.getAllActionStates();
|
||||
|
||||
Object minCrossState = null;
|
||||
List<?> states = action.getAllActionStates();
|
||||
for (Object state : states) {
|
||||
if (((ActionState) state).getName().indexOf("Nested Code Layout") != -1) {
|
||||
minCrossState = state;
|
||||
break;
|
||||
ActionState<Class<? extends FGLayoutProvider>> nestedCodeState = null;
|
||||
for (ActionState<Class<? extends FGLayoutProvider>> state : states) {
|
||||
if (state.getName().indexOf("Nested Code Layout") != -1) {
|
||||
nestedCodeState = state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertNotNull("Could not find min cross layout!", minCrossState);
|
||||
assertNotNull("Could not find Nested Code Layout layout!", nestedCodeState);
|
||||
|
||||
//@formatter:off
|
||||
invokeInstanceMethod( "setCurrentActionState",
|
||||
action,
|
||||
new Class<?>[] { ActionState.class },
|
||||
new Object[] { minCrossState });
|
||||
//@formatter:on
|
||||
action.setCurrentActionState(nestedCodeState);
|
||||
|
||||
runSwing(() -> action.actionPerformed(new DefaultActionContext()));
|
||||
// action.actionPerformed(new DefaultActionContext())
|
||||
});
|
||||
|
||||
// wait for the threaded graph layout code
|
||||
FGController controller = getFunctionGraphController();
|
||||
@@ -869,6 +853,13 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
Msg.debug(this, "relayout time: " + ((end - start) / 1000.0) + "s");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installTestGraphLayout(FGProvider provider) {
|
||||
// Do nothing. The normal tests will install a test layout in this method. We don't need
|
||||
// that behavior.
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
@@ -898,28 +889,4 @@ public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest {
|
||||
return helpTopicDir;
|
||||
}
|
||||
}
|
||||
|
||||
private class FGCalloutComponentInfo extends CalloutComponentInfo {
|
||||
|
||||
private VisualizationViewer<FGVertex, FGEdge> viewer;
|
||||
private FGVertex vertex;
|
||||
|
||||
FGCalloutComponentInfo(Component destinationComponent, Component component,
|
||||
Point locationOnScreen, Point relativeLocation, Dimension size,
|
||||
VisualizationViewer<FGVertex, FGEdge> viewer, FGVertex vertex) {
|
||||
|
||||
super(destinationComponent, component, locationOnScreen, relativeLocation, size);
|
||||
this.viewer = viewer;
|
||||
this.vertex = vertex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point convertPointToParent(Point location) {
|
||||
// TODO: this won't work for now if the graph is scaled. This is because there is
|
||||
// point information that is calculated by the client of this class that does
|
||||
// not take into account the scaling of the graph. This is a known issue--
|
||||
// don't use this class when the graph is scaled.
|
||||
return location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,11 +24,10 @@ import javax.swing.table.JTableHeader;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import docking.DockableComponent;
|
||||
import docking.menu.MultiStateDockingAction;
|
||||
import docking.util.AnimationUtils;
|
||||
import docking.util.image.Callout;
|
||||
import docking.util.image.CalloutComponentInfo;
|
||||
import docking.util.image.CalloutInfo;
|
||||
import docking.widgets.EmptyBorderButton;
|
||||
import docking.widgets.filter.*;
|
||||
import docking.widgets.table.columnfilter.ColumnBasedTableFilter;
|
||||
@@ -88,11 +87,15 @@ public class TreesScreenShots extends GhidraScreenShotGenerator {
|
||||
component we provide. But, we need to be able to translate that component's
|
||||
location to a value that is relative to the image (we created the image above by
|
||||
capturing the provider using it's DockableComponent).
|
||||
|
||||
Important!: since we only captured the provider and not the window, we need to pass in
|
||||
the dockable component, which is the same bounds as the provider. If we pass the parent
|
||||
window, then we will be off in the y direction in the amount of all the items above the
|
||||
dockable component, such as the window bar, the menu bar, etc.
|
||||
*/
|
||||
|
||||
DockableComponent dc = getDockableComponent(provider);
|
||||
|
||||
CalloutComponentInfo calloutInfo = new CalloutComponentInfo(dc, label);
|
||||
Component dc = getDockableComponent(provider);
|
||||
CalloutInfo calloutInfo = new CalloutInfo(dc, label);
|
||||
calloutInfo.setMagnification(2.75D); // make it a bit bigger than default
|
||||
Callout callout = new Callout();
|
||||
image = callout.createCalloutOnImage(image, calloutInfo);
|
||||
@@ -104,8 +107,8 @@ public class TreesScreenShots extends GhidraScreenShotGenerator {
|
||||
Rectangle area = new Rectangle();
|
||||
int height = 275;
|
||||
area.x = 0;
|
||||
area.y = 80;
|
||||
area.width = 560;
|
||||
area.y = 60;
|
||||
area.width = 580;
|
||||
area.height = height - area.y;
|
||||
crop(area);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user