diff --git a/Ghidra/Features/Base/build.gradle b/Ghidra/Features/Base/build.gradle index 0ea023e9e2..a6076a0cd7 100644 --- a/Ghidra/Features/Base/build.gradle +++ b/Ghidra/Features/Base/build.gradle @@ -38,13 +38,7 @@ configurations { } dependencies { - api project(':Utility') - api project(':Generic') - api project(':Docking') - api project(':Graph') api project(':SoftwareModeling') - api project(':DB') - api project(':Help') api 'org.apache.felix:org.apache.felix.framework:7.0.3' api 'com.github.rotty3000:phidias:0.3.7' diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java index 79f040cb94..110424086a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/database/ProgramBuilder.java @@ -22,6 +22,7 @@ import java.util.*; import generic.jar.ResourceFile; import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.cmd.data.CreateDataCmd; import ghidra.app.cmd.disassemble.ArmDisassembleCommand; import ghidra.app.cmd.disassemble.DisassembleCommand; @@ -216,7 +217,7 @@ public class ProgramBuilder { private void flushEvents() { program.flushEvents(); if (!SystemUtilities.isInHeadlessMode()) { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/ProjectTestUtils.java b/Ghidra/Features/Base/src/main/java/ghidra/test/ProjectTestUtils.java index 6c359364e0..f27d654fff 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/ProjectTestUtils.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/ProjectTestUtils.java @@ -20,7 +20,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.util.*; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.store.LockException; @@ -131,7 +131,7 @@ public class ProjectTestUtils { Msg.warn(ProjectTestUtils.class, "deleteLockFile(): " + "unable to delete file " + lockFile.getAbsolutePath() + "- trying again."); for (int i = 0; i < 6; i++) { - AbstractGenericTest.waitForPostedSwingRunnables(); + AbstractGuiTest.waitForPostedSwingRunnables(); try { Thread.sleep(1000); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/TestEnv.java b/Ghidra/Features/Base/src/main/java/ghidra/test/TestEnv.java index c37943595a..f9411e6141 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/TestEnv.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/TestEnv.java @@ -189,12 +189,12 @@ public class TestEnv { closeAllProgramsFor(tool); // don't want to prompt for saving - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { tool.setConfigChanged(false); }); - AbstractGenericTest.runSwing(() -> tool.close(), false); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.runSwing(() -> tool.close(), false); + AbstractGuiTest.waitForSwing(); tool = null; } @@ -231,7 +231,7 @@ public class TestEnv { } extraTools.remove(toolToClose); - AbstractGenericTest.executeOnSwingWithoutBlocking(() -> { + AbstractGuiTest.executeOnSwingWithoutBlocking(() -> { if (ignoreChanges) { toolToClose.setConfigChanged(false); } @@ -244,13 +244,13 @@ public class TestEnv { return; } - AbstractGenericTest.runSwing(() -> frontEndTool.close()); + AbstractGuiTest.runSwing(() -> frontEndTool.close()); frontEndTool = null; removeFrontEndFromSystem(); } private void dipsoseTestTools() { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { disposeSingleTool(tool); Iterator it = extraTools.iterator(); @@ -279,7 +279,7 @@ public class TestEnv { } public void saveRestoreToolState() { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { Element element = lazyTool().saveDataStateToXml(true); lazyTool().restoreDataStateFromXml(element); }); @@ -413,7 +413,7 @@ public class TestEnv { ToolChest toolChest = project.getLocalToolChest(); ToolTemplate template = getToolTemplate(AbstractGenericTest.DEFAULT_TEST_TOOL_NAME); template.setName(AbstractGenericTest.DEFAULT_TOOL_NAME); - AbstractGenericTest.runSwing(() -> toolChest.replaceToolTemplate(template)); + AbstractGuiTest.runSwing(() -> toolChest.replaceToolTemplate(template)); } private void initializeSimpleTool() { @@ -422,7 +422,7 @@ public class TestEnv { throw new AssertException("Tool already exists--you are doing something wrong!"); } - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { Project project = gp.getProject(); tool = new TestTool(project); @@ -452,7 +452,7 @@ public class TestEnv { return frontEndTool; } - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { frontEndTool = new TestFrontEndTool(gp.getProjectManager()); frontEndTool.setActiveProject(getProject()); @@ -517,7 +517,7 @@ public class TestEnv { protected PluginTool launchDefaultToolByName(String toolName) { - return AbstractGenericTest.runSwing(() -> { + return AbstractGuiTest.runSwing(() -> { ToolTemplate toolTemplate = getToolTemplate(toolName); if (toolTemplate == null) { @@ -540,7 +540,7 @@ public class TestEnv { private static ToolTemplate getToolTemplate(String toolName) { - return AbstractGenericTest.runSwing(() -> { + return AbstractGuiTest.runSwing(() -> { ToolTemplate toolTemplate = ToolUtils.readToolTemplate("defaultTools/" + toolName + ToolUtils.TOOL_EXTENSION); if (toolTemplate == null) { @@ -620,7 +620,7 @@ public class TestEnv { public PluginTool restartTool() { closeTool(); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); tool = null; initializeSimpleTool(); @@ -634,7 +634,7 @@ public class TestEnv { */ public PluginTool launchAnotherDefaultTool() { PluginTool newTool = createDefaultTool(); - AbstractGenericTest.runSwing(() -> newTool.setToolName(newTool.getToolName() + toolID++)); + AbstractGuiTest.runSwing(() -> newTool.setToolName(newTool.getToolName() + toolID++)); extraTools.add(newTool); return newTool; @@ -833,7 +833,7 @@ public class TestEnv { throw new AssertException("Tool already exists--you are doing something wrong!"); } - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { tool = launchDefaultTool(); ProgramManager pm = tool.getService(ProgramManager.class); pm.openProgram(program.getDomainFile()); @@ -844,7 +844,7 @@ public class TestEnv { "Unable to launch the default tool: " + ToolServices.DEFAULT_TOOLNAME); } - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); removeAllConsumersExceptTool(program, tool); @@ -879,7 +879,7 @@ public class TestEnv { public PluginTool launchTool(String toolName, DomainFile domainFile) { AtomicReference ref = new AtomicReference<>(); - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { PluginTool newTool = doLaunchTool(toolName); ref.set(newTool); if (newTool != null) { @@ -909,7 +909,7 @@ public class TestEnv { public PluginTool launchToolWithURL(String toolName, URL ghidraUrl) { AtomicReference ref = new AtomicReference<>(); - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { PluginTool newTool = doLaunchTool(toolName); ref.set(newTool); if (newTool != null) { @@ -956,7 +956,7 @@ public class TestEnv { protected void setAutoSaveEnabled(final FrontEndTool frontEndToolInstance, final boolean enabled) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { Options options = frontEndToolInstance.getOptions(ToolConstants.TOOL_OPTIONS); options.setBoolean(FrontEndTool.AUTOMATICALLY_SAVE_TOOLS, enabled); }); @@ -1085,7 +1085,7 @@ public class TestEnv { Project project = gp.getProject(); String projectName = project.getName(); try { - AbstractGenericTest.runSwing(() -> gp.close()); + AbstractGuiTest.runSwing(() -> gp.close()); } catch (Throwable t) { Msg.error(TestEnv.class, "Problem disposing the test project", t); @@ -1146,7 +1146,7 @@ public class TestEnv { private void printOpenModalDialogs() { boolean hasModal = false; - Set windows = AbstractGenericTest.getAllWindows(); + Set windows = AbstractGuiTest.getAllWindows(); for (Window window : windows) { if (window instanceof Dialog) { if (((Dialog) window).isModal() && window.isShowing()) { @@ -1168,7 +1168,7 @@ public class TestEnv { } private void disposeTestTools() { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { try { dipsoseTestTools(); } @@ -1183,7 +1183,7 @@ public class TestEnv { // the deprecation is OK--we are a framework method and we know we can use it @SuppressWarnings("deprecation") private void privateWaitForSwingRunnables() { - AbstractGenericTest.privateWaitForPostedSwingRunnables_SwingSafe(); + AbstractGuiTest.privateWaitForPostedSwingRunnables_SwingSafe(); } private void disposeAllSwingUpdateManagers() { @@ -1207,7 +1207,7 @@ public class TestEnv { Msg.out(StringUtils.join(list, ",\n")); */ - AbstractGenericTest.runSwing(() -> s.clear()); + AbstractGuiTest.runSwing(() -> s.clear()); } private void markAllProgramsAsUnchanged() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/TestProgramManager.java b/Ghidra/Features/Base/src/main/java/ghidra/test/TestProgramManager.java index 85ad72e1c1..96b8ede7ec 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/TestProgramManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/TestProgramManager.java @@ -21,8 +21,7 @@ import java.util.*; import db.DBConstants; import db.DBHandle; import db.buffers.BufferFile; -import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.*; import ghidra.app.util.xml.*; import ghidra.framework.data.DomainObjectAdapterDB; import ghidra.framework.model.*; @@ -243,7 +242,7 @@ public class TestProgramManager { while (true) { try { DomainFile df = folder.createFile(name, gzf, TaskMonitor.DUMMY); - AbstractGenericTest.waitForPostedSwingRunnables(); + AbstractGuiTest.waitForPostedSwingRunnables(); DomainObject dobj = df.getDomainObject(this, true, false, null); try { if (dobj.isChanged()) { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeTestUtils.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeTestUtils.java index 8f67e5c6f1..3805dd9cd7 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeTestUtils.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/datamgr/DataTypeTestUtils.java @@ -25,6 +25,7 @@ import docking.action.DockingActionIf; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.plugin.core.datamgr.archive.*; import ghidra.app.plugin.core.datamgr.tree.ArchiveNode; import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree; @@ -125,7 +126,7 @@ public class DataTypeTestUtils { // who cares? } } - AbstractGenericTest.waitForPostedSwingRunnables(); + AbstractGuiTest.waitForPostedSwingRunnables(); } public static ArchiveNode openArchive(String archiveName, boolean checkout, @@ -239,14 +240,14 @@ public class DataTypeTestUtils { public static void performAction(DockingActionIf action, Program program, GTree tree, boolean wait) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { ActionContext context = new DataTypesActionContext(null, program, (DataTypeArchiveGTree) tree, null, true); action.actionPerformed(context); }, wait); if (!SwingUtilities.isEventDispatchThread()) { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); } } @@ -255,14 +256,14 @@ public class DataTypeTestUtils { } public static void performAction(DockingActionIf action, GTree tree, boolean wait) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { ActionContext context = new DataTypesActionContext(null, null, (DataTypeArchiveGTree) tree, null, true); action.actionPerformed(context); }, wait); if (!SwingUtilities.isEventDispatchThread()) { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/PairedTransactionTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/PairedTransactionTest.java index 06aa17f6ee..befd5f83a9 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/PairedTransactionTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/PairedTransactionTest.java @@ -22,12 +22,12 @@ import java.util.*; import org.junit.*; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.model.*; import ghidra.framework.options.Options; import ghidra.framework.store.LockException; -public class PairedTransactionTest extends AbstractGenericTest { +public class PairedTransactionTest extends AbstractGuiTest { DummyDomainObject obj1; DummyDomainObject obj2; diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/ConsoleTextPaneTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/ConsoleTextPaneTest.java index 69e4c55f19..f69f32fc5c 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/ConsoleTextPaneTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/main/ConsoleTextPaneTest.java @@ -25,7 +25,7 @@ import javax.swing.text.Document; import org.junit.Test; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.plugintool.DummyPluginTool; public class ConsoleTextPaneTest { @@ -110,28 +110,28 @@ public class ConsoleTextPaneTest { private void assertCaretAtTop(ConsoleTextPane text) { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); int expectedPosition = 0; assertCaretPosition(text, expectedPosition); } private void assertCaretAtBottom(ConsoleTextPane text) { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); int expectedPosition = text.getDocument().getLength(); assertCaretPosition(text, expectedPosition); } private void assertCaretPosition(ConsoleTextPane text, int expectedPosition) { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); Document doc = text.getDocument(); int actualPosition = swing(() -> text.getCaretPosition()); assertEquals(expectedPosition, actualPosition); } private void printEnoughLinesToOverflowTheMaxCharCount(ConsoleTextPane text) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { int charsWritten = 0; for (int i = 0; charsWritten < text.getMaximumCharacterLimit(); i++) { @@ -145,10 +145,10 @@ public class ConsoleTextPaneTest { } private void swing(Runnable r) { - AbstractGenericTest.runSwing(r); + AbstractGuiTest.runSwing(r); } private T swing(Supplier s) { - return AbstractGenericTest.runSwing(s); + return AbstractGuiTest.runSwing(s); } } diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/SampleLocationGenerator.java b/Ghidra/Features/Base/src/test/java/ghidra/app/SampleLocationGenerator.java index 7bb77fb219..de54425efa 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/SampleLocationGenerator.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/SampleLocationGenerator.java @@ -18,7 +18,7 @@ package ghidra.app; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; @@ -56,7 +56,7 @@ public class SampleLocationGenerator implements GhidraLocationGenerator { * @param cb */ public void toggleOpenComposites(final CodeBrowserPlugin cb) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { Data data = program.getListing().getDataAt(addr(0x100d0f3)); if (data.getDataType() instanceof Composite) { cb.toggleOpen(data); diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/assembler/AssemblerPluginTestHelper.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/assembler/AssemblerPluginTestHelper.java index c7ae8b65e3..5392fdf3a9 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/assembler/AssemblerPluginTestHelper.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/assembler/AssemblerPluginTestHelper.java @@ -23,7 +23,7 @@ import javax.swing.JTextField; import docking.test.AbstractDockingTest; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.plugin.core.assembler.AssemblyDualTextField.AssemblyCompletion; import ghidra.app.plugin.core.assembler.AssemblyDualTextField.AssemblyInstruction; import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; @@ -78,14 +78,14 @@ public class AssemblerPluginTestHelper { } public List inputAndGetCompletions(String text) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { instructionInput.setText(text); JTextField field = instructionInput.getOperandsField(); instructionInput.auto.fakeFocusGained(field); instructionInput.auto.startCompletion(field); instructionInput.auto.updateNow(); }); - return AbstractGenericTest.waitForValue(() -> AbstractGenericTest.runSwing(() -> { + return AbstractGuiTest.waitForValue(() -> AbstractGuiTest.runSwing(() -> { List suggestions = instructionInput.auto.getSuggestions(); if (suggestions.isEmpty()) { return null; @@ -98,7 +98,7 @@ public class AssemblerPluginTestHelper { ListingPanel listingPanel = provider.getListingPanel(); ProgramLocation location = new ProgramLocation(program, address); AbstractGTest.waitForCondition(() -> { - AbstractGenericTest.runSwing(() -> listingPanel.goTo(location)); + AbstractGuiTest.runSwing(() -> listingPanel.goTo(location)); ProgramLocation confirm = listingPanel.getCursorLocation(); if (confirm == null) { return false; @@ -126,7 +126,7 @@ public class AssemblerPluginTestHelper { assertTrue(first instanceof AssemblyInstruction); AssemblyInstruction ai = (AssemblyInstruction) first; - AbstractGenericTest.runSwing(() -> patchInstructionAction.accept(ai)); + AbstractGuiTest.runSwing(() -> patchInstructionAction.accept(ai)); AbstractGhidraHeadedIntegrationTest.waitForProgram(program); return AbstractGTest.waitForValue(() -> listing.getInstructionAt(address)); @@ -140,7 +140,7 @@ public class AssemblerPluginTestHelper { assertEquals(expText, dataInput.getText()); assertEquals(address, patchDataAction.getAddress()); - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { dataInput.setText(newText); patchDataAction.accept(); }); diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/FunctionEditorModelTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/FunctionEditorModelTest.java index 7698b02a8c..bddd3aea40 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/FunctionEditorModelTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/FunctionEditorModelTest.java @@ -21,7 +21,7 @@ import java.util.List; import org.junit.*; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.cparser.C.ParseException; import ghidra.program.database.ProgramBuilder; @@ -34,7 +34,7 @@ import ghidra.program.model.listing.*; import ghidra.program.model.pcode.Varnode; import ghidra.util.exception.InvalidInputException; -public class FunctionEditorModelTest extends AbstractGenericTest { +public class FunctionEditorModelTest extends AbstractGuiTest { private FunctionEditorModel model; private volatile boolean dataChangeCalled; diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/StorageEditorModelTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/StorageEditorModelTest.java index ee4d0b1ac5..7434b83809 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/StorageEditorModelTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/function/editor/StorageEditorModelTest.java @@ -22,7 +22,7 @@ import java.util.List; import org.junit.Before; import org.junit.Test; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramDB; import ghidra.program.model.address.Address; @@ -32,7 +32,7 @@ import ghidra.program.model.listing.Function; import ghidra.program.model.listing.VariableStorage; import ghidra.util.exception.InvalidInputException; -public class StorageEditorModelTest extends AbstractGenericTest { +public class StorageEditorModelTest extends AbstractGuiTest { protected static final int REQUIRE_SIZE = 8; protected StorageAddressModel model; diff --git a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java index 3c03ac9af8..a5c2ce56ac 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/framework/options/OptionsTest.java @@ -30,13 +30,13 @@ import javax.swing.KeyStroke; import org.jdom.Element; import org.junit.*; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.util.HelpLocation; import ghidra.util.bean.opteditor.OptionsVetoException; import ghidra.util.exception.InvalidInputException; -public class OptionsTest extends AbstractGenericTest { +public class OptionsTest extends AbstractGuiTest { public enum FRUIT { Apple, Orange, Pear diff --git a/Ghidra/Features/Base/src/test/java/ghidra/program/database/AbstractMTFModel.java b/Ghidra/Features/Base/src/test/java/ghidra/program/database/AbstractMTFModel.java index 52d07c1b86..3539c55bc9 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/program/database/AbstractMTFModel.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/program/database/AbstractMTFModel.java @@ -20,6 +20,7 @@ import java.io.IOException; import db.*; import db.buffers.BufferFile; import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.plugin.core.analysis.AutoAnalysisManager; import ghidra.framework.data.GhidraFolder; import ghidra.framework.model.DomainFile; @@ -158,7 +159,7 @@ public abstract class AbstractMTFModel { } if (resultProgram != null) { resultProgram.flushEvents(); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); resultProgram.release(this); resultProgram = null; } diff --git a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java index cb4ea223ea..c476f8f424 100644 --- a/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java +++ b/Ghidra/Features/FunctionGraph/src/test.slow/java/ghidra/app/plugin/core/functiongraph/AbstractFunctionGraphTest.java @@ -44,7 +44,6 @@ import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.visualization.VisualizationModel; import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.picking.PickedState; -import generic.test.AbstractGenericTest; import generic.test.TestUtils; import ghidra.app.cmd.label.AddLabelCmd; import ghidra.app.cmd.label.SetLabelPrimaryCmd; @@ -2312,11 +2311,11 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte } protected void swing(Runnable r) { - AbstractGenericTest.runSwing(r); + runSwing(r); } protected T swing(Supplier s) { - return AbstractGenericTest.runSwing(s); + return runSwing(s); } static class DummyTransferable implements Transferable { diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/TreeTestUtils.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/TreeTestUtils.java index a3fba31b9d..c0299892dc 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/TreeTestUtils.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/TreeTestUtils.java @@ -22,7 +22,7 @@ import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import docking.widgets.tree.GTreeNode; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; public class TreeTestUtils { public static TreePath findTreePathToText(JTree tree, String text) { @@ -57,7 +57,7 @@ public class TreeTestUtils { */ public static void selectTreeNodeByText(final JTree tree, final String text) { - AbstractGenericTest.runSwing(new Runnable() { + AbstractGuiTest.runSwing(new Runnable() { @Override public void run() { TreePath path = findTreePathToText(tree, text); @@ -68,9 +68,9 @@ public class TreeTestUtils { } }); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); - AbstractGenericTest.runSwing(new Runnable() { + AbstractGuiTest.runSwing(new Runnable() { @Override public void run() { TreePath path = findTreePathToText(tree, text); diff --git a/Ghidra/Framework/Docking/build.gradle b/Ghidra/Framework/Docking/build.gradle index c041f1c13c..279b119dcd 100644 --- a/Ghidra/Framework/Docking/build.gradle +++ b/Ghidra/Framework/Docking/build.gradle @@ -24,7 +24,6 @@ apply plugin: 'eclipse' eclipse.project.name = 'Framework Docking' dependencies { - api project(':Generic') api project(':Help') // include code from src/test in Generic diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManagerTestUtils.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManagerTestUtils.java index da52413b75..502d170671 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManagerTestUtils.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManagerTestUtils.java @@ -21,7 +21,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; /** * This class mainly serves as a conduit through which testing code can access some of the @@ -44,7 +44,7 @@ public class DockingWindowManagerTestUtils { public static Window moveProviderToWindow(final DockingWindowManager dwm, final ComponentProvider provider) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { if (!dwm.containsProvider(provider)) { return; } @@ -65,7 +65,7 @@ public class DockingWindowManagerTestUtils { public static void moveProvider(final DockingWindowManager dwm, final ComponentProvider movee, final ComponentProvider relativeTo, final WindowPosition position) { - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { ComponentPlaceholder moveePlaceholder = dwm.getPlaceholder(movee); ComponentPlaceholder relativeToPlaceholder = dwm.getPlaceholder(relativeTo); dwm.movePlaceholder(moveePlaceholder, relativeToPlaceholder, position); @@ -76,7 +76,7 @@ public class DockingWindowManagerTestUtils { final ComponentProvider provider) { final AtomicReference ref = new AtomicReference<>(); - AbstractGenericTest.runSwing(() -> ref.set(dwm.getDockableComponent(provider))); + AbstractGuiTest.runSwing(() -> ref.set(dwm.getDockableComponent(provider))); return ref.get(); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java index 16de685cae..cff1c097bd 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java @@ -23,6 +23,7 @@ import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.net.URL; import java.util.*; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -48,8 +49,9 @@ import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.table.threaded.ThreadedTableModel; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import generic.test.ConcurrentTestExceptionHandler; +import generic.theme.GIcon; import generic.util.image.ImageUtils; import ghidra.GhidraTestApplicationLayout; import ghidra.framework.ApplicationConfiguration; @@ -58,11 +60,12 @@ import ghidra.util.exception.AssertException; import ghidra.util.task.SwingUpdateManager; import ghidra.util.worker.Worker; import junit.framework.AssertionFailedError; +import resources.icons.UrlImageIcon; import sun.awt.AppContext; import util.CollectionUtils; import utility.application.ApplicationLayout; -public abstract class AbstractDockingTest extends AbstractGenericTest { +public abstract class AbstractDockingTest extends AbstractGuiTest { static { ConcurrentTestExceptionHandler.registerHandler(); @@ -2265,4 +2268,39 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { ImageUtils.writeFile(image, imageFile); Msg.info(AbstractDockingTest.class, "Wrote image to " + imageFile.getCanonicalPath()); } + + /** + * Asserts that the two icons are or refer to the same icon (handles GIcon) + * @param expected the expected icon + * @param actual the actual icon + */ + public void assertIconsEqual(Icon expected, Icon actual) { + if (expected.equals(actual)) { + return; + } + URL url1 = getURL(expected); + URL url2 = getURL(actual); + + if (url1 != null && url1.equals(url2)) { + return; + } + fail("Expected icon [" + expected.getClass().getSimpleName() + "]" + expected.toString() + + ", but got: [" + actual.getClass().getSimpleName() + "]" + actual.toString()); + } + + /** + * Gets the URL for the given icon + * @param icon the icon to get a URL for + * @return the URL for the given icon + */ + public URL getURL(Icon icon) { + if (icon instanceof UrlImageIcon urlIcon) { + return urlIcon.getUrl(); + } + if (icon instanceof GIcon gIcon) { + return gIcon.getUrl(); + } + return null; + } + } diff --git a/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/filter/FilterTextFieldTest.java b/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/filter/FilterTextFieldTest.java index f03e18c280..7fe4044ac4 100644 --- a/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/filter/FilterTextFieldTest.java +++ b/Ghidra/Framework/Docking/src/test.slow/java/docking/widgets/filter/FilterTextFieldTest.java @@ -17,7 +17,7 @@ package docking.widgets.filter; import static docking.test.AbstractDockingTest.*; import static generic.test.AbstractGTest.*; -import static generic.test.AbstractGenericTest.*; +import static generic.test.AbstractGuiTest.*; import static org.junit.Assert.*; import java.awt.BorderLayout; @@ -32,7 +32,7 @@ import org.junit.Before; import org.junit.Test; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import utility.function.Callback; public class FilterTextFieldTest { @@ -276,7 +276,7 @@ public class FilterTextFieldTest { private void clickClearFilterIcon() { JLabel clearLabel = filter.getClearLabel(); - AbstractGenericTest.clickMouse(clearLabel, MouseEvent.BUTTON1, 0, 0, 1, 0); + AbstractGuiTest.clickMouse(clearLabel, MouseEvent.BUTTON1, 0, 0, 1, 0); } private void setFilter(String text) { diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java index 21a9123f91..3555c5d59e 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/fieldpanel/ColorRangeMapTest.java @@ -18,13 +18,10 @@ package docking.widgets.fieldpanel; import org.junit.Test; import docking.widgets.fieldpanel.internal.ColorRangeMap; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import generic.theme.GThemeDefaults.Colors.Palette; -public class ColorRangeMapTest extends AbstractGenericTest { - public ColorRangeMapTest() { - super(); - } +public class ColorRangeMapTest extends AbstractGuiTest { @Test public void testPaint1() { diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/tree/support/TreeIteratorTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/tree/support/TreeIteratorTest.java index ceb28375ad..6062425363 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/tree/support/TreeIteratorTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/tree/support/TreeIteratorTest.java @@ -23,7 +23,7 @@ import org.junit.Before; import org.junit.Test; import docking.widgets.tree.*; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; /** * Class to test the {@link DepthFirstIterator} and {@link BreadthFirstIterator} classes for @@ -48,7 +48,7 @@ public class TreeIteratorTest { node0_1 = new GTestNode("Node0_1"); node1_0 = new GTestNode("Node1_0"); - AbstractGenericTest.runSwing(() -> { + AbstractGuiTest.runSwing(() -> { root.addNode(node0); root.addNode(node1); root.addNode(node2); diff --git a/Ghidra/Framework/FileSystem/build.gradle b/Ghidra/Framework/FileSystem/build.gradle index 9541f2b5a6..940b215475 100644 --- a/Ghidra/Framework/FileSystem/build.gradle +++ b/Ghidra/Framework/FileSystem/build.gradle @@ -23,7 +23,6 @@ apply plugin: 'eclipse' eclipse.project.name = 'Framework FileSystem' dependencies { - api project(':Generic') api project(':DB') api project(':Docking') } diff --git a/Ghidra/Framework/Generic/build.gradle b/Ghidra/Framework/Generic/build.gradle index f7d479cf69..c470719743 100644 --- a/Ghidra/Framework/Generic/build.gradle +++ b/Ghidra/Framework/Generic/build.gradle @@ -38,13 +38,9 @@ dependencies { api 'org.bouncycastle:bcpkix-jdk15on:1.69' // requires bcutil and bcprov api 'org.bouncycastle:bcprov-jdk15on:1.69' api 'org.bouncycastle:bcutil-jdk15on:1.69' - api 'com.formdev:flatlaf:2.6' compileOnly "junit:junit:4.12" } -ext.addExports([ - 'java.desktop/sun.awt=ALL-UNNAMED' -]) diff --git a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java index d2d318f7e4..edb1480f8f 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java @@ -15,10 +15,7 @@ */ package generic.test; -import static org.junit.Assert.*; - import java.awt.*; -import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.*; import java.lang.reflect.*; @@ -26,18 +23,10 @@ import java.net.*; import java.nio.file.*; import java.util.*; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; import java.util.regex.Pattern; -import javax.swing.*; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableCellRenderer; -import javax.swing.text.JTextComponent; -import javax.swing.tree.*; +import javax.swing.SwingUtilities; -import org.junit.Assert; import org.junit.Rule; import org.junit.rules.*; import org.junit.runner.Description; @@ -45,25 +34,21 @@ import org.junit.runner.Description; import generic.jar.ResourceFile; import generic.test.rule.Repeated; import generic.test.rule.RepeatedTestRule; -import generic.theme.GIcon; -import generic.theme.Gui; import generic.util.WindowUtilities; import ghidra.GhidraTestApplicationLayout; import ghidra.framework.Application; import ghidra.framework.ApplicationConfiguration; -import ghidra.util.*; -import ghidra.util.datastruct.WeakSet; +import ghidra.util.Msg; +import ghidra.util.SystemUtilities; import ghidra.util.exception.AssertException; -import ghidra.util.task.AbstractSwingUpdateManager; -import ghidra.util.task.SwingUpdateManager; -import junit.framework.AssertionFailedError; -import resources.icons.UrlImageIcon; -import sun.awt.AppContext; import utilities.util.FileUtilities; import utilities.util.reflection.ReflectionUtilities; import utility.application.ApplicationLayout; -import utility.function.ExceptionalCallback; +/** + * Base class for tests that provide some helper methods that are useful for tests that don't + * require swing/gui support. + */ public abstract class AbstractGenericTest extends AbstractGTest { /** Property that defines the test report output directory */ @@ -262,40 +247,6 @@ public abstract class AbstractGenericTest extends AbstractGTest { return WindowUtilities.windowForComponent(c); } - /** - * Gets all windows in the system (including Frames). - * - * @return all windows - */ - public static Set getAllWindows() { - Set set = new HashSet<>(); - Frame sharedOwnerFrame = (Frame) AppContext.getAppContext() - .get(new StringBuffer("SwingUtilities.sharedOwnerFrame")); - if (sharedOwnerFrame != null) { - set.addAll(getAllWindows(sharedOwnerFrame)); - } - - for (Frame frame : Frame.getFrames()) { - set.addAll(getAllWindows(frame)); - } - - Window[] windows = Window.getWindows(); - for (Window window : windows) { - set.add(window); - } - - return set; - } - - private static List getAllWindows(Window parent) { - List list = new ArrayList<>(); - list.add(parent); - for (Window w : parent.getOwnedWindows()) { - list.add(w); - } - return list; - } - public File getLocalResourceFile(String relativePath) { URL resource = getClass().getResource(relativePath); try { @@ -421,127 +372,6 @@ public abstract class AbstractGenericTest extends AbstractGTest { } } - public static void printMemory() { - yieldToSwing(); - System.gc(); - yieldToSwing(); - System.gc(); - yieldToSwing(); - System.gc(); - - Runtime runTime = Runtime.getRuntime(); - System.out.println("----------------------"); - System.out.printf("Max: %,10dK\n", runTime.maxMemory() / 1000); - System.out.printf("Total: %,10dK\n", runTime.totalMemory() / 1000); - System.out.printf("Free: %,10dK\n", runTime.freeMemory() / 1000); - System.out.printf("Used: %,10dK\n", - ((runTime.totalMemory() - runTime.freeMemory()) / 1000)); - } - - /** - * Waits for all system tasks to complete. These tasks are tracked by the - * SystemUtilities during testing only. - * - * @throws AssertionFailedError if the timeout period expires while waiting - * for tasks - */ - public static void waitForTasks() { - doWaitForTasks(PRIVATE_LONG_WAIT_TIMEOUT); - } - - private static void doWaitForTasks(long timeout) { - waitForSwing(); - - long time = 0; - while (TaskUtilities.isExecutingTasks()) { - time += sleep(DEFAULT_WAIT_DELAY); - if (time >= timeout) { - Msg.error(AbstractGenericTest.class, createStackTraceForAllThreads()); - throw new AssertionFailedError("Time expired waiting for tasks to complete."); - } - } - - // let any pending Swing work finish - waitForSwing(); - } - - // TODO deprecate this; at time of writing there are 1174 references; wait until it is - // a more reasonable number - // - // Update: 744 references at 12/1/19 - // Update: 559 references at 12/4/20 - public static void waitForPostedSwingRunnables() { - waitForSwing(); - } - - public static T findComponent(Container parent, Class desiredClass) { - return findComponent(parent, desiredClass, false); - } - - public static T findComponent(Container parent, Class desiredClass, - boolean checkOwnedWindows) { - Component[] comps = parent.getComponents(); - for (Component element : comps) { - if (element == null) { - continue;// this started happening in 1.6, not sure why - } - if (desiredClass.isAssignableFrom(element.getClass())) { - return desiredClass.cast(element); - } - else if (element instanceof Container) { - T c = findComponent((Container) element, desiredClass, checkOwnedWindows); - if (c != null) { - return desiredClass.cast(c); - } - } - } - if (checkOwnedWindows && (parent instanceof Window)) { - Window[] windows = ((Window) parent).getOwnedWindows(); - for (int i = windows.length - 1; i >= 0; i--) { - Component c = findComponent(windows[i], desiredClass, checkOwnedWindows); - if (c != null) { - return desiredClass.cast(c); - } - } - } - return null; - } - - public static List findComponents(Container parent, - Class desiredClass) { - return findComponents(parent, desiredClass, false); - } - - public static List findComponents(Container parent, - Class desiredClass, boolean checkOwnedWindows) { - Component[] comps = parent.getComponents(); - List list = new ArrayList<>(); - for (Component element : comps) { - if (element == null) { - continue;// this started happening in 1.6, not sure why - } - if (desiredClass.isAssignableFrom(element.getClass())) { - list.add(desiredClass.cast(element)); - } - else if (element instanceof Container) { - T c = findComponent((Container) element, desiredClass, checkOwnedWindows); - if (c != null) { - list.add(desiredClass.cast(c)); - } - } - } - if (checkOwnedWindows && (parent instanceof Window)) { - Window[] windows = ((Window) parent).getOwnedWindows(); - for (int i = windows.length - 1; i >= 0; i--) { - Component c = findComponent(windows[i], desiredClass, checkOwnedWindows); - if (c != null) { - list.add(desiredClass.cast(c)); - } - } - } - return list; - } - /** * Get the first field object contained within object ownerInstance which * has the type classType. This method is only really useful if it is known @@ -675,883 +505,6 @@ public abstract class AbstractGenericTest extends AbstractGTest { return invokeInstanceMethod(methodName, ownerInstance, null, null); } - public static void findOwnedWindows(Window win, Set winList) { - Window[] children = win.getOwnedWindows(); - for (Window element : children) { - winList.add(element); - findOwnedWindows(element, winList); - } - } - - /** - * Finds the button with the indicated TEXT that is a sub-component of the - * indicated container, and then programmatically presses the button.
- * The following is a sample JUnit test use: - * - *
-	 * env.showTool();
-	 * OptionDialog dialog = (OptionDialog) env.waitForDialog(OptionDialog.class, 1000);
-	 * assertNotNull(dialog);
-	 * pressButtonByText(dialog, "OK");
-	 * 
- * - * @param container the container to search. (Typically a dialog.) - * @param buttonText the text on the desired JButton. - * @throws AssertionError if the button isn't found, isn't showing or isn't - * enabled - */ - public static void pressButtonByText(Container container, String buttonText) { - pressButtonByText(container, buttonText, true); - } - - /** - * Finds the button with the indicated TEXT that is a sub-component of the - * indicated container, and then programmatically presses the button. - * - * @param container the container to search. (Typically a dialog.) - * @param buttonText the text on the desired JButton. - * @param waitForCompletion if true wait for action to complete before - * returning, otherwise schedule action to be performed and - * return immediately. - * @throws AssertionError if the button isn't found, isn't showing or isn't - * enabled - */ - public static void pressButtonByText(Container container, String buttonText, - boolean waitForCompletion) { - - AbstractButton button = findAbstractButtonByText(container, buttonText); - if (button == null) { - throw new AssertionError("Couldn't find button " + buttonText + "."); - } - if (!runSwing(() -> button.isShowing())) { - throw new AssertionError("Button " + buttonText + " is not showing."); - } - if (!runSwing(() -> button.isEnabled())) { - throw new AssertionError("Button " + buttonText + " is not enabled."); - } - pressButton(button, waitForCompletion); - } - - /** - * Finds the button with the indicated NAME that is a subcomponent of the - * indicated container, and then programmatically presses the button. - * - * @param container the container to search. (Typically a dialog) - * @param buttonName the name on the desired AbstractButton (see - * Component.setName()) - */ - public static void pressButtonByName(Container container, String buttonName) { - pressButtonByName(container, buttonName, true); - } - - /** - * Finds the button with the indicated NAME that is a subcomponent of the - * indicated container, and then programmatically presses the button. - * - * @param container the container to search. (Typically a dialog.) - * @param buttonName the name on the desired AbstractButton (see - * Component.setName()). - * @param waitForCompletion if true wait for action to complete before - * returning, otherwise schedule action to be performed and - * return immediately - */ - public static void pressButtonByName(Container container, String buttonName, - boolean waitForCompletion) { - - AbstractButton button = (AbstractButton) findComponentByName(container, buttonName); - if (button == null) { - throw new AssertionError("Couldn't find button " + buttonName + "."); - } - if (!runSwing(() -> button.isShowing())) { - throw new AssertionError("Button " + buttonName + " is not showing."); - } - if (!runSwing(() -> button.isEnabled())) { - throw new AssertionError("Button " + buttonName + " is not enabled."); - } - pressButton(button, waitForCompletion); - } - - /** - * Programmatically presses the indicated button. - * - * @param button the button - */ - public static void pressButton(AbstractButton button) { - if (!button.isEnabled()) { - throw new AssertException("Attempted to press a disabled button"); - } - pressButton(button, true); - } - - /** - * Programmatically presses the indicated button. - * - * @param button the button - * @param waitForCompletion if true wait for action to complete before - * returning, otherwise schedule action to be performed and - * return immediately. - */ - public static void pressButton(AbstractButton button, boolean waitForCompletion) { - Runnable r = () -> button.doClick(0); // 0 means no sleeping - runSwing(r, waitForCompletion); - } - - /** - * Searches the subcomponents of the indicated container and returns the - * component with the specified name. - * - * @param container the container to search - * @param componentName the name of the desired component - * - * @return the component, or null if not found - */ - public static Component findComponentByName(Container container, String componentName) { - return findComponentByName(container, componentName, false); - } - - public static Component findComponentByName(Container container, String componentName, - boolean checkOwnedWindows) { - - String containerName = container.getName(); - - if (containerName != null && container.getName().equals(componentName)) { - return container; - } - - Component[] comps = container.getComponents(); - for (Component element : comps) { - if (element == null) { - continue;// this started happening in 1.6, not sure why - } - String name = element.getName(); - if (name != null && name.equals(componentName)) { - return element; - } - else if (element instanceof Container) { - Component comp = - findComponentByName((Container) element, componentName, checkOwnedWindows); - if (comp != null) { - return comp; - } - } - } - if (checkOwnedWindows && (container instanceof Window)) { - Window[] windows = ((Window) container).getOwnedWindows(); - for (int i = windows.length - 1; i >= 0; i--) { - Component c = findComponentByName(windows[i], componentName, checkOwnedWindows); - if (c != null) { - return c; - } - } - } - return null; - } - - public static List findComponentsByName(Container container, String componentName, - boolean checkOwnedWindows) { - - List retList = new ArrayList<>(); - - Component[] components = container.getComponents(); - for (Component component : components) { - if (component == null) { - continue; - } - String name = component.getName(); - if (name != null && name.equals(componentName)) { - retList.add(component); - } - else if (component instanceof Container) { - retList.addAll( - findComponentsByName((Container) component, componentName, checkOwnedWindows)); - } - - } - return retList; - } - - public static JButton findButtonByIcon(Container container, Icon icon) { - Component[] comps = container.getComponents(); - for (Component element : comps) { - if (element instanceof JButton) { - JButton button = (JButton) element; - Icon buttonIcon = button.getIcon(); - if (icon.equals(buttonIcon)) { - return button; - } - } - else if (element instanceof Container) { - JButton button = findButtonByIcon((Container) element, icon); - if (button != null) { - return button; - } - } - } - return null; - - } - - /** - * Searches the subcomponents of the the given container and returns the - * JButton that has the specified text. - * - * @param container the container to search - * @param text the button text - * @return the JButton, or null the button was not found - */ - public static JButton findButtonByText(Container container, String text) { - Component[] comps = container.getComponents(); - for (Component element : comps) { - if (element instanceof JButton) { - JButton button = (JButton) element; - if (button.getText() != null && button.getText().equals(text)) { - return button; - } - } - else if (element instanceof Container) { - JButton button = findButtonByText((Container) element, text); - if (button != null) { - return button; - } - } - } - return null; - } - - /** - * Searches the sub-components of the given container and returns the - * AbstractButton that has the specified text. - *

- * This differs from {@link #findButtonByText(Container, String)} in that - * this method will find buttons that do not extend from {@link JButton}. - * That method is convenient when you do not wish to cast the result from - * AbstractButton to JButton. Other than that, this method can handle all - * cases the other method cannot. - * - * @param container container to search - * @param text button text - * @return null if the button was not found - */ - public static AbstractButton findAbstractButtonByText(Container container, String text) { - - Component[] comp = container.getComponents(); - for (Component element : comp) { - if ((element instanceof AbstractButton) && - text.equals(((AbstractButton) element).getText())) { - return (AbstractButton) element; - } - else if (element instanceof Container) { - AbstractButton b = findAbstractButtonByText((Container) element, text); - if (b != null) { - return b; - } - } - } - return null; - } - - /** - * Searches the sub-components of the given container and returns the - * AbstractButton that has the specified name. - * - * @param container container to search - * @param name the button name (you must set this manually). - * @return null if the button was not found - */ - public static AbstractButton findAbstractButtonByName(Container container, String name) { - - Component[] comp = container.getComponents(); - for (Component element : comp) { - if ((element instanceof AbstractButton) && - name.equals(((AbstractButton) element).getName())) { - return (AbstractButton) element; - } - else if (element instanceof Container) { - AbstractButton b = findAbstractButtonByName((Container) element, name); - if (b != null) { - return b; - } - } - } - return null; - } - - public static void leftClick(JComponent comp, int x, int y) { - clickMouse(comp, MouseEvent.BUTTON1, x, y, 1, 0); - } - - public static void middleClick(JComponent comp, int x, int y) { - clickMouse(comp, MouseEvent.BUTTON2, x, y, 1, 0); - } - - public static void rightClick(JComponent comp, int x, int y) { - clickMouse(comp, MouseEvent.BUTTON3, x, y, 1, 0, true); - } - - public static void doubleClick(JComponent comp, int x, int y) { - clickMouse(comp, MouseEvent.BUTTON1, x, y, 2, 0); - } - - /** - * Simulates click the mouse button. - * - * @param comp the component to click on. - * @param button the mouse button (1, 2, or 3) - * @param x the x coordinate of the click location - * @param y the y coordinate of the click location - * @param clickCount the number of clicks (2 = double click) - * @param modifiers additional modifiers (e.g. MouseEvent.SHIFT_MASK) - * @param popupTrigger a boolean, true if this event is a trigger for a - * popup menu - */ - public static void clickMouse(Component comp, int button, int x, int y, int clickCount, - int modifiers, boolean popupTrigger) { - - int nonRelesedModifiers = convertToExtendedModifiers(modifiers, button, false); - int relesedModifiers = convertToExtendedModifiers(modifiers, button, true); - for (int cnt = 1; cnt <= clickCount; ++cnt) { - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), - nonRelesedModifiers, x, y, cnt, false, button)); - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), - nonRelesedModifiers, x, y, cnt, false, button)); - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), - relesedModifiers, x, y, cnt, popupTrigger, button)); - } - } - - /** - * Simulates click the mouse button. - * - * @param comp the component to click on. - * @param button the mouse button (1, 2, or 3) - * @param x the x coordinate of the click location - * @param y the y coordinate of the click location - * @param clickCount the number of clicks (2 = double click) - * @param modifiers additional modifiers (e.g. MouseEvent.SHIFT_MASK) - */ - public static void clickMouse(Component comp, int button, int x, int y, int clickCount, - int modifiers) { - - clickMouse(comp, button, x, y, clickCount, modifiers, false); - } - - /** - * Simulates a mouse drag action - * - * @param comp the component to drag on. - * @param button the mouse button (1, 2, or 3) - * @param startX the x coordinate of the start drag location - * @param startY the y coordinate of the start drag location - * @param endX the x coordinate of the end drag location - * @param endY the y coordinate of the end drag location - * @param modifiers additional modifiers (e.g. MouseEvent.SHIFT_MASK) - */ - public static void dragMouse(final Component comp, int button, final int startX, - final int startY, final int endX, final int endY, int modifiers) { - - int nonRelesedModifiers = convertToExtendedModifiers(modifiers, button, false); - int relesedModifiers = convertToExtendedModifiers(modifiers, button, true); - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), - nonRelesedModifiers, startX, startY, 1, false, button)); - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_DRAGGED, System.currentTimeMillis(), - nonRelesedModifiers, endX, endY, 1, false, button)); - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), - relesedModifiers, endX, endY, 1, false, button)); - - } - - /** - * Fire a mouse moved event for the given component. - * - * @param comp source of the event. - * @param x x position relative to the component - * @param y y position relative to the component - */ - public static void moveMouse(Component comp, int x, int y) { - postEvent(new MouseEvent(comp, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(), 0, x, y, - 0, false)); - - } - - @SuppressWarnings("deprecation") - private static int convertToExtendedModifiers(int modifiers, int button, boolean isRelease) { - - // TODO: Eliminate duplication of similar modifier modification logic - // which exists in KeyBindingData - - // remove system-dependent control key mask and transform deprecated modifiers - - int controlMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); - - if ((modifiers & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK) { - modifiers = modifiers ^ InputEvent.CTRL_DOWN_MASK; - modifiers = modifiers | controlMask; - } - - if ((modifiers & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) { - modifiers = modifiers ^ InputEvent.CTRL_MASK; - modifiers = modifiers | controlMask; - } - - if ((modifiers & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) { - modifiers = modifiers ^ ActionEvent.CTRL_MASK; - modifiers = modifiers | controlMask; - } - - if ((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) { - modifiers = modifiers ^ InputEvent.SHIFT_MASK; - modifiers = modifiers | InputEvent.SHIFT_DOWN_MASK; - } - - if ((modifiers & InputEvent.ALT_MASK) == InputEvent.ALT_MASK) { - modifiers = modifiers ^ InputEvent.ALT_MASK; - modifiers = modifiers | InputEvent.ALT_DOWN_MASK; - } - - if ((modifiers & InputEvent.META_MASK) == InputEvent.META_MASK) { - modifiers = modifiers ^ InputEvent.META_MASK; - modifiers = modifiers | InputEvent.META_DOWN_MASK; - } - - if (!isRelease) { - // - // There are no mouse buttons down on a 'release' in Java's extended event processing. - // (The original non-extended events did include the button in the release event.) - // - switch (button) { - case 1: - modifiers |= InputEvent.BUTTON1_DOWN_MASK; - break; - case 2: - modifiers |= InputEvent.BUTTON2_DOWN_MASK; - break; - case 3: - modifiers |= InputEvent.BUTTON3_DOWN_MASK; - break; - } - } - return modifiers; - } - - public static void postEvent(final AWTEvent ev) { - runSwing(() -> { - EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); - eq.postEvent(ev); - }); - waitForSwing(); - } - - /** - * Returns the value from the given {@link Supplier}, invoking the call in - * the Swing thread. This is useful when you may have values that are being - * changed on the Swing thread and you need the test thread to see the - * changes. - * - * @param s the supplier - * @return the value returned by the supplier - */ - public static T runSwing(Supplier s) { - AtomicReference ref = new AtomicReference<>(); - runSwing(() -> ref.set(s.get())); - return ref.get(); - } - - /** - * Run the given code snippet on the Swing thread and wait for it to finish - * @param r the runnable code snippet - */ - public static void runSwing(Runnable r) { - runSwing(r, true); - } - - /** - * Run the given code snippet on the Swing thread later, not blocking the current thread. Use - * this if the code snippet causes a blocking operation. - * - *

This is a shortcut for runSwing(r, false);. - * - * @param r the runnable code snippet - */ - public void runSwingLater(Runnable r) { - runSwing(r, false); - } - - /** - * Call this version of {@link #runSwing(Runnable)} when you expect your runnable may - * throw exceptions - * - * @param callback the runnable code snippet to call - * @throws Exception any exception that is thrown on the Swing thread - */ - public static void runSwingWithException(ExceptionalCallback callback) - throws Exception { - - if (Swing.isSwingThread()) { - throw new AssertException("Unexpectedly called from the Swing thread"); - } - - ExceptionHandlingRunner exceptionHandlingRunner = new ExceptionHandlingRunner(callback); - Throwable throwable = exceptionHandlingRunner.getException(); - if (throwable == null) { - return; - } - - if (throwable instanceof Exception) { - // this is what the client expected - throw (Exception) throwable; - } - - // a runtime exception; re-throw - throw new AssertException(throwable); - } - - public static void runSwing(Runnable runnable, boolean wait) { - - // - // Special Case: this check handled re-entrant test code. That is, an calls to runSwing() - // that are made from within a runSwing() call. Most clients do not do - // this, but it can happen when a client makes a test API call (which itself - // calls runSwing()) from within a runSwing() call. - // - // Calling the run method directly here ensures that the order of client - // requests is preserved. - // - if (SwingUtilities.isEventDispatchThread()) { - runnable.run(); - return; - } - - if (wait) { - runSwingAndWait(runnable); - return; - } - - // don't wait; invoke later; catch any exceptions ourselves in order to fail-fast - Runnable swingExceptionCatcher = () -> { - try { - runnable.run(); - } - catch (Throwable t) { - // submit this failure directly to the handler; fail the test - ConcurrentTestExceptionHandler.handle(Thread.currentThread(), t); - } - }; - - SwingUtilities.invokeLater(swingExceptionCatcher); - } - - protected static class ExceptionHandlingRunner { - private final ExceptionalCallback delegateCallback; - private Throwable exception; - - ExceptionHandlingRunner(Runnable delegateRunnable) { - this.delegateCallback = () -> { - delegateRunnable.run(); - }; - run(); - } - - ExceptionHandlingRunner(ExceptionalCallback delegateCallback) { - this.delegateCallback = delegateCallback; - run(); - } - - Throwable getException() { - return exception; - } - - String getExceptionMessage() { - Throwable throwable = getException(); - String message = throwable.getMessage(); - if (message != null) { - return message; - } - - return getCauseExceptionMessage(throwable); - } - - protected String getCauseExceptionMessage(Throwable t) { - if (t == null) { - return ""; - } - - if (t instanceof AssertionError) { - return t.getMessage(); - } - - String message = t.getMessage(); - if (message != null) { - return message; - } - - return getCauseExceptionMessage(t.getCause()); - } - - private void run() { - - Runnable swingExceptionCatcher = () -> { - try { - delegateCallback.call(); - } - catch (Throwable t) { - exception = t; - } - }; - - try { - doRun(swingExceptionCatcher); - } - catch (InterruptedException e) { - // Typically, this InterrruptedException that is caused by our test harness when it - // is interrupting the test thread after a previous Swing exception that we have - // detected--we don't care to throw the InterruptedException, as we caused it. - // Log a message to signal that unusual things may happen when in this state. - Msg.debug(this, "\n>>>>>>>>>>>>>>>> Test thread interrupted. Unusual/unexpected " + - "errors may follow.\n\n"); - } - catch (InvocationTargetException e) { - // Assume that if we have an exception reported by our catcher above, then that is - // the root cause of this exception and do not report this one. This should not - // happen, as we are catching the exception above. - } - } - - private void doRun(Runnable runnable) - throws InvocationTargetException, InterruptedException { - if (SwingUtilities.isEventDispatchThread()) { - runnable.run(); - } - else { - SwingUtilities.invokeAndWait(runnable); - } - } - } - - private static void runSwingAndWait(Runnable runnable) { - ExceptionHandlingRunner exceptionHandlingRunner = new ExceptionHandlingRunner(runnable); - - Throwable throwable = exceptionHandlingRunner.getException(); - if (throwable == null) { - return; - } - - // - // Handle the exception - // - if (!TestThread.isTestThread()) { - // we have plumbing that checks for this in headed environments - ConcurrentTestExceptionHandler.handle(Thread.currentThread(), throwable); - return; - } - - // - // When not in batch mode, Eclipse and Gradle will show the exception we build here, - // which is the most helpful. - // - String message = "Exception in Swing thread via runSwingAndWait():"; - if (!BATCH_MODE) { - TestReportingException exception = - TestReportingException.fromSwingThread(message, throwable); - throw exception; - } - - // - // When running in batch mode, the report generated by Gradle will not correctly show - // the stack trace if we throw the exception, so will will trigger a failure instead, - // which looks good in the test report. - // - String string = TestReportingException.getSwingThreadTraceString(throwable); - Assert.fail(message + "\n" + string + "\nTest Thread stack at that time:"); - } - - /** - * Launches the runnable on a new thread so as to not block the calling - * thread. This is very useful for performing actions on the Swing thread - * that show modal dialogs, which would otherwise block the calling thread, - * such as a testing thread. - * - * @param runnable The runnable that will be executed in a new Thread that - * will place the runnable on the Swing thread. - */ - public static void executeOnSwingWithoutBlocking(Runnable runnable) { - - AtomicBoolean didRun = new AtomicBoolean(); - (new Thread() { - @Override - public void run() { - didRun.set(true); - runSwing(runnable); - } - }).start(); - - // we can make this call, since any potential modal dialogs are not blocking in the Swing - // thread, but in the new event queue created by the modal dialog (this is how repainting - // still works when a modal dialog is shown) - waitForSwing(); - - waitForCondition(() -> didRun.get()); - - // pause a bit to let the swing thread process - sleep(DEFAULT_WAIT_DELAY); - - // make sure any pending Swing events have been processed - waitForSwing(); - } - - public static void clickTableCell(final JTable table, final int row, final int col, - int clickCount) { - runSwing(() -> table.setRowSelectionInterval(row, row)); - waitForSwing(); - Rectangle rect = table.getCellRect(row, col, true); - clickMouse(table, MouseEvent.BUTTON1, rect.x + 10, rect.y + 10, clickCount, 0); - waitForSwing(); - } - - /** - * Clicks a range of items in a list (simulates holding SHIFT and selecting - * each item in the range in-turn) - * - * @param list the list to select from - * @param row the initial index - * @param count the number of rows to select - */ - public static void clickListRange(final JList list, final int row, int count) { - waitForSwing(); - for (int i = row; i < row + count; i++) { - Rectangle rect = list.getCellBounds(i, i); - clickMouse(list, MouseEvent.BUTTON1, rect.x + 10, rect.y + 10, 1, - InputEvent.SHIFT_DOWN_MASK); - } - waitForSwing(); - } - - /** - * Clicks a range of items in a table (simulates holding SHIFT and selecting - * each item in the range) - * - * @param table the table to select - * @param row the starting row index - * @param count the number of rows to select - */ - public static void clickTableRange(final JTable table, final int row, int count) { - waitForSwing(); - for (int i = row; i < row + count; i++) { - Rectangle rect = table.getCellRect(i, 0, true); - clickMouse(table, MouseEvent.BUTTON1, rect.x + 10, rect.y + 10, 1, - InputEvent.SHIFT_DOWN_MASK); - } - waitForSwing(); - } - - public static TableCellEditor editCell(final JTable table, final int row, final int col) { - - waitForSwing(); - - runSwing(() -> table.setRowSelectionInterval(row, row)); - waitForSwing(); - - runSwing(() -> table.editCellAt(row, col)); - waitForSwing(); - - TableCellEditor editor = table.getCellEditor(row, col); - assertNotNull("Unable to edit table cell at " + row + ", " + col, editor); - return editor; - } - - /** - * Gets the rendered value for the specified table cell. The actual value at the cell may - * not be a String. This method will get the String display value, as created by the table. - * - * @param table the table to query - * @param row the row to query - * @param column the column to query - * @return the String value - * @throws IllegalArgumentException if there is no renderer or the rendered component is - * something from which this method can get a String (such as a JLabel) - */ - public static String getRenderedTableCellValue(JTable table, int row, int column) { - - return runSwing(() -> { - - TableCellRenderer renderer = table.getCellRenderer(row, column); - if (renderer == null) { - throw new IllegalArgumentException( - "No renderer registered for row/col: " + row + '/' + column); - } - Component component = table.prepareRenderer(renderer, row, column); - if (!(component instanceof JLabel)) { - throw new IllegalArgumentException( - "Do not know how to get text from a renderer " + "that is not a JLabel"); - } - - return ((JLabel) component).getText(); - }); - } - - public static void setComboBoxSelection(final JComboBox comboField, final T selection) { - runSwing(() -> comboField.setSelectedItem(selection)); - waitForSwing(); - } - - public static void setText(final JTextComponent field, final String text) { - runSwing(() -> field.setText(text)); - waitForSwing(); - } - - public static String getText(final JTextComponent field) { - return runSwing(() -> field.getText()); - } - - /** - * Finds the path of a tree node in the indicated tree with the specified - * text. The matching tree node is determined by comparing the specified - * text with the string returned by the tree node's toString() method.
- * Note: This method affects the expansion state of the tree. It will expand - * nodes starting at the root until a match is found or all of the tree is - * checked. - * - * @param tree the tree - * @param text the tree node's text - * @return the tree path - */ - public static TreePath findTreePathToText(JTree tree, String text) { - TreeModel tm = tree.getModel(); - TreeNode rootNode = (TreeNode) tm.getRoot(); - TreePath rootPath = new TreePath(rootNode); - return findPathToText(tree, rootPath, text); - } - - /** - * Performs a depth first search for the named tree node. - * - * @param tree the tree to search - * @param startTreePath path indicating node to begin searching from in the - * tree - * @param text the name of the node to find - * @return the path to the named node or null if it can't be found. - */ - protected static TreePath findPathToText(JTree tree, TreePath startTreePath, String text) { - if (text.equals(startTreePath.getLastPathComponent().toString())) { - return startTreePath; - } - tree.expandPath(startTreePath); - int len = startTreePath.getPathCount(); - Object[] tpObjects = new Object[len + 1]; - System.arraycopy(startTreePath.getPath(), 0, tpObjects, 0, len); - TreeNode treeNode = (TreeNode) startTreePath.getLastPathComponent(); - int num = treeNode.getChildCount(); - for (int i = 0; i < num; i++) { - TreeNode childNode = treeNode.getChildAt(i); - tpObjects[len] = childNode; - TreePath childPath = new TreePath(tpObjects); - TreePath treePath = findPathToText(tree, childPath, text); - if (treePath != null) { - return treePath; - } - } - return null; - } - /** * Returns a string which is a printout of a stack trace for each thread * running in the current JVM @@ -1589,44 +542,6 @@ public abstract class AbstractGenericTest extends AbstractGTest { return buffer.toString(); } - /** - * Invoke fixupGUI at the beginning of your JUnit test or in - * its setup() method to make your GUI for the JUnit test appear using the - * system Look and Feel. The system look and feel is the default that Ghidra - * uses. This will also change the default fonts for the JUnit test to be - * the same as those in Ghidra. - * - * @exception InterruptedException if we're interrupted while waiting for - * the event dispatching thread to finish excecuting - * doRun.run() - * @exception InvocationTargetException if an exception is thrown while - * running doRun - */ - public static void fixupGUI() throws InterruptedException, InvocationTargetException { - // Make the test look & feel as it would normally. - SwingUtilities.invokeAndWait(() -> { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } - catch (ClassNotFoundException e1) { - // don't care - } - catch (InstantiationException e2) { - // don't care - } - catch (IllegalAccessException e3) { - // don't care - } - catch (UnsupportedLookAndFeelException e4) { - // don't care - } - }); - // Fix up the default fonts that Java 1.5.0 changed to Courier, which looked terrible. - Font f = Gui.getFont("font.monospaced"); - UIManager.put("PasswordField.font", f); - UIManager.put("TextArea.font", f); - } - /** * Returns a font metrics for the given font using a generic buffered image graphics context. * @param font the font @@ -1659,177 +574,6 @@ public abstract class AbstractGenericTest extends AbstractGTest { } } -//================================================================================================== -// Swing Methods -//================================================================================================== - - /** - * Waits for the Swing thread to process any pending events. This method - * also waits for any {@link SwingUpdateManager}s that have pending events - * to be flushed. - * - * @return true if the any {@link SwingUpdateManager}s were busy. - */ - public static boolean waitForSwing() { - if (SwingUtilities.isEventDispatchThread()) { - throw new AssertException("Can't wait for swing from within the swing thread!"); - } - - Set set = new HashSet<>(); - runSwing(() -> { - @SuppressWarnings("unchecked") - WeakSet s = - (WeakSet) getInstanceField("instances", - SwingUpdateManager.class); - for (AbstractSwingUpdateManager manager : s) { - set.add(manager); - } - }); - - /* - long start = System.nanoTime(); - boolean wasEverBusy = waitForSwing(set, true); - long end = System.nanoTime(); - Msg.out("\twaitForSwing() - " + - TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS)); - */ - - boolean wasEverBusy = waitForSwing(set, true); - return wasEverBusy; - } - - private static boolean waitForSwing(Set managers, boolean flush) { - - // Note: not sure how long is too long to wait for the Swing thread and update managers - // to finish. This is usually less than a second. We have seen a degenerate - // case where this took minutes. This method is called often, so don't wait too - // long. This will have to be changed through trial-and-error. - int MAX_SWING_TIMEOUT = 15000; - int totalTime = 0; - - // flush all managers up front to get them started before we check them - flushAllManagers(managers, flush); - - boolean wasEverBusy = false; - boolean keepGoing = true; - while (keepGoing) { - - // let swing paint and maybe schedule more work on the update managers - yieldToSwing(); - keepGoing = false; - - for (AbstractSwingUpdateManager manager : managers) { - - if (!manager.isBusy()) { - // no current or pending work - continue; - } - - // Msg.out("busy manager: " + manager.toStringDebug()); - - doFlush(flush, manager); - - boolean isBusy = true; - while (isBusy) { - - keepGoing = true; // true, since we had a busy signal - wasEverBusy = true; - - totalTime += sleep(DEFAULT_WAIT_DELAY); - if (totalTime >= MAX_SWING_TIMEOUT) { - // eject! - Msg.debug(AbstractGenericTest.class, - "Timed-out waitinig for Swing after " + totalTime + " ms. " + - "The currently waited SwingUpdateManager:\n" + - manager.toStringDebug()); - return true; - } - - isBusy = manager.isBusy(); - } - } - // let any resulting swing events finish - yieldToSwing(); - } - - return wasEverBusy; - } - - private static void flushAllManagers(Set managers, boolean flush) { - - // - // Some update managers will make an update that causes another manager to schedule an - // update. In order to *not* have to wait for each of these, one-at-a-time, loop a - // few times so that any follow-up scheduling events will be executed as well. These - // calls all execute in the Swing thread in a blocking fashion, so when we are done - // flushing, there should be no more work scheduled due to us flushing. Due to other - // potential background threads though, more work may be scheduled as we are working. - // Thus, for fast tests, you should not have background work happening that is not - // directly related to your code being tested. - // - - // arbitrary; we have at least one level of a manager triggering another manager, - // which would be 2 - int n = 3; - for (int i = 0; i < n; i++) { - for (AbstractSwingUpdateManager manager : managers) { - doFlush(flush, manager); - } - } - } - - private static void doFlush(boolean doFlush, AbstractSwingUpdateManager manager) { - if (!doFlush) { - return; - } - - runSwing(() -> { - manager.flush(); - }, false); - yieldToSwing(); - } - - /** - * This is only for internal use. If you need to wait for the Swing thread - * from your test, then use {@link #waitForSwing()}. - * - * @deprecated This is not a test writer's method, but instead an - * infrastructure method. - */ - @Deprecated - public static void privateWaitForPostedSwingRunnables_SwingSafe() { - yieldToSwing(); - } - - protected static void yieldToSwing() { - - if (SwingUtilities.isEventDispatchThread()) { - Msg.error(AbstractGenericTest.class, - "Incorrectly called yieldToSwing() from the Swing thread"); - return; // shouldn't happen - } - - Runnable empty = () -> { - // do nothing...this is just a placeholder runnable that gets put onto the stack - }; - - // - // Note: the calls below are designed to ignore being interrupted. Further, if one of - // the calls is interrupted, the others will still work as expected. - // - for (int i = 0; i < 3; i++) { - try { - SwingUtilities.invokeAndWait(empty); - } - catch (Exception e) { - // Assumption: since our runnable is empty, this can only an interrupted - // exception, which can happen if our test framework decides to - // shut the operation down. - return; - } - } - } - //================================================================================================== // Temp File Management //================================================================================================== @@ -2087,51 +831,4 @@ public abstract class AbstractGenericTest extends AbstractGTest { } } - /** - * Asserts that the two colors have the same rgb values (handles GColor) - * @param expected the expected color - * @param actual the actual color - */ - public void assertColorsEqual(Color expected, Color actual) { - if (expected.getRGB() == actual.getRGB()) { - return; - } - fail("Expected: [" + expected.getClass().getSimpleName() + "]" + expected + - ", but got: [" + actual.getClass().getSimpleName() + "]" + actual); - } - - /** - * Asserts that the two icons are or refer to the same icon (handles GIcon) - * @param expected the expected icon - * @param actual the actual icon - */ - public void assertIconsEqual(Icon expected, Icon actual) { - if (expected.equals(actual)) { - return; - } - URL url1 = getURL(expected); - URL url2 = getURL(actual); - - if (url1 != null && url1.equals(url2)) { - return; - } - fail("Expected icon [" + expected.getClass().getSimpleName() + "]" + expected.toString() + - ", but got: [" + actual.getClass().getSimpleName() + "]" + actual.toString()); - } - - /** - * Gets the URL for the given icon - * @param icon the icon to get a URL for - * @return the URL for the given icon - */ - public URL getURL(Icon icon) { - if (icon instanceof UrlImageIcon urlIcon) { - return urlIcon.getUrl(); - } - if (icon instanceof GIcon gIcon) { - return gIcon.getUrl(); - } - return null; - } - } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/util/FileLocker.java b/Ghidra/Framework/Generic/src/main/java/generic/util/FileLocker.java index 4668b55f14..a273f18589 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/util/FileLocker.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/util/FileLocker.java @@ -22,8 +22,6 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; -import ghidra.util.HTMLUtilities; - public class FileLocker { private static final String META_TAG = " "; @@ -111,10 +109,10 @@ public class FileLocker { for (String name : PROPERTY_KEYS) { buf.append(""); buf.append("     "); - buf.append(HTMLUtilities.escapeHTML(name)); + buf.append(name); buf.append(": "); buf.append(""); - buf.append(HTMLUtilities.escapeHTML(existingLockProperties.get(name).toString())); + buf.append(existingLockProperties.get(name).toString()); buf.append(""); } buf.append(""); diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/LoggingInitialization.java b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/LoggingInitialization.java index d73cf3c449..36a04c5d4c 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/LoggingInitialization.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/framework/LoggingInitialization.java @@ -24,7 +24,6 @@ import org.apache.logging.log4j.core.LoggerContext; import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.exception.AssertException; -import resources.ResourceManager; public class LoggingInitialization { @@ -90,7 +89,7 @@ public class LoggingInitialization { loggingConfigFilename = DEVELOPMENT_LOGGING_CONFIGURATION_FILE; } - return ResourceManager.getResource(loggingConfigFilename); + return LoggingInitialization.class.getClassLoader().getResource(loggingConfigFilename); } private static URL getLogFileFromSystemProperty() { @@ -100,7 +99,7 @@ public class LoggingInitialization { } // first see if the given filename is something that is in our classpath - URL resource = ResourceManager.getResource(configString); + URL resource = LoggingInitialization.class.getClassLoader().getResource(configString); if (resource != null) { return resource; } diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java index 3975fab8db..8857ecf726 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java @@ -33,8 +33,6 @@ import ghidra.security.KeyStorePasswordProvider; import ghidra.util.Msg; import ghidra.util.SystemUtilities; import ghidra.util.exception.CancelledException; -import ghidra.util.filechooser.ExtensionFileFilter; -import ghidra.util.filechooser.GhidraFileFilter; /** * ApplicationKeyManagerFactory provides application keystore management @@ -58,12 +56,6 @@ public class ApplicationKeyManagerFactory { */ public static final String KEYSTORE_PASSWORD_PROPERTY = "ghidra.password"; - /** - * PKCS Private Key/Certificate File Filter - */ - public static final GhidraFileFilter CERTIFICATE_FILE_FILTER = - new ExtensionFileFilter(ApplicationKeyStore.PKCS_FILE_EXTENSIONS, "PKCS Key File"); - public static final String DEFAULT_PASSWORD = "changeme"; private static final int SELF_SIGNED_DURATION_DAYS = 2 * 365; // 2-years diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java index 9a6c1d4d96..55fd3a1e9f 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java @@ -26,6 +26,7 @@ import java.util.*; import javax.net.ssl.*; import javax.security.auth.DestroyFailedException; import javax.security.auth.x500.X500Principal; +import javax.swing.filechooser.FileNameExtensionFilter; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.style.RFC4519Style; @@ -61,6 +62,10 @@ public class ApplicationKeyManagerUtils { public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; public static final String END_CERT = "-----END CERTIFICATE-----"; + public static final String[] PKCS_FILE_EXTENSIONS = new String[] { "p12", "pks", "pfx" }; + public static final FileNameExtensionFilter PKCS_FILENAME_FILTER = + new FileNameExtensionFilter("PKCS Key File", PKCS_FILE_EXTENSIONS); + static { /** * Bouncy Castle uses its BCStyle for X500Names which reverses Distingushed Name ordering. @@ -356,21 +361,21 @@ public class ApplicationKeyManagerUtils { long durationMs = (long) durationDays * MILLISECONDS_PER_DAY; Date notAfter = new Date(notBefore.getTime() + durationMs); BigInteger serialNumber = new BigInteger(128, random); - + // JcaX509ExtensionUtils x509Utils = new JcaX509ExtensionUtils(); - + X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(caX500Name, serialNumber, notBefore, notAfter, x500Name, bcPk); certificateBuilder // .addExtension(Extension.subjectKeyIdentifier, true, x509Utils.createSubjectKeyIdentifier(bcPk)) .addExtension(Extension.keyUsage, true, keyUsage); - + if (caEntry == null) { certificateBuilder .addExtension(Extension.basicConstraints, true, new BasicConstraints(1)); // .addExtension(Extension.authorityKeyIdentifier, true, x509Utils.createAuthorityKeyIdentifier(bcPk)); } - + ContentSigner contentSigner = new JcaContentSignerBuilder(SIGNING_ALGORITHM).build(issuerKey); diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyStore.java b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyStore.java index eae5a8108f..cea30ea79d 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyStore.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyStore.java @@ -23,7 +23,6 @@ import java.util.Date; import java.util.Enumeration; import javax.security.auth.x500.X500Principal; -import javax.swing.filechooser.FileNameExtensionFilter; import ghidra.util.Msg; @@ -35,11 +34,6 @@ import ghidra.util.Msg; */ class ApplicationKeyStore { - static final String[] PKCS_FILE_EXTENSIONS = new String[] { "p12", "pks", "pfx" }; - - private static final FileNameExtensionFilter PKCS_FILENAME_FILTER = - new FileNameExtensionFilter("PKCS Key File", PKCS_FILE_EXTENSIONS); - private ApplicationKeyStore() { // no instantiation - static methods only } @@ -113,7 +107,7 @@ class ApplicationKeyStore { throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { File keystoreFile = new File(keystorePath); - boolean isPKCS12 = PKCS_FILENAME_FILTER.accept(keystoreFile); + boolean isPKCS12 = ApplicationKeyManagerUtils.PKCS_FILENAME_FILTER.accept(keystoreFile); String type = isPKCS12 ? "PKCS12" : "JKS"; // JKS assumed if not PKCS KeyStore ks = KeyStore.getInstance(type); diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/xml/XmlWriter.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/xml/XmlWriter.java index 2bfbf1d65a..7bc905dee6 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/xml/XmlWriter.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/xml/XmlWriter.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. @@ -16,15 +15,8 @@ */ package ghidra.util.xml; - - import java.io.*; -import resources.ResourceManager; - - - - /** * A class for creating XML files. */ @@ -42,68 +34,75 @@ public class XmlWriter { * @throws IOException if an i/o error occurs */ public XmlWriter(File file, String dtdName) throws IOException { - this(new FileOutputStream(file), dtdName); + this(new FileOutputStream(file), dtdName); } + /** * Constructs a new XML writer. * @param out the output stream * @param dtdName the name of the DTD * @throws IOException if an i/o error occurs */ - public XmlWriter(OutputStream out, String dtdName) throws IOException { - writer = new PrintWriter(out); - counter = new Counter(); + public XmlWriter(OutputStream out, String dtdName) throws IOException { + writer = new PrintWriter(out); + counter = new Counter(); if (dtdName != null) { writeDTD(dtdName); } - } - /** - * Returns the XML summary string. - * @return the XML summary string - */ + } + + /** + * Returns the XML summary string. + * @return the XML summary string + */ public Counter getCounter() { return counter; } + /** * Closes this XML writer. */ public void close() { writer.close(); } + /** * Writes the specified DTD into the file. * @param dtdName the name of the DTD * @throws IOException if an i/o error occurs */ - public void writeDTD(String dtdName) throws IOException { - InputStream is = ResourceManager.getResourceAsStream(dtdName); - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - String line; - while((line = reader.readLine()) != null) { - writer.println(line); - } - reader.close(); - } - /** - * Writes the specified start element. - * @param name the name of the start element - */ + public void writeDTD(String dtdName) throws IOException { + InputStream is = getClass().getClassLoader().getResourceAsStream(dtdName); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line; + while ((line = reader.readLine()) != null) { + writer.println(line); + } + reader.close(); + } + + /** + * Writes the specified start element. + * @param name the name of the start element + */ public void startElement(String name) { startElement(name, null, null); } - /** - * Writes the specified start element with the attributes. - * @param name the name of the start element - * @param attrs the attributes of the start element - */ + + /** + * Writes the specified start element with the attributes. + * @param name the name of the start element + * @param attrs the attributes of the start element + */ public void startElement(String name, XmlAttributes attrs) { startElement(name, attrs, null); } - private void startElement(String name, XmlAttributes attrs, String text) { - if (addedText) { - throw new IllegalStateException("Cannot have child elements in parent elements with text!"); - } + private void startElement(String name, XmlAttributes attrs, String text) { + if (addedText) { + throw new IllegalStateException( + "Cannot have child elements in parent elements with text!"); + } counter.increment(name); @@ -111,54 +110,56 @@ public class XmlWriter { writer.println(">"); incompleteLine = false; } - indent(); - indentLevel++; - writer.print("<"); - writer.print(name); + indent(); + indentLevel++; + writer.print("<"); + writer.print(name); incompleteLine = true; - if (attrs != null) { - writer.print(attrs.toString()); - } - if (text != null) { - writer.print(">"); - writer.print(XmlUtilities.escapeElementEntities(text)); + if (attrs != null) { + writer.print(attrs.toString()); + } + if (text != null) { + writer.print(">"); + writer.print(XmlUtilities.escapeElementEntities(text)); incompleteLine = false; addedText = true; - } - } + } + } - /** - * Writes the specified end element. - * @param name the name of the end element - */ - public void endElement(String name) { + /** + * Writes the specified end element. + * @param name the name of the end element + */ + public void endElement(String name) { indentLevel--; - if (incompleteLine) { + if (incompleteLine) { writer.println(" />"); - } - else { - if (!addedText) { + } + else { + if (!addedText) { indent(); - } - writer.println(""); - } + } + writer.println(""); + } incompleteLine = false; addedText = false; - } - /** - * Writes the specified element with the attributes. - * @param name the name of the start element - * @param attrs the attributes of the start element - */ + } + + /** + * Writes the specified element with the attributes. + * @param name the name of the start element + * @param attrs the attributes of the start element + */ public void writeElement(String name, XmlAttributes attrs) { writeElement(name, attrs, null); } - /** - * Writes the specified element with the attributes and text. - * @param name the name of the element - * @param attrs the attributes of the element - * @param text the text of the element - */ + + /** + * Writes the specified element with the attributes and text. + * @param name the name of the element + * @param attrs the attributes of the element + * @param text the text of the element + */ public void writeElement(String name, XmlAttributes attrs, String text) { startElement(name, attrs, text); endElement(name); @@ -170,5 +171,3 @@ public class XmlWriter { } } } - - diff --git a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/GraphViewerTransformationsTest.java b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/GraphViewerTransformationsTest.java index 763e13843a..af1cbc8091 100644 --- a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/GraphViewerTransformationsTest.java +++ b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/GraphViewerTransformationsTest.java @@ -25,7 +25,7 @@ import org.junit.*; import edu.uci.ics.jung.algorithms.layout.DAGLayout; import edu.uci.ics.jung.algorithms.layout.Layout; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.graph.graphs.*; import ghidra.graph.support.*; import ghidra.graph.viewer.GraphViewerUtils; @@ -60,7 +60,7 @@ public class GraphViewerTransformationsTest { } protected void swing(Runnable r) { - AbstractGenericTest.runSwing(r); + AbstractGuiTest.runSwing(r); } private TestVisualGraph buildGraph() { @@ -196,7 +196,7 @@ public class GraphViewerTransformationsTest { // TODO move up the Swing methods? ...to reduce dependencies on slow startup stuff? - AbstractGenericTest.runSwing(() -> GraphViewerUtils.setGraphScale(viewer, d)); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.runSwing(() -> GraphViewerUtils.setGraphScale(viewer, d)); + AbstractGuiTest.waitForSwing(); } } diff --git a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/job/VisualGraphJobRunnerTest.java b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/job/VisualGraphJobRunnerTest.java index 329b14535b..ba286a0054 100644 --- a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/job/VisualGraphJobRunnerTest.java +++ b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/job/VisualGraphJobRunnerTest.java @@ -27,7 +27,7 @@ import org.apache.logging.log4j.Logger; import org.junit.*; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.LoggingInitialization; import ghidra.util.Msg; import ghidra.util.SystemUtilities; @@ -35,7 +35,7 @@ import ghidra.util.datastruct.WeakDataStructureFactory; import ghidra.util.datastruct.WeakSet; import ghidra.util.exception.AssertException; -public class VisualGraphJobRunnerTest extends AbstractGenericTest { +public class VisualGraphJobRunnerTest extends AbstractGuiTest { // something reasonable: too large makes the test slower; too small, then the test can timeout private static final int RUN_TIME_MILLIS_JOB_THREAD_MAX = 1000; diff --git a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/AbstractVisualGraphTest.java b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/AbstractVisualGraphTest.java index e367f61e77..11450661b7 100644 --- a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/AbstractVisualGraphTest.java +++ b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/AbstractVisualGraphTest.java @@ -32,7 +32,6 @@ import org.junit.Before; import docking.test.AbstractDockingTest; import edu.uci.ics.jung.algorithms.layout.Layout; -import generic.test.AbstractGenericTest; import ghidra.graph.graphs.AbstractTestVertex; import ghidra.graph.graphs.TestEdge; import ghidra.graph.support.*; @@ -123,11 +122,11 @@ public abstract class AbstractVisualGraphTest extends AbstractDockingTest { } protected void swing(Runnable r) { - AbstractGenericTest.runSwing(r); + runSwing(r); } protected T swing(Supplier s) { - return AbstractGenericTest.runSwing(s); + return runSwing(s); } protected void waitForAnimation() { @@ -258,7 +257,7 @@ public abstract class AbstractVisualGraphTest extends AbstractDockingTest { protected void clickViewer(int x, int y) { GraphViewer viewer = graphComponent.getPrimaryViewer(); - AbstractGenericTest.clickMouse(viewer, MouseEvent.BUTTON1, x, y, 1, 0); + clickMouse(viewer, MouseEvent.BUTTON1, x, y, 1, 0); waitForSwing(); } @@ -276,7 +275,7 @@ public abstract class AbstractVisualGraphTest extends AbstractDockingTest { Point p = getViewLocation(v); int x = p.x + xOffset; int y = p.y + yOffset; - AbstractGenericTest.clickMouse(viewer, MouseEvent.BUTTON1, x, y, clickCount, 0); + clickMouse(viewer, MouseEvent.BUTTON1, x, y, clickCount, 0); waitForSwing(); AbstractTestVertex focused = swing(() -> graph.getFocusedVertex()); @@ -318,12 +317,12 @@ public abstract class AbstractVisualGraphTest extends AbstractDockingTest { int x = (int) p.getX(); int y = (int) p.getY(); - AbstractGenericTest.moveMouse(viewer, x, y); + moveMouse(viewer, x, y); } protected void drag(int x1, int y1, int x2, int y2) { GraphViewer viewer = graphComponent.getPrimaryViewer(); - AbstractGenericTest.dragMouse(viewer, MouseEvent.BUTTON1, x1, y1, x2, y2, 0); + dragMouse(viewer, MouseEvent.BUTTON1, x1, y1, x2, y2, 0); waitForAnimation(); } diff --git a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/GraphComponentTest.java b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/GraphComponentTest.java index a5a461a226..a802981ad9 100644 --- a/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/GraphComponentTest.java +++ b/Ghidra/Framework/Graph/src/test.slow/java/ghidra/graph/viewer/GraphComponentTest.java @@ -33,7 +33,6 @@ import org.junit.Test; import docking.test.AbstractDockingTest; import edu.uci.ics.jung.visualization.RenderContext; -import generic.test.AbstractGenericTest; import generic.test.TestUtils; import generic.util.WindowUtilities; import ghidra.graph.graphs.*; @@ -481,7 +480,7 @@ public class GraphComponentTest extends AbstractVisualGraphTest { } private void press(String name) { - AbstractGenericTest.pressButtonByName(graphComponent.getComponent(), name, true); + pressButtonByName(graphComponent.getComponent(), name, true); } private AbstractTestVertex pickNonEditableVertex() { diff --git a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/AbstractGraphAlgorithmsTest.java b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/AbstractGraphAlgorithmsTest.java index c24917d455..f59759fb53 100644 --- a/Ghidra/Framework/Graph/src/test/java/ghidra/graph/AbstractGraphAlgorithmsTest.java +++ b/Ghidra/Framework/Graph/src/test/java/ghidra/graph/AbstractGraphAlgorithmsTest.java @@ -15,8 +15,7 @@ */ package ghidra.graph; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import java.util.*; @@ -24,6 +23,7 @@ import org.junit.Assert; import org.junit.Before; import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.graph.algo.ChkDominanceAlgorithm; import ghidra.graph.algo.ChkPostDominanceAlgorithm; import ghidra.util.exception.CancelledException; @@ -65,7 +65,7 @@ public abstract class AbstractGraphAlgorithmsTest extends AbstractGenericTest { while (true) { sleep(1000); - printMemory(); + AbstractGuiTest.printMemory(); } }, "Memory Monitor"); diff --git a/Ghidra/Framework/Gui/Module.manifest b/Ghidra/Framework/Gui/Module.manifest new file mode 100644 index 0000000000..25eb760254 --- /dev/null +++ b/Ghidra/Framework/Gui/Module.manifest @@ -0,0 +1 @@ +MODULE FILE LICENSE: lib/flatlaf-2.6.jar Apache License 2.0 diff --git a/Ghidra/Framework/Gui/build.gradle b/Ghidra/Framework/Gui/build.gradle new file mode 100644 index 0000000000..ffa550216e --- /dev/null +++ b/Ghidra/Framework/Gui/build.gradle @@ -0,0 +1,39 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import org.gradle.plugins.ide.eclipse.model.Container; + +apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" +apply from: "$rootProject.projectDir/gradle/javaProject.gradle" +apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" +apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" +apply from: "$rootProject.projectDir/gradle/javadoc.gradle" +apply plugin: 'eclipse' + +eclipse.project.name = 'Framework Gui' + +dependencies { + api project(':Generic') + api 'com.formdev:flatlaf:2.6' + + compileOnly "junit:junit:4.12" + + testImplementation project(path: ':Generic', configuration: 'testArtifacts') +} + +ext.addExports([ + 'java.desktop/sun.awt=ALL-UNNAMED' +]) + diff --git a/Ghidra/Framework/Gui/certification.manifest b/Ghidra/Framework/Gui/certification.manifest new file mode 100644 index 0000000000..ed9881a825 --- /dev/null +++ b/Ghidra/Framework/Gui/certification.manifest @@ -0,0 +1,9 @@ +##VERSION: 2.0 +##MODULE IP: Modified Nuvola Icons - LGPL 2.1 +##MODULE IP: Nuvola Icons - LGPL 2.1 +##MODULE IP: Oxygen Icons - LGPL 3.0 +##MODULE IP: Tango Icons - Public Domain +.classpath||GHIDRA||||END| +Module.manifest||GHIDRA||||END| +src/main/java/ghidra/framework/options/package.html||GHIDRA||||END| +src/main/java/ghidra/util/layout/package.html||GHIDRA||||END| diff --git a/Ghidra/Framework/Gui/src/main/java/generic/test/AbstractGuiTest.java b/Ghidra/Framework/Gui/src/main/java/generic/test/AbstractGuiTest.java new file mode 100644 index 0000000000..c65b176bca --- /dev/null +++ b/Ghidra/Framework/Gui/src/main/java/generic/test/AbstractGuiTest.java @@ -0,0 +1,1305 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package generic.test; + +import static org.junit.Assert.*; + +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.text.JTextComponent; +import javax.swing.tree.*; + +import org.junit.Assert; + +import ghidra.util.*; +import ghidra.util.datastruct.WeakSet; +import ghidra.util.exception.AssertException; +import ghidra.util.task.AbstractSwingUpdateManager; +import ghidra.util.task.SwingUpdateManager; +import junit.framework.AssertionFailedError; +import sun.awt.AppContext; +import utility.function.ExceptionalCallback; + +/** + * Base class for tests that need swing support methods. Tests that don't involve Swing/Gui elements + * should use AbstractGenericTest instead + */ +public class AbstractGuiTest extends AbstractGenericTest { + /** + * Gets all windows in the system (including Frames). + * + * @return all windows + */ + public static Set getAllWindows() { + Set set = new HashSet<>(); + Frame sharedOwnerFrame = (Frame) AppContext.getAppContext() + .get(new StringBuffer("SwingUtilities.sharedOwnerFrame")); + if (sharedOwnerFrame != null) { + set.addAll(getAllWindows(sharedOwnerFrame)); + } + + for (Frame frame : Frame.getFrames()) { + set.addAll(getAllWindows(frame)); + } + + Window[] windows = Window.getWindows(); + for (Window window : windows) { + set.add(window); + } + + return set; + } + + private static List getAllWindows(Window parent) { + List list = new ArrayList<>(); + list.add(parent); + for (Window w : parent.getOwnedWindows()) { + list.add(w); + } + return list; + } + + /** + * Waits for all system tasks to complete. These tasks are tracked by the + * SystemUtilities during testing only. + * + * @throws AssertionFailedError if the timeout period expires while waiting + * for tasks + */ + public static void waitForTasks() { + doWaitForTasks(PRIVATE_LONG_WAIT_TIMEOUT); + } + + private static void doWaitForTasks(long timeout) { + waitForSwing(); + + long time = 0; + while (TaskUtilities.isExecutingTasks()) { + time += sleep(DEFAULT_WAIT_DELAY); + if (time >= timeout) { + Msg.error(AbstractGenericTest.class, createStackTraceForAllThreads()); + throw new AssertionFailedError("Time expired waiting for tasks to complete."); + } + } + + // let any pending Swing work finish + waitForSwing(); + } + + // TODO deprecate this; at time of writing there are 1174 references; wait until it is + // a more reasonable number + // + // Update: 744 references at 12/1/19 + // Update: 559 references at 12/4/20 + public static void waitForPostedSwingRunnables() { + waitForSwing(); + } + + public static T findComponent(Container parent, Class desiredClass) { + return findComponent(parent, desiredClass, false); + } + + public static T findComponent(Container parent, Class desiredClass, + boolean checkOwnedWindows) { + Component[] comps = parent.getComponents(); + for (Component element : comps) { + if (element == null) { + continue;// this started happening in 1.6, not sure why + } + if (desiredClass.isAssignableFrom(element.getClass())) { + return desiredClass.cast(element); + } + else if (element instanceof Container) { + T c = findComponent((Container) element, desiredClass, checkOwnedWindows); + if (c != null) { + return desiredClass.cast(c); + } + } + } + if (checkOwnedWindows && (parent instanceof Window)) { + Window[] windows = ((Window) parent).getOwnedWindows(); + for (int i = windows.length - 1; i >= 0; i--) { + Component c = findComponent(windows[i], desiredClass, checkOwnedWindows); + if (c != null) { + return desiredClass.cast(c); + } + } + } + return null; + } + + public static List findComponents(Container parent, + Class desiredClass) { + return findComponents(parent, desiredClass, false); + } + + public static List findComponents(Container parent, + Class desiredClass, boolean checkOwnedWindows) { + Component[] comps = parent.getComponents(); + List list = new ArrayList<>(); + for (Component element : comps) { + if (element == null) { + continue;// this started happening in 1.6, not sure why + } + if (desiredClass.isAssignableFrom(element.getClass())) { + list.add(desiredClass.cast(element)); + } + else if (element instanceof Container) { + T c = findComponent((Container) element, desiredClass, checkOwnedWindows); + if (c != null) { + list.add(desiredClass.cast(c)); + } + } + } + if (checkOwnedWindows && (parent instanceof Window)) { + Window[] windows = ((Window) parent).getOwnedWindows(); + for (int i = windows.length - 1; i >= 0; i--) { + Component c = findComponent(windows[i], desiredClass, checkOwnedWindows); + if (c != null) { + list.add(desiredClass.cast(c)); + } + } + } + return list; + } + + public static void findOwnedWindows(Window win, Set winList) { + Window[] children = win.getOwnedWindows(); + for (Window element : children) { + winList.add(element); + findOwnedWindows(element, winList); + } + } + + /** + * Finds the button with the indicated TEXT that is a sub-component of the + * indicated container, and then programmatically presses the button.
+ * The following is a sample JUnit test use: + * + *

+	 * env.showTool();
+	 * OptionDialog dialog = (OptionDialog) env.waitForDialog(OptionDialog.class, 1000);
+	 * assertNotNull(dialog);
+	 * pressButtonByText(dialog, "OK");
+	 * 
+ * + * @param container the container to search. (Typically a dialog.) + * @param buttonText the text on the desired JButton. + * @throws AssertionError if the button isn't found, isn't showing or isn't + * enabled + */ + public static void pressButtonByText(Container container, String buttonText) { + pressButtonByText(container, buttonText, true); + } + + /** + * Finds the button with the indicated TEXT that is a sub-component of the + * indicated container, and then programmatically presses the button. + * + * @param container the container to search. (Typically a dialog.) + * @param buttonText the text on the desired JButton. + * @param waitForCompletion if true wait for action to complete before + * returning, otherwise schedule action to be performed and + * return immediately. + * @throws AssertionError if the button isn't found, isn't showing or isn't + * enabled + */ + public static void pressButtonByText(Container container, String buttonText, + boolean waitForCompletion) { + + AbstractButton button = findAbstractButtonByText(container, buttonText); + if (button == null) { + throw new AssertionError("Couldn't find button " + buttonText + "."); + } + if (!runSwing(() -> button.isShowing())) { + throw new AssertionError("Button " + buttonText + " is not showing."); + } + if (!runSwing(() -> button.isEnabled())) { + throw new AssertionError("Button " + buttonText + " is not enabled."); + } + pressButton(button, waitForCompletion); + } + + /** + * Finds the button with the indicated NAME that is a subcomponent of the + * indicated container, and then programmatically presses the button. + * + * @param container the container to search. (Typically a dialog) + * @param buttonName the name on the desired AbstractButton (see + * Component.setName()) + */ + public static void pressButtonByName(Container container, String buttonName) { + pressButtonByName(container, buttonName, true); + } + + /** + * Finds the button with the indicated NAME that is a subcomponent of the + * indicated container, and then programmatically presses the button. + * + * @param container the container to search. (Typically a dialog.) + * @param buttonName the name on the desired AbstractButton (see + * Component.setName()). + * @param waitForCompletion if true wait for action to complete before + * returning, otherwise schedule action to be performed and + * return immediately + */ + public static void pressButtonByName(Container container, String buttonName, + boolean waitForCompletion) { + + AbstractButton button = (AbstractButton) findComponentByName(container, buttonName); + if (button == null) { + throw new AssertionError("Couldn't find button " + buttonName + "."); + } + if (!runSwing(() -> button.isShowing())) { + throw new AssertionError("Button " + buttonName + " is not showing."); + } + if (!runSwing(() -> button.isEnabled())) { + throw new AssertionError("Button " + buttonName + " is not enabled."); + } + pressButton(button, waitForCompletion); + } + + /** + * Programmatically presses the indicated button. + * + * @param button the button + */ + public static void pressButton(AbstractButton button) { + if (!button.isEnabled()) { + throw new AssertException("Attempted to press a disabled button"); + } + pressButton(button, true); + } + + /** + * Programmatically presses the indicated button. + * + * @param button the button + * @param waitForCompletion if true wait for action to complete before + * returning, otherwise schedule action to be performed and + * return immediately. + */ + public static void pressButton(AbstractButton button, boolean waitForCompletion) { + Runnable r = () -> button.doClick(0); // 0 means no sleeping + runSwing(r, waitForCompletion); + } + + /** + * Searches the subcomponents of the indicated container and returns the + * component with the specified name. + * + * @param container the container to search + * @param componentName the name of the desired component + * + * @return the component, or null if not found + */ + public static Component findComponentByName(Container container, String componentName) { + return findComponentByName(container, componentName, false); + } + + public static Component findComponentByName(Container container, String componentName, + boolean checkOwnedWindows) { + + String containerName = container.getName(); + + if (containerName != null && container.getName().equals(componentName)) { + return container; + } + + Component[] comps = container.getComponents(); + for (Component element : comps) { + if (element == null) { + continue;// this started happening in 1.6, not sure why + } + String name = element.getName(); + if (name != null && name.equals(componentName)) { + return element; + } + else if (element instanceof Container) { + Component comp = + findComponentByName((Container) element, componentName, checkOwnedWindows); + if (comp != null) { + return comp; + } + } + } + if (checkOwnedWindows && (container instanceof Window)) { + Window[] windows = ((Window) container).getOwnedWindows(); + for (int i = windows.length - 1; i >= 0; i--) { + Component c = findComponentByName(windows[i], componentName, checkOwnedWindows); + if (c != null) { + return c; + } + } + } + return null; + } + + public static List findComponentsByName(Container container, String componentName, + boolean checkOwnedWindows) { + + List retList = new ArrayList<>(); + + Component[] components = container.getComponents(); + for (Component component : components) { + if (component == null) { + continue; + } + String name = component.getName(); + if (name != null && name.equals(componentName)) { + retList.add(component); + } + else if (component instanceof Container) { + retList.addAll( + findComponentsByName((Container) component, componentName, checkOwnedWindows)); + } + + } + return retList; + } + + public static JButton findButtonByIcon(Container container, Icon icon) { + Component[] comps = container.getComponents(); + for (Component element : comps) { + if (element instanceof JButton) { + JButton button = (JButton) element; + Icon buttonIcon = button.getIcon(); + if (icon.equals(buttonIcon)) { + return button; + } + } + else if (element instanceof Container) { + JButton button = findButtonByIcon((Container) element, icon); + if (button != null) { + return button; + } + } + } + return null; + + } + + /** + * Searches the subcomponents of the the given container and returns the + * JButton that has the specified text. + * + * @param container the container to search + * @param text the button text + * @return the JButton, or null the button was not found + */ + public static JButton findButtonByText(Container container, String text) { + Component[] comps = container.getComponents(); + for (Component element : comps) { + if (element instanceof JButton) { + JButton button = (JButton) element; + if (button.getText() != null && button.getText().equals(text)) { + return button; + } + } + else if (element instanceof Container) { + JButton button = findButtonByText((Container) element, text); + if (button != null) { + return button; + } + } + } + return null; + } + + /** + * Searches the sub-components of the given container and returns the + * AbstractButton that has the specified text. + *

+ * This differs from {@link #findButtonByText(Container, String)} in that + * this method will find buttons that do not extend from {@link JButton}. + * That method is convenient when you do not wish to cast the result from + * AbstractButton to JButton. Other than that, this method can handle all + * cases the other method cannot. + * + * @param container container to search + * @param text button text + * @return null if the button was not found + */ + public static AbstractButton findAbstractButtonByText(Container container, String text) { + + Component[] comp = container.getComponents(); + for (Component element : comp) { + if ((element instanceof AbstractButton) && + text.equals(((AbstractButton) element).getText())) { + return (AbstractButton) element; + } + else if (element instanceof Container) { + AbstractButton b = findAbstractButtonByText((Container) element, text); + if (b != null) { + return b; + } + } + } + return null; + } + + /** + * Searches the sub-components of the given container and returns the + * AbstractButton that has the specified name. + * + * @param container container to search + * @param name the button name (you must set this manually). + * @return null if the button was not found + */ + public static AbstractButton findAbstractButtonByName(Container container, String name) { + + Component[] comp = container.getComponents(); + for (Component element : comp) { + if ((element instanceof AbstractButton) && + name.equals(((AbstractButton) element).getName())) { + return (AbstractButton) element; + } + else if (element instanceof Container) { + AbstractButton b = findAbstractButtonByName((Container) element, name); + if (b != null) { + return b; + } + } + } + return null; + } + + public static void leftClick(JComponent comp, int x, int y) { + clickMouse(comp, MouseEvent.BUTTON1, x, y, 1, 0); + } + + public static void middleClick(JComponent comp, int x, int y) { + clickMouse(comp, MouseEvent.BUTTON2, x, y, 1, 0); + } + + public static void rightClick(JComponent comp, int x, int y) { + clickMouse(comp, MouseEvent.BUTTON3, x, y, 1, 0, true); + } + + public static void doubleClick(JComponent comp, int x, int y) { + clickMouse(comp, MouseEvent.BUTTON1, x, y, 2, 0); + } + + /** + * Simulates click the mouse button. + * + * @param comp the component to click on. + * @param button the mouse button (1, 2, or 3) + * @param x the x coordinate of the click location + * @param y the y coordinate of the click location + * @param clickCount the number of clicks (2 = double click) + * @param modifiers additional modifiers (e.g. MouseEvent.SHIFT_MASK) + * @param popupTrigger a boolean, true if this event is a trigger for a + * popup menu + */ + public static void clickMouse(Component comp, int button, int x, int y, int clickCount, + int modifiers, boolean popupTrigger) { + + int nonRelesedModifiers = convertToExtendedModifiers(modifiers, button, false); + int relesedModifiers = convertToExtendedModifiers(modifiers, button, true); + for (int cnt = 1; cnt <= clickCount; ++cnt) { + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), + nonRelesedModifiers, x, y, cnt, false, button)); + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), + nonRelesedModifiers, x, y, cnt, false, button)); + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), + relesedModifiers, x, y, cnt, popupTrigger, button)); + } + } + + /** + * Simulates click the mouse button. + * + * @param comp the component to click on. + * @param button the mouse button (1, 2, or 3) + * @param x the x coordinate of the click location + * @param y the y coordinate of the click location + * @param clickCount the number of clicks (2 = double click) + * @param modifiers additional modifiers (e.g. MouseEvent.SHIFT_MASK) + */ + public static void clickMouse(Component comp, int button, int x, int y, int clickCount, + int modifiers) { + + clickMouse(comp, button, x, y, clickCount, modifiers, false); + } + + /** + * Simulates a mouse drag action + * + * @param comp the component to drag on. + * @param button the mouse button (1, 2, or 3) + * @param startX the x coordinate of the start drag location + * @param startY the y coordinate of the start drag location + * @param endX the x coordinate of the end drag location + * @param endY the y coordinate of the end drag location + * @param modifiers additional modifiers (e.g. MouseEvent.SHIFT_MASK) + */ + public static void dragMouse(final Component comp, int button, final int startX, + final int startY, final int endX, final int endY, int modifiers) { + + int nonRelesedModifiers = convertToExtendedModifiers(modifiers, button, false); + int relesedModifiers = convertToExtendedModifiers(modifiers, button, true); + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), + nonRelesedModifiers, startX, startY, 1, false, button)); + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_DRAGGED, System.currentTimeMillis(), + nonRelesedModifiers, endX, endY, 1, false, button)); + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), + relesedModifiers, endX, endY, 1, false, button)); + + } + + /** + * Fire a mouse moved event for the given component. + * + * @param comp source of the event. + * @param x x position relative to the component + * @param y y position relative to the component + */ + public static void moveMouse(Component comp, int x, int y) { + postEvent(new MouseEvent(comp, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(), 0, x, y, + 0, false)); + + } + + @SuppressWarnings("deprecation") + private static int convertToExtendedModifiers(int modifiers, int button, boolean isRelease) { + + // TODO: Eliminate duplication of similar modifier modification logic + // which exists in KeyBindingData + + // remove system-dependent control key mask and transform deprecated modifiers + + int controlMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); + + if ((modifiers & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK) { + modifiers = modifiers ^ InputEvent.CTRL_DOWN_MASK; + modifiers = modifiers | controlMask; + } + + if ((modifiers & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) { + modifiers = modifiers ^ InputEvent.CTRL_MASK; + modifiers = modifiers | controlMask; + } + + if ((modifiers & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) { + modifiers = modifiers ^ ActionEvent.CTRL_MASK; + modifiers = modifiers | controlMask; + } + + if ((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) { + modifiers = modifiers ^ InputEvent.SHIFT_MASK; + modifiers = modifiers | InputEvent.SHIFT_DOWN_MASK; + } + + if ((modifiers & InputEvent.ALT_MASK) == InputEvent.ALT_MASK) { + modifiers = modifiers ^ InputEvent.ALT_MASK; + modifiers = modifiers | InputEvent.ALT_DOWN_MASK; + } + + if ((modifiers & InputEvent.META_MASK) == InputEvent.META_MASK) { + modifiers = modifiers ^ InputEvent.META_MASK; + modifiers = modifiers | InputEvent.META_DOWN_MASK; + } + + if (!isRelease) { + // + // There are no mouse buttons down on a 'release' in Java's extended event processing. + // (The original non-extended events did include the button in the release event.) + // + switch (button) { + case 1: + modifiers |= InputEvent.BUTTON1_DOWN_MASK; + break; + case 2: + modifiers |= InputEvent.BUTTON2_DOWN_MASK; + break; + case 3: + modifiers |= InputEvent.BUTTON3_DOWN_MASK; + break; + } + } + return modifiers; + } + + public static void postEvent(final AWTEvent ev) { + runSwing(() -> { + EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + eq.postEvent(ev); + }); + waitForSwing(); + } + + /** + * Returns the value from the given {@link Supplier}, invoking the call in + * the Swing thread. This is useful when you may have values that are being + * changed on the Swing thread and you need the test thread to see the + * changes. + * + * @param s the supplier + * @return the value returned by the supplier + */ + public static T runSwing(Supplier s) { + AtomicReference ref = new AtomicReference<>(); + runSwing(() -> ref.set(s.get())); + return ref.get(); + } + + /** + * Run the given code snippet on the Swing thread and wait for it to finish + * @param r the runnable code snippet + */ + public static void runSwing(Runnable r) { + runSwing(r, true); + } + + /** + * Run the given code snippet on the Swing thread later, not blocking the current thread. Use + * this if the code snippet causes a blocking operation. + * + *

This is a shortcut for runSwing(r, false);. + * + * @param r the runnable code snippet + */ + public void runSwingLater(Runnable r) { + runSwing(r, false); + } + + /** + * Call this version of {@link #runSwing(Runnable)} when you expect your runnable may + * throw exceptions + * + * @param callback the runnable code snippet to call + * @throws Exception any exception that is thrown on the Swing thread + */ + public static void runSwingWithException(ExceptionalCallback callback) + throws Exception { + + if (Swing.isSwingThread()) { + throw new AssertException("Unexpectedly called from the Swing thread"); + } + + ExceptionHandlingRunner exceptionHandlingRunner = new ExceptionHandlingRunner(callback); + Throwable throwable = exceptionHandlingRunner.getException(); + if (throwable == null) { + return; + } + + if (throwable instanceof Exception) { + // this is what the client expected + throw (Exception) throwable; + } + + // a runtime exception; re-throw + throw new AssertException(throwable); + } + + public static void runSwing(Runnable runnable, boolean wait) { + + // + // Special Case: this check handled re-entrant test code. That is, an calls to runSwing() + // that are made from within a runSwing() call. Most clients do not do + // this, but it can happen when a client makes a test API call (which itself + // calls runSwing()) from within a runSwing() call. + // + // Calling the run method directly here ensures that the order of client + // requests is preserved. + // + if (SwingUtilities.isEventDispatchThread()) { + runnable.run(); + return; + } + + if (wait) { + runSwingAndWait(runnable); + return; + } + + // don't wait; invoke later; catch any exceptions ourselves in order to fail-fast + Runnable swingExceptionCatcher = () -> { + try { + runnable.run(); + } + catch (Throwable t) { + // submit this failure directly to the handler; fail the test + ConcurrentTestExceptionHandler.handle(Thread.currentThread(), t); + } + }; + + SwingUtilities.invokeLater(swingExceptionCatcher); + } + + protected static class ExceptionHandlingRunner { + private final ExceptionalCallback delegateCallback; + private Throwable exception; + + ExceptionHandlingRunner(Runnable delegateRunnable) { + this.delegateCallback = () -> { + delegateRunnable.run(); + }; + run(); + } + + ExceptionHandlingRunner(ExceptionalCallback delegateCallback) { + this.delegateCallback = delegateCallback; + run(); + } + + Throwable getException() { + return exception; + } + + String getExceptionMessage() { + Throwable throwable = getException(); + String message = throwable.getMessage(); + if (message != null) { + return message; + } + + return getCauseExceptionMessage(throwable); + } + + protected String getCauseExceptionMessage(Throwable t) { + if (t == null) { + return ""; + } + + if (t instanceof AssertionError) { + return t.getMessage(); + } + + String message = t.getMessage(); + if (message != null) { + return message; + } + + return getCauseExceptionMessage(t.getCause()); + } + + private void run() { + + Runnable swingExceptionCatcher = () -> { + try { + delegateCallback.call(); + } + catch (Throwable t) { + exception = t; + } + }; + + try { + doRun(swingExceptionCatcher); + } + catch (InterruptedException e) { + // Typically, this InterrruptedException that is caused by our test harness when it + // is interrupting the test thread after a previous Swing exception that we have + // detected--we don't care to throw the InterruptedException, as we caused it. + // Log a message to signal that unusual things may happen when in this state. + Msg.debug(this, "\n>>>>>>>>>>>>>>>> Test thread interrupted. Unusual/unexpected " + + "errors may follow.\n\n"); + } + catch (InvocationTargetException e) { + // Assume that if we have an exception reported by our catcher above, then that is + // the root cause of this exception and do not report this one. This should not + // happen, as we are catching the exception above. + } + } + + private void doRun(Runnable runnable) + throws InvocationTargetException, InterruptedException { + if (SwingUtilities.isEventDispatchThread()) { + runnable.run(); + } + else { + SwingUtilities.invokeAndWait(runnable); + } + } + } + + private static void runSwingAndWait(Runnable runnable) { + ExceptionHandlingRunner exceptionHandlingRunner = new ExceptionHandlingRunner(runnable); + + Throwable throwable = exceptionHandlingRunner.getException(); + if (throwable == null) { + return; + } + + // + // Handle the exception + // + if (!TestThread.isTestThread()) { + // we have plumbing that checks for this in headed environments + ConcurrentTestExceptionHandler.handle(Thread.currentThread(), throwable); + return; + } + + // + // When not in batch mode, Eclipse and Gradle will show the exception we build here, + // which is the most helpful. + // + String message = "Exception in Swing thread via runSwingAndWait():"; + if (!BATCH_MODE) { + TestReportingException exception = + TestReportingException.fromSwingThread(message, throwable); + throw exception; + } + + // + // When running in batch mode, the report generated by Gradle will not correctly show + // the stack trace if we throw the exception, so will will trigger a failure instead, + // which looks good in the test report. + // + String string = TestReportingException.getSwingThreadTraceString(throwable); + Assert.fail(message + "\n" + string + "\nTest Thread stack at that time:"); + } + + /** + * Launches the runnable on a new thread so as to not block the calling + * thread. This is very useful for performing actions on the Swing thread + * that show modal dialogs, which would otherwise block the calling thread, + * such as a testing thread. + * + * @param runnable The runnable that will be executed in a new Thread that + * will place the runnable on the Swing thread. + */ + public static void executeOnSwingWithoutBlocking(Runnable runnable) { + + AtomicBoolean didRun = new AtomicBoolean(); + (new Thread() { + @Override + public void run() { + didRun.set(true); + runSwing(runnable); + } + }).start(); + + // we can make this call, since any potential modal dialogs are not blocking in the Swing + // thread, but in the new event queue created by the modal dialog (this is how repainting + // still works when a modal dialog is shown) + waitForSwing(); + + waitForCondition(() -> didRun.get()); + + // pause a bit to let the swing thread process + sleep(DEFAULT_WAIT_DELAY); + + // make sure any pending Swing events have been processed + waitForSwing(); + } + + public static void clickTableCell(final JTable table, final int row, final int col, + int clickCount) { + runSwing(() -> table.setRowSelectionInterval(row, row)); + waitForSwing(); + Rectangle rect = table.getCellRect(row, col, true); + clickMouse(table, MouseEvent.BUTTON1, rect.x + 10, rect.y + 10, clickCount, 0); + waitForSwing(); + } + + /** + * Clicks a range of items in a list (simulates holding SHIFT and selecting + * each item in the range in-turn) + * + * @param list the list to select from + * @param row the initial index + * @param count the number of rows to select + */ + public static void clickListRange(final JList list, final int row, int count) { + waitForSwing(); + for (int i = row; i < row + count; i++) { + Rectangle rect = list.getCellBounds(i, i); + clickMouse(list, MouseEvent.BUTTON1, rect.x + 10, rect.y + 10, 1, + InputEvent.SHIFT_DOWN_MASK); + } + waitForSwing(); + } + + /** + * Clicks a range of items in a table (simulates holding SHIFT and selecting + * each item in the range) + * + * @param table the table to select + * @param row the starting row index + * @param count the number of rows to select + */ + public static void clickTableRange(final JTable table, final int row, int count) { + waitForSwing(); + for (int i = row; i < row + count; i++) { + Rectangle rect = table.getCellRect(i, 0, true); + clickMouse(table, MouseEvent.BUTTON1, rect.x + 10, rect.y + 10, 1, + InputEvent.SHIFT_DOWN_MASK); + } + waitForSwing(); + } + + public static TableCellEditor editCell(final JTable table, final int row, final int col) { + + waitForSwing(); + + runSwing(() -> table.setRowSelectionInterval(row, row)); + waitForSwing(); + + runSwing(() -> table.editCellAt(row, col)); + waitForSwing(); + + TableCellEditor editor = table.getCellEditor(row, col); + assertNotNull("Unable to edit table cell at " + row + ", " + col, editor); + return editor; + } + + /** + * Gets the rendered value for the specified table cell. The actual value at the cell may + * not be a String. This method will get the String display value, as created by the table. + * + * @param table the table to query + * @param row the row to query + * @param column the column to query + * @return the String value + * @throws IllegalArgumentException if there is no renderer or the rendered component is + * something from which this method can get a String (such as a JLabel) + */ + public static String getRenderedTableCellValue(JTable table, int row, int column) { + + return runSwing(() -> { + + TableCellRenderer renderer = table.getCellRenderer(row, column); + if (renderer == null) { + throw new IllegalArgumentException( + "No renderer registered for row/col: " + row + '/' + column); + } + Component component = table.prepareRenderer(renderer, row, column); + if (!(component instanceof JLabel)) { + throw new IllegalArgumentException( + "Do not know how to get text from a renderer " + "that is not a JLabel"); + } + + return ((JLabel) component).getText(); + }); + } + + public static void setComboBoxSelection(final JComboBox comboField, final T selection) { + runSwing(() -> comboField.setSelectedItem(selection)); + waitForSwing(); + } + + public static void setText(final JTextComponent field, final String text) { + runSwing(() -> field.setText(text)); + waitForSwing(); + } + + public static String getText(final JTextComponent field) { + return runSwing(() -> field.getText()); + } + + /** + * Finds the path of a tree node in the indicated tree with the specified + * text. The matching tree node is determined by comparing the specified + * text with the string returned by the tree node's toString() method.
+ * Note: This method affects the expansion state of the tree. It will expand + * nodes starting at the root until a match is found or all of the tree is + * checked. + * + * @param tree the tree + * @param text the tree node's text + * @return the tree path + */ + public static TreePath findTreePathToText(JTree tree, String text) { + TreeModel tm = tree.getModel(); + TreeNode rootNode = (TreeNode) tm.getRoot(); + TreePath rootPath = new TreePath(rootNode); + return findPathToText(tree, rootPath, text); + } + + /** + * Performs a depth first search for the named tree node. + * + * @param tree the tree to search + * @param startTreePath path indicating node to begin searching from in the + * tree + * @param text the name of the node to find + * @return the path to the named node or null if it can't be found. + */ + protected static TreePath findPathToText(JTree tree, TreePath startTreePath, String text) { + if (text.equals(startTreePath.getLastPathComponent().toString())) { + return startTreePath; + } + tree.expandPath(startTreePath); + int len = startTreePath.getPathCount(); + Object[] tpObjects = new Object[len + 1]; + System.arraycopy(startTreePath.getPath(), 0, tpObjects, 0, len); + TreeNode treeNode = (TreeNode) startTreePath.getLastPathComponent(); + int num = treeNode.getChildCount(); + for (int i = 0; i < num; i++) { + TreeNode childNode = treeNode.getChildAt(i); + tpObjects[len] = childNode; + TreePath childPath = new TreePath(tpObjects); + TreePath treePath = findPathToText(tree, childPath, text); + if (treePath != null) { + return treePath; + } + } + return null; + } + + /** + * Invoke fixupGUI at the beginning of your JUnit test or in + * its setup() method to make your GUI for the JUnit test appear using the + * system Look and Feel. The system look and feel is the default that Ghidra + * uses. This will also change the default fonts for the JUnit test to be + * the same as those in Ghidra. + * + * @exception InterruptedException if we're interrupted while waiting for + * the event dispatching thread to finish excecuting + * doRun.run() + * @exception InvocationTargetException if an exception is thrown while + * running doRun + */ + public static void fixupGUI() throws InterruptedException, InvocationTargetException { + // Make the test look & feel as it would normally. + SwingUtilities.invokeAndWait(() -> { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } + catch (ClassNotFoundException e1) { + // don't care + } + catch (InstantiationException e2) { + // don't care + } + catch (IllegalAccessException e3) { + // don't care + } + catch (UnsupportedLookAndFeelException e4) { + // don't care + } + }); + // Fix up the default fonts that Java 1.5.0 changed to Courier, which looked terrible. + Font f = new Font("monospaced", Font.PLAIN, 12); + UIManager.put("PasswordField.font", f); + UIManager.put("TextArea.font", f); + } + + /** + * Asserts that the two colors have the same rgb values (handles GColor) + * @param expected the expected color + * @param actual the actual color + */ + public void assertColorsEqual(Color expected, Color actual) { + if (expected.getRGB() == actual.getRGB()) { + return; + } + fail("Expected: [" + expected.getClass().getSimpleName() + "]" + expected + + ", but got: [" + actual.getClass().getSimpleName() + "]" + actual); + } + + public static void printMemory() { + yieldToSwing(); + System.gc(); + yieldToSwing(); + System.gc(); + yieldToSwing(); + System.gc(); + + Runtime runTime = Runtime.getRuntime(); + System.out.println("----------------------"); + System.out.printf("Max: %,10dK\n", runTime.maxMemory() / 1000); + System.out.printf("Total: %,10dK\n", runTime.totalMemory() / 1000); + System.out.printf("Free: %,10dK\n", runTime.freeMemory() / 1000); + System.out.printf("Used: %,10dK\n", + ((runTime.totalMemory() - runTime.freeMemory()) / 1000)); + } + +//================================================================================================== +// Swing Methods +//================================================================================================== + + /** + * Waits for the Swing thread to process any pending events. This method + * also waits for any {@link SwingUpdateManager}s that have pending events + * to be flushed. + * + * @return true if the any {@link SwingUpdateManager}s were busy. + */ + public static boolean waitForSwing() { + if (SwingUtilities.isEventDispatchThread()) { + throw new AssertException("Can't wait for swing from within the swing thread!"); + } + + Set set = new HashSet<>(); + runSwing(() -> { + @SuppressWarnings("unchecked") + WeakSet s = + (WeakSet) getInstanceField("instances", + SwingUpdateManager.class); + for (AbstractSwingUpdateManager manager : s) { + set.add(manager); + } + }); + + /* + long start = System.nanoTime(); + boolean wasEverBusy = waitForSwing(set, true); + long end = System.nanoTime(); + Msg.out("\twaitForSwing() - " + + TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS)); + */ + + boolean wasEverBusy = waitForSwing(set, true); + return wasEverBusy; + } + + private static boolean waitForSwing(Set managers, boolean flush) { + + // Note: not sure how long is too long to wait for the Swing thread and update managers + // to finish. This is usually less than a second. We have seen a degenerate + // case where this took minutes. This method is called often, so don't wait too + // long. This will have to be changed through trial-and-error. + int MAX_SWING_TIMEOUT = 15000; + int totalTime = 0; + + // flush all managers up front to get them started before we check them + flushAllManagers(managers, flush); + + boolean wasEverBusy = false; + boolean keepGoing = true; + while (keepGoing) { + + // let swing paint and maybe schedule more work on the update managers + yieldToSwing(); + keepGoing = false; + + for (AbstractSwingUpdateManager manager : managers) { + + if (!manager.isBusy()) { + // no current or pending work + continue; + } + + // Msg.out("busy manager: " + manager.toStringDebug()); + + doFlush(flush, manager); + + boolean isBusy = true; + while (isBusy) { + + keepGoing = true; // true, since we had a busy signal + wasEverBusy = true; + + totalTime += sleep(DEFAULT_WAIT_DELAY); + if (totalTime >= MAX_SWING_TIMEOUT) { + // eject! + Msg.debug(AbstractGenericTest.class, + "Timed-out waitinig for Swing after " + totalTime + " ms. " + + "The currently waited SwingUpdateManager:\n" + + manager.toStringDebug()); + return true; + } + + isBusy = manager.isBusy(); + } + } + // let any resulting swing events finish + yieldToSwing(); + } + + return wasEverBusy; + } + + private static void flushAllManagers(Set managers, boolean flush) { + + // + // Some update managers will make an update that causes another manager to schedule an + // update. In order to *not* have to wait for each of these, one-at-a-time, loop a + // few times so that any follow-up scheduling events will be executed as well. These + // calls all execute in the Swing thread in a blocking fashion, so when we are done + // flushing, there should be no more work scheduled due to us flushing. Due to other + // potential background threads though, more work may be scheduled as we are working. + // Thus, for fast tests, you should not have background work happening that is not + // directly related to your code being tested. + // + + // arbitrary; we have at least one level of a manager triggering another manager, + // which would be 2 + int n = 3; + for (int i = 0; i < n; i++) { + for (AbstractSwingUpdateManager manager : managers) { + doFlush(flush, manager); + } + } + } + + private static void doFlush(boolean doFlush, AbstractSwingUpdateManager manager) { + if (!doFlush) { + return; + } + + runSwing(() -> { + manager.flush(); + }, false); + yieldToSwing(); + } + + /** + * This is only for internal use. If you need to wait for the Swing thread + * from your test, then use {@link #waitForSwing()}. + * + * @deprecated This is not a test writer's method, but instead an + * infrastructure method. + */ + @Deprecated + public static void privateWaitForPostedSwingRunnables_SwingSafe() { + yieldToSwing(); + } + + protected static void yieldToSwing() { + + if (SwingUtilities.isEventDispatchThread()) { + Msg.error(AbstractGenericTest.class, + "Incorrectly called yieldToSwing() from the Swing thread"); + return; // shouldn't happen + } + + Runnable empty = () -> { + // do nothing...this is just a placeholder runnable that gets put onto the stack + }; + + // + // Note: the calls below are designed to ignore being interrupted. Further, if one of + // the calls is interrupted, the others will still work as expected. + // + for (int i = 0; i < 3; i++) { + try { + SwingUtilities.invokeAndWait(empty); + } + catch (Exception e) { + // Assumption: since our runnable is empty, this can only an interrupted + // exception, which can happen if our test framework decides to + // shut the operation down. + return; + } + } + } + +} diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/AbstractThemeReader.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/AbstractThemeReader.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/AbstractThemeReader.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/AbstractThemeReader.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/AllValuesChangedThemeEvent.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/AllValuesChangedThemeEvent.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/AllValuesChangedThemeEvent.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/AllValuesChangedThemeEvent.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ApplicationThemeDefaultsProvider.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeDefaultsProvider.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ApplicationThemeDefaultsProvider.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeDefaultsProvider.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ApplicationThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ApplicationThemeManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorChangedThemeEvent.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ColorChangedThemeEvent.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ColorChangedThemeEvent.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ColorChangedThemeEvent.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ColorValue.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ColorValue.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ColorValue.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/DiscoverableGTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/DiscoverableGTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/DiscoverableGTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/DiscoverableGTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontChangedThemeEvent.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/FontChangedThemeEvent.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/FontChangedThemeEvent.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/FontChangedThemeEvent.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontModifier.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/FontModifier.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/FontModifier.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/FontModifier.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/FontValue.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/FontValue.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/FontValue.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GColor.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GColor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GColor.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GColor.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GColorUIResource.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GColorUIResource.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GColorUIResource.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GColorUIResource.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GIcon.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GIcon.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GIconUIResource.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GIconUIResource.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GIconUIResource.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GIconUIResource.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeDefaults.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeDefaults.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeValueMap.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeValueMap.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeValueMap.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeValueMap.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/Gui.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/Gui.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/Gui.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/Gui.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/HeadlessThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/HeadlessThemeManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/HeadlessThemeManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/HeadlessThemeManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconChangedThemeEvent.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/IconChangedThemeEvent.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/IconChangedThemeEvent.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/IconChangedThemeEvent.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconModifier.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/IconModifier.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/IconModifier.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/IconModifier.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/IconValue.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/IconValue.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/IconValue.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/LafType.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/LafType.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/LafType.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/LafType.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/StubThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/StubThemeManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/StubThemeManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/StubThemeManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeDefaultsProvider.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeDefaultsProvider.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeDefaultsProvider.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeDefaultsProvider.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeEvent.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeEvent.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeEvent.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeEvent.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeListener.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeListener.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeListener.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeListener.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemePreferences.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePreferences.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemePreferences.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePreferences.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemePropertyFileReader.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePropertyFileReader.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemePropertyFileReader.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePropertyFileReader.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeReader.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeReader.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeValue.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValue.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeValue.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValueUtils.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeValueUtils.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeValueUtils.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeValueUtils.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeWriter.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeWriter.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/ThemeWriter.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeWriter.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/CDEMotifTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/CDEMotifTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/CDEMotifTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/CDEMotifTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/FlatDarkTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/FlatDarkTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/FlatDarkTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/FlatDarkTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/FlatLightTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/FlatLightTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/FlatLightTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/FlatLightTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/GTKTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/GTKTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/GTKTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/GTKTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/MacTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/MacTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/MacTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/MacTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/MetalTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/MetalTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/MetalTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/MetalTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/NimbusTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/NimbusTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/NimbusTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/NimbusTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/WindowsClassicTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/WindowsClassicTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/WindowsClassicTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/WindowsClassicTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/WindowsTheme.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/WindowsTheme.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/builtin/WindowsTheme.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/builtin/WindowsTheme.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ComponentFontRegistry.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ComponentFontRegistry.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/FlatLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/FlatLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/FlatLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/FlatLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/FlatThemeGrouper.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/FlatThemeGrouper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/FlatThemeGrouper.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/FlatThemeGrouper.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/FontNonUiResource.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/FontNonUiResource.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/FontNonUiResource.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/FontNonUiResource.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/GNimbusLookAndFeel.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/GNimbusLookAndFeel.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/GNimbusLookAndFeel.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/GNimbusLookAndFeel.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/GtkLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/GtkLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/GtkLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/GtkLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/LookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/LookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MacLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MacLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MacLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MacLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MacThemeGrouper.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MacThemeGrouper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MacThemeGrouper.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MacThemeGrouper.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MetalLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MetalLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MetalLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MetalLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MotifLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MotifLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MotifLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MotifLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MotifThemeGrouper.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MotifThemeGrouper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/MotifThemeGrouper.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/MotifThemeGrouper.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/NimbusLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusThemeGrouper.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/NimbusThemeGrouper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/NimbusThemeGrouper.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/NimbusThemeGrouper.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ThemeGrouper.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ThemeGrouper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/ThemeGrouper.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ThemeGrouper.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/WindowsClassicLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/WindowsClassicLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/WindowsClassicLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/WindowsClassicLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/WindowsLookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/WindowsLookAndFeelManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/WindowsLookAndFeelManager.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/WindowsLookAndFeelManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/laf/nimbus/SelectedTreePainter.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/nimbus/SelectedTreePainter.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/theme/laf/nimbus/SelectedTreePainter.java rename to Ghidra/Framework/Gui/src/main/java/generic/theme/laf/nimbus/SelectedTreePainter.java diff --git a/Ghidra/Framework/Generic/src/main/java/generic/util/image/ImageUtils.java b/Ghidra/Framework/Gui/src/main/java/generic/util/image/ImageUtils.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/generic/util/image/ImageUtils.java rename to Ghidra/Framework/Gui/src/main/java/generic/util/image/ImageUtils.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/SwingExceptionHandler.java b/Ghidra/Framework/Gui/src/main/java/ghidra/SwingExceptionHandler.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/SwingExceptionHandler.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/SwingExceptionHandler.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/AbstractOptions.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/AbstractOptions.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/AbstractOptions.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOption.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/CustomOption.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOption.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/CustomOption.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOptionsEditor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/CustomOptionsEditor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/CustomOptionsEditor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/CustomOptionsEditor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorState.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/EditorState.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorState.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/EditorState.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorStateFactory.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/EditorStateFactory.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EditorStateFactory.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/EditorStateFactory.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EnumEditor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/EnumEditor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/EnumEditor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/EnumEditor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ErrorPropertyEditor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ErrorPropertyEditor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ErrorPropertyEditor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ErrorPropertyEditor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/FileOptions.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/FileOptions.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/FileOptions.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/FileOptions.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/NoRegisteredEditorPropertyEditor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/NoRegisteredEditorPropertyEditor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/NoRegisteredEditorPropertyEditor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/NoRegisteredEditorPropertyEditor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Option.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Option.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Option.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Option.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/OptionType.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/OptionType.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/OptionType.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/OptionType.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Options.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Options.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/Options.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/Options.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/OptionsChangeListener.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/OptionsChangeListener.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/OptionsChangeListener.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/OptionsChangeListener.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/OptionsEditor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/OptionsEditor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/OptionsEditor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/OptionsEditor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PreferenceState.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PreferenceState.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PreferenceState.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PreferenceState.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PropertyBoolean.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PropertyBoolean.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PropertyBoolean.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PropertyBoolean.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PropertySelector.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PropertySelector.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PropertySelector.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PropertySelector.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PropertyText.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PropertyText.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/PropertyText.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/PropertyText.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/SaveState.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SaveState.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/SaveState.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SaveState.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/SubOptions.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SubOptions.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/SubOptions.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/SubOptions.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeColorOption.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ThemeColorOption.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeColorOption.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ThemeColorOption.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeFontOption.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ThemeFontOption.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ThemeFontOption.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ThemeFontOption.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ToolOptions.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/ToolOptions.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/ToolOptions.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedColor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedColor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedColor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedColor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedCustomOption.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedCustomOption.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedCustomOption.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedCustomOption.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedDate.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedDate.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedDate.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedDate.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedFile.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedFile.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedFile.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedFile.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedFont.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedFont.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedFont.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedFont.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedKeyStroke.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedKeyStroke.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedKeyStroke.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedKeyStroke.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedOption.java b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedOption.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/WrappedOption.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/WrappedOption.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/package.html b/Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/package.html similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/framework/options/package.html rename to Ghidra/Framework/Gui/src/main/java/ghidra/framework/options/package.html diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/test/ScriptTaskListener.java b/Ghidra/Framework/Gui/src/main/java/ghidra/test/ScriptTaskListener.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/test/ScriptTaskListener.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/test/ScriptTaskListener.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/ColorUtils.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/ColorUtils.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/ColorUtils.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/ColorUtils.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/HTMLUtilities.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/HTMLUtilities.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/HelpLocation.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/HelpLocation.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/HelpLocation.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/HelpLocation.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/TaskUtilities.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/TaskUtilities.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/TaskUtilities.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/TaskUtilities.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/TrackedTaskListener.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/TrackedTaskListener.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/TrackedTaskListener.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/TrackedTaskListener.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/WebColors.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/WebColors.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/WebColors.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/WebColors.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/bean/GGlassPane.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/bean/GGlassPane.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/bean/GGlassPane.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/bean/GGlassPane.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/bean/GGlassPanePainter.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/bean/GGlassPanePainter.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/bean/GGlassPanePainter.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/bean/GGlassPanePainter.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/bean/opteditor/OptionsVetoException.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/bean/opteditor/OptionsVetoException.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/bean/opteditor/OptionsVetoException.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/bean/opteditor/OptionsVetoException.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/filechooser/ExtensionFileFilter.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/filechooser/ExtensionFileFilter.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/filechooser/ExtensionFileFilter.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/filechooser/ExtensionFileFilter.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/filechooser/GhidraFileChooserModel.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/filechooser/GhidraFileChooserModel.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/filechooser/GhidraFileChooserModel.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/filechooser/GhidraFileChooserModel.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/filechooser/GhidraFileFilter.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/filechooser/GhidraFileFilter.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/filechooser/GhidraFileFilter.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/filechooser/GhidraFileFilter.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/html/HTMLElement.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/html/HTMLElement.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/html/HTMLElement.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/html/HTMLElement.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/html/HtmlLineSplitter.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/html/HtmlLineSplitter.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/html/HtmlLineSplitter.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/html/HtmlLineSplitter.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/html/PreservingWhitespaceHandler.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/html/PreservingWhitespaceHandler.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/html/PreservingWhitespaceHandler.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/html/PreservingWhitespaceHandler.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/html/TrimmingWhitespaceHandler.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/html/TrimmingWhitespaceHandler.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/html/TrimmingWhitespaceHandler.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/html/TrimmingWhitespaceHandler.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/html/WhitespaceHandler.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/html/WhitespaceHandler.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/html/WhitespaceHandler.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/html/WhitespaceHandler.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/ColumnLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/ColumnLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/ColumnLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/ColumnLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/HorizontalLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/HorizontalLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/HorizontalLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/HorizontalLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/MaximizeSpecificColumnGridLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/MaximizeSpecificColumnGridLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/MaximizeSpecificColumnGridLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/MaximizeSpecificColumnGridLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/MiddleLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/MiddleLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/MiddleLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/MiddleLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/PairLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/PairLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/PairLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/PairLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/RightSidedSquishyBuddyLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/RightSidedSquishyBuddyLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/RightSidedSquishyBuddyLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/RightSidedSquishyBuddyLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/RowColumnLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/RowColumnLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/RowColumnLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/RowColumnLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/RowLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/RowLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/RowLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/RowLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/StretchLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/StretchLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/StretchLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/StretchLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/TwoColumnPairLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/TwoColumnPairLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/TwoColumnPairLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/TwoColumnPairLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/VariableHeightPairLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/VariableHeightPairLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/VariableHeightPairLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/VariableHeightPairLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/VariableRowHeightGridLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/VariableRowHeightGridLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/VariableRowHeightGridLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/VariableRowHeightGridLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/VerticalLayout.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/VerticalLayout.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/VerticalLayout.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/VerticalLayout.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/package.html b/Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/package.html similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/layout/package.html rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/layout/package.html diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/AbstractSwingUpdateManager.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/AbstractSwingUpdateManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/AbstractSwingUpdateManager.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/AbstractSwingUpdateManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/BufferedSwingRunner.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/BufferedSwingRunner.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/BufferedSwingRunner.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/BufferedSwingRunner.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/CompoundTask.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/CompoundTask.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/CompoundTask.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/CompoundTask.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/DummyCancellableTaskMonitor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/DummyCancellableTaskMonitor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/DummyCancellableTaskMonitor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/DummyCancellableTaskMonitor.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/SwingRunnable.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/SwingRunnable.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/SwingRunnable.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/SwingRunnable.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/SwingUpdateManager.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/SwingUpdateManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/SwingUpdateManager.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/SwingUpdateManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/Task.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/Task.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/Task.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/Task.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/TaskListener.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/TaskListener.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/TaskListener.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/TaskListener.java diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/task/UnknownProgressWrappingTaskMonitor.java b/Ghidra/Framework/Gui/src/main/java/ghidra/util/task/UnknownProgressWrappingTaskMonitor.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/ghidra/util/task/UnknownProgressWrappingTaskMonitor.java rename to Ghidra/Framework/Gui/src/main/java/ghidra/util/task/UnknownProgressWrappingTaskMonitor.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/IconProvider.java b/Ghidra/Framework/Gui/src/main/java/resources/IconProvider.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/IconProvider.java rename to Ghidra/Framework/Gui/src/main/java/resources/IconProvider.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/Icons.java b/Ghidra/Framework/Gui/src/main/java/resources/Icons.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/Icons.java rename to Ghidra/Framework/Gui/src/main/java/resources/Icons.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/MultiIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/MultiIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/MultiIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/MultiIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/MultiIconBuilder.java b/Ghidra/Framework/Gui/src/main/java/resources/MultiIconBuilder.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/MultiIconBuilder.java rename to Ghidra/Framework/Gui/src/main/java/resources/MultiIconBuilder.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/QUADRANT.java b/Ghidra/Framework/Gui/src/main/java/resources/QUADRANT.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/QUADRANT.java rename to Ghidra/Framework/Gui/src/main/java/resources/QUADRANT.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/ResourceManager.java b/Ghidra/Framework/Gui/src/main/java/resources/ResourceManager.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/ResourceManager.java rename to Ghidra/Framework/Gui/src/main/java/resources/ResourceManager.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/BytesImageIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/BytesImageIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/BytesImageIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/BytesImageIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/CenterTranslateIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/CenterTranslateIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/CenterTranslateIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/CenterTranslateIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/ColorIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/ColorIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/ColorIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/ColorIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/ColorIcon3D.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/ColorIcon3D.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/ColorIcon3D.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/ColorIcon3D.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/DerivedImageIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/DerivedImageIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/DerivedImageIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/DerivedImageIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/DisabledImageIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/DisabledImageIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/DisabledImageIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/DisabledImageIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/DisabledImageIconWrapper.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/DisabledImageIconWrapper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/DisabledImageIconWrapper.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/DisabledImageIconWrapper.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/EmptyIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/EmptyIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/EmptyIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/EmptyIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/FileBasedIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/FileBasedIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/FileBasedIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/FileBasedIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/IconWrapper.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/IconWrapper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/IconWrapper.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/IconWrapper.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/ImageIconWrapper.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/ImageIconWrapper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/ImageIconWrapper.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/ImageIconWrapper.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/LazyImageIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/LazyImageIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/LazyImageIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/LazyImageIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/OvalBackgroundColorIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/OvalBackgroundColorIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/OvalBackgroundColorIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/OvalBackgroundColorIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/OvalColorIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/OvalColorIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/OvalColorIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/OvalColorIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/ReflectedIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/ReflectedIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/ReflectedIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/ReflectedIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/RotateIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/RotateIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/RotateIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/RotateIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/ScaledImageIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/ScaledImageIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/ScaledImageIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/ScaledImageIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/ScaledImageIconWrapper.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/ScaledImageIconWrapper.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/ScaledImageIconWrapper.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/ScaledImageIconWrapper.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/TranslateIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/TranslateIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/TranslateIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/TranslateIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/UnresolvedIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/UnresolvedIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/UnresolvedIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/UnresolvedIcon.java diff --git a/Ghidra/Framework/Generic/src/main/java/resources/icons/UrlImageIcon.java b/Ghidra/Framework/Gui/src/main/java/resources/icons/UrlImageIcon.java similarity index 100% rename from Ghidra/Framework/Generic/src/main/java/resources/icons/UrlImageIcon.java rename to Ghidra/Framework/Gui/src/main/java/resources/icons/UrlImageIcon.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ApplicationThemeManagerTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/ApplicationThemeManagerTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/ApplicationThemeManagerTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/ApplicationThemeManagerTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ColorValueTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/ColorValueTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/ColorValueTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/ColorValueTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/FontModifierTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/FontModifierTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/FontModifierTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/FontModifierTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/FontValueTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/FontValueTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/FontValueTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/FontValueTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/GThemeTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/GThemeTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/GThemeTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/GThemeTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/IconModifierTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/IconModifierTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/IconModifierTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/IconModifierTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/IconValueTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/IconValueTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/IconValueTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/IconValueTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeEventTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/ThemeEventTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeEventTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/ThemeEventTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemePropertyFileReaderTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/ThemePropertyFileReaderTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/ThemePropertyFileReaderTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/ThemePropertyFileReaderTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeValueUtilsTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/ThemeValueUtilsTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/ThemeValueUtilsTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/ThemeValueUtilsTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/generic/theme/laf/ThemeGrouperTest.java b/Ghidra/Framework/Gui/src/test/java/generic/theme/laf/ThemeGrouperTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/generic/theme/laf/ThemeGrouperTest.java rename to Ghidra/Framework/Gui/src/test/java/generic/theme/laf/ThemeGrouperTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java b/Ghidra/Framework/Gui/src/test/java/ghidra/util/HTMLUtilitiesTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java rename to Ghidra/Framework/Gui/src/test/java/ghidra/util/HTMLUtilitiesTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/WebColorsTest.java b/Ghidra/Framework/Gui/src/test/java/ghidra/util/WebColorsTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/ghidra/util/WebColorsTest.java rename to Ghidra/Framework/Gui/src/test/java/ghidra/util/WebColorsTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/task/BufferedSwingRunnerTest.java b/Ghidra/Framework/Gui/src/test/java/ghidra/util/task/BufferedSwingRunnerTest.java similarity index 98% rename from Ghidra/Framework/Generic/src/test/java/ghidra/util/task/BufferedSwingRunnerTest.java rename to Ghidra/Framework/Gui/src/test/java/ghidra/util/task/BufferedSwingRunnerTest.java index 33ad77fd89..36598b2101 100644 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/task/BufferedSwingRunnerTest.java +++ b/Ghidra/Framework/Gui/src/test/java/ghidra/util/task/BufferedSwingRunnerTest.java @@ -24,10 +24,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Before; import org.junit.Test; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.util.SystemUtilities; -public class BufferedSwingRunnerTest extends AbstractGenericTest { +public class BufferedSwingRunnerTest extends AbstractGuiTest { private static final int MIN_DELAY = 500; private static final int MAX_DELAY = 1000; diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/task/SwingUpdateManagerTest.java b/Ghidra/Framework/Gui/src/test/java/ghidra/util/task/SwingUpdateManagerTest.java similarity index 98% rename from Ghidra/Framework/Generic/src/test/java/ghidra/util/task/SwingUpdateManagerTest.java rename to Ghidra/Framework/Gui/src/test/java/ghidra/util/task/SwingUpdateManagerTest.java index c14664c7cc..d0fcc64a0c 100644 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/task/SwingUpdateManagerTest.java +++ b/Ghidra/Framework/Gui/src/test/java/ghidra/util/task/SwingUpdateManagerTest.java @@ -24,10 +24,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Before; import org.junit.Test; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.util.SystemUtilities; -public class SwingUpdateManagerTest extends AbstractGenericTest { +public class SwingUpdateManagerTest extends AbstractGuiTest { private static final int MIN_DELAY = 500; private static final int MAX_DELAY = 1000; private volatile int runnableCalled; diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/task/TimeoutTaskMonitorTest.java b/Ghidra/Framework/Gui/src/test/java/ghidra/util/task/TimeoutTaskMonitorTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/ghidra/util/task/TimeoutTaskMonitorTest.java rename to Ghidra/Framework/Gui/src/test/java/ghidra/util/task/TimeoutTaskMonitorTest.java diff --git a/Ghidra/Framework/Generic/src/test/java/resources/icons/MultiIconBuilderTest.java b/Ghidra/Framework/Gui/src/test/java/resources/icons/MultiIconBuilderTest.java similarity index 100% rename from Ghidra/Framework/Generic/src/test/java/resources/icons/MultiIconBuilderTest.java rename to Ghidra/Framework/Gui/src/test/java/resources/icons/MultiIconBuilderTest.java diff --git a/Ghidra/Framework/Help/build.gradle b/Ghidra/Framework/Help/build.gradle index 9e13b753c3..e62b9f8d71 100644 --- a/Ghidra/Framework/Help/build.gradle +++ b/Ghidra/Framework/Help/build.gradle @@ -23,8 +23,7 @@ apply plugin: 'eclipse' eclipse.project.name = 'Framework Help' dependencies { - api project(':Utility') - api project(':Generic') + api project(':Gui') api 'net.java.dev.timingframework:timingframework:1.0' diff --git a/Ghidra/Framework/Project/build.gradle b/Ghidra/Framework/Project/build.gradle index d13ff51ca6..eae2d0ba55 100644 --- a/Ghidra/Framework/Project/build.gradle +++ b/Ghidra/Framework/Project/build.gradle @@ -24,11 +24,7 @@ apply plugin: 'eclipse' eclipse.project.name = 'Framework Project' dependencies { - api project(':Generic') - api project(':DB') - api project(':Docking') api project(':FileSystem') - api project(':Utility') testImplementation project(path: ':Generic', configuration: 'testArtifacts') api "org.apache.commons:commons-compress:1.21" diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/EditActionManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/EditActionManager.java index 2d56336d3e..0ad0d08dbe 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/EditActionManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/EditActionManager.java @@ -24,12 +24,20 @@ import docking.tool.ToolConstants; import docking.widgets.OptionDialog; import docking.widgets.filechooser.GhidraFileChooser; import ghidra.net.ApplicationKeyManagerFactory; +import ghidra.net.ApplicationKeyManagerUtils; import ghidra.util.HelpLocation; +import ghidra.util.filechooser.ExtensionFileFilter; +import ghidra.util.filechooser.GhidraFileFilter; /** * Helper class to manage the actions on the Edit menu. */ class EditActionManager { + /** + * PKCS Private Key/Certificate File Filter + */ + public static final GhidraFileFilter CERTIFICATE_FILE_FILTER = + new ExtensionFileFilter(ApplicationKeyManagerUtils.PKCS_FILE_EXTENSIONS, "PKCS Key File"); private FrontEndPlugin plugin; private FrontEndTool tool; @@ -170,7 +178,7 @@ class EditActionManager { GhidraFileChooser fileChooser = new GhidraFileChooser(tool.getToolFrame()); fileChooser.setTitle("Select Certificate (req'd for PKI authentication only)"); fileChooser.setApproveButtonText("Set Certificate"); - fileChooser.setFileFilter(ApplicationKeyManagerFactory.CERTIFICATE_FILE_FILTER); + fileChooser.setFileFilter(CERTIFICATE_FILE_FILTER); fileChooser.setFileSelectionMode(GhidraFileChooser.FILES_ONLY); fileChooser.setHelpLocation(new HelpLocation(plugin.getName(), "Set_PKI_Certificate")); return fileChooser; diff --git a/Ghidra/Framework/SoftwareModeling/build.gradle b/Ghidra/Framework/SoftwareModeling/build.gradle index 092080cc2c..36187041b6 100644 --- a/Ghidra/Framework/SoftwareModeling/build.gradle +++ b/Ghidra/Framework/SoftwareModeling/build.gradle @@ -32,8 +32,6 @@ rootProject.createJsondocs.exclude '**/pcodeCPort/**' rootProject.prepDev.dependsOn compileJava dependencies { - api project(':Generic') - api project(':FileSystem') api project(':Project') api project(':Graph') diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/InstructionPatternSearchScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/InstructionPatternSearchScreenShots.java index 22f9c9264c..8d8a913cb9 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/InstructionPatternSearchScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/InstructionPatternSearchScreenShots.java @@ -24,7 +24,7 @@ import org.junit.Test; import docking.DialogComponentProvider; import docking.action.DockingActionIf; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.app.plugin.core.instructionsearch.InstructionSearchPlugin; import ghidra.app.plugin.core.instructionsearch.ui.*; import ghidra.app.plugin.core.table.TableComponentProvider; @@ -58,7 +58,7 @@ public class InstructionPatternSearchScreenShots extends AbstractSearchScreenSho DialogComponentProvider dialog = getDialog(); JButton manualEntryButton = - (JButton) AbstractGenericTest.findComponentByName(dialog.getComponent(), + (JButton) AbstractGuiTest.findComponentByName(dialog.getComponent(), "manual entry"); pressButton(manualEntryButton); @@ -210,7 +210,7 @@ public class InstructionPatternSearchScreenShots extends AbstractSearchScreenSho DialogComponentProvider dialog = getDialog(); JButton searchButton = - (JButton) AbstractGenericTest.findAbstractButtonByText(dialog.getComponent(), + (JButton) AbstractGuiTest.findAbstractButtonByText(dialog.getComponent(), "Search All"); pressButton(searchButton); diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/SharedProjectUtil.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/SharedProjectUtil.java index 3e4ac23c54..f681a8353f 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/SharedProjectUtil.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/SharedProjectUtil.java @@ -18,7 +18,7 @@ */ package ghidra.framework.main; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import java.io.File; import java.io.IOException; @@ -31,7 +31,7 @@ import docking.action.DockingActionIf; import docking.test.AbstractDockingTest; import docking.wizard.WizardManager; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.client.*; import ghidra.framework.model.*; import ghidra.server.remote.ServerTestUtil; @@ -71,13 +71,13 @@ public class SharedProjectUtil { DockingActionIf action = getAction(frontEndTool, "New Project"); AbstractDockingTest.performAction(action, false); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); WizardManager wm = AbstractDockingTest.waitForDialogComponent(WizardManager.class); ProjectTypePanel typePanel = AbstractDockingTest.findComponent(wm, ProjectTypePanel.class); final JRadioButton rb = - (JRadioButton) AbstractGenericTest.findAbstractButtonByText(typePanel, + (JRadioButton) AbstractGuiTest.findAbstractButtonByText(typePanel, "Shared Project"); SwingUtilities.invokeAndWait(() -> rb.setSelected(true)); @@ -85,41 +85,41 @@ public class SharedProjectUtil { JButton nextButton = AbstractDockingTest.findButtonByText(wm, "Next >>"); JButton finishButton = AbstractDockingTest.findButtonByText(wm, "Finish"); - AbstractGenericTest.pressButton(nextButton, true); + AbstractGuiTest.pressButton(nextButton, true); ServerInfoPanel serverPanel = AbstractDockingTest.findComponent(wm, ServerInfoPanel.class); final JTextField serverField = - (JTextField) AbstractGenericTest.findComponentByName(serverPanel, "Server Name"); + (JTextField) AbstractGuiTest.findComponentByName(serverPanel, "Server Name"); final JTextField portNumberField = - (JTextField) AbstractGenericTest.findComponentByName(serverPanel, "Port Number"); + (JTextField) AbstractGuiTest.findComponentByName(serverPanel, "Port Number"); SwingUtilities.invokeAndWait(() -> { serverField.setText(LOCALHOST); portNumberField.setText(Integer.toString(SERVER_PORT)); }); - AbstractGenericTest.pressButton(nextButton); + AbstractGuiTest.pressButton(nextButton); // next panel should be the repository panel RepositoryPanel repPanel = AbstractDockingTest.findComponent(wm, RepositoryPanel.class); - final JList repList = AbstractGenericTest.findComponent(repPanel, JList.class); + final JList repList = AbstractGuiTest.findComponent(repPanel, JList.class); // select existing repository SwingUtilities.invokeAndWait(() -> repList.setSelectedIndex(0)); // next panel is project location panel - AbstractGenericTest.pressButton(nextButton, true); + AbstractGuiTest.pressButton(nextButton, true); final SelectProjectPanel projPanel = AbstractDockingTest.findComponent(wm, SelectProjectPanel.class); final String testProjectDirectory = AbstractGTest.getTestDirectoryPath(); final JTextField projDirField = - (JTextField) AbstractGenericTest.findComponentByName(projPanel, "Project Directory"); + (JTextField) AbstractGuiTest.findComponentByName(projPanel, "Project Directory"); final JTextField projNameField = - (JTextField) AbstractGenericTest.findComponentByName(projPanel, "Project Name"); + (JTextField) AbstractGuiTest.findComponentByName(projPanel, "Project Name"); SwingUtilities.invokeAndWait(() -> { projDirField.setText(testProjectDirectory); @@ -133,8 +133,8 @@ public class SharedProjectUtil { return false; } - AbstractGenericTest.pressButton(finishButton, true); - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.pressButton(finishButton, true); + AbstractGuiTest.waitForSwing(); boolean didOpen = waitForProjectToOpen(projectName, projectListener); System.err.println("\tdid the project get opened?: " + didOpen); return didOpen; @@ -151,7 +151,7 @@ public class SharedProjectUtil { AbstractGTest.sleep(waitTime); } - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); boolean success = desiredProjectName.equals(lastOpenedProjectName); if (!success) { System.err.println("\tOpen windows: " + AbstractDockingTest.getOpenWindowsAsString()); diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java index 84fd92be8c..7c83d21ea2 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/framework/main/datatree/VersionControlAction2Test.java @@ -32,6 +32,7 @@ import docking.action.DockingActionIf; import docking.widgets.OptionDialog; import docking.widgets.table.GTable; import docking.widgets.tree.GTreeNode; +import generic.theme.GIcon; import ghidra.framework.main.projectdata.actions.VersionControlAction; import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainFolder; @@ -42,6 +43,7 @@ import ghidra.program.model.symbol.SymbolTable; import ghidra.util.task.TaskMonitor; import resources.MultiIcon; import resources.ResourceManager; +import resources.icons.UrlImageIcon; /** * Tests for version control (not multi user). @@ -424,4 +426,20 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest pressButtonByText(dialog, "Dismiss"); waitForTasks(); } + + /** + * Gets the URL for the given icon + * @param icon the icon to get a URL for + * @return the URL for the given icon + */ + public URL getURL(Icon icon) { + if (icon instanceof UrlImageIcon urlIcon) { + return urlIcon.getUrl(); + } + if (icon instanceof GIcon gIcon) { + return gIcon.getUrl(); + } + return null; + } + } diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/DataTreeHelper.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/DataTreeHelper.java index bcd6d81151..d3a5c3e683 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/DataTreeHelper.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/DataTreeHelper.java @@ -25,7 +25,7 @@ import docking.test.AbstractDockingTest; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.main.datatable.ProjectDataContext; import ghidra.framework.main.datatree.*; import ghidra.framework.model.DomainFile; @@ -104,7 +104,7 @@ public class DataTreeHelper { } public void clearTreeSelection() { - AbstractGenericTest.runSwing(() -> tree.clearSelection()); + AbstractGuiTest.runSwing(() -> tree.clearSelection()); } public void setTreeSelection(final TreePath[] paths) throws Exception { diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java index 0ffc529e39..8fca5319fe 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java @@ -30,7 +30,7 @@ import docking.widgets.OptionDialog; import docking.widgets.tree.GTree; import docking.widgets.tree.GTreeNode; import generic.test.AbstractGTest; -import generic.test.AbstractGenericTest; +import generic.test.AbstractGuiTest; import ghidra.framework.main.FrontEndTool; import ghidra.framework.main.SharedProjectUtil; import ghidra.framework.main.datatree.*; @@ -80,7 +80,7 @@ public class FrontEndTestEnv { // assume read-only project views are not active and only active // project tree is present DataTree tree = - AbstractGenericTest.findComponent(frontEndTool.getToolFrame(), DataTree.class); + AbstractGuiTest.findComponent(frontEndTool.getToolFrame(), DataTree.class); projectTreeHelper = new DataTreeHelper(tree, true); Project project = frontEndTool.getProject(); @@ -168,19 +168,19 @@ public class FrontEndTestEnv { } public void waitForSwing() { - AbstractGenericTest.waitForSwing(); + AbstractGuiTest.waitForSwing(); } private void runSwing(Runnable r) { - AbstractGenericTest.runSwing(r); + AbstractGuiTest.runSwing(r); } private void runSwing(Runnable r, boolean wait) { - AbstractGenericTest.runSwing(r, wait); + AbstractGuiTest.runSwing(r, wait); } private void waitForTasks() { - AbstractGenericTest.waitForTasks(); + AbstractGuiTest.waitForTasks(); } public void setTreeSelection(final TreePath[] paths) throws Exception { @@ -237,8 +237,8 @@ public class FrontEndTestEnv { assertTrue(node.getDomainFile().isCheckedOut()); - AbstractGenericTest.waitForSwing(); - AbstractGenericTest.waitForTasks(); + AbstractGuiTest.waitForSwing(); + AbstractGuiTest.waitForTasks(); Program program = (Program) node.getDomainFile().getDomainObject(this, true, false, TaskMonitor.DUMMY); @@ -305,7 +305,7 @@ public class FrontEndTestEnv { ActionContext context = provider.getActionContext(null); AbstractDockingTest.performAction(terminateCheckoutAction, context, false); OptionDialog optDialog = AbstractDockingTest.waitForDialogComponent(OptionDialog.class); - AbstractGenericTest.pressButtonByText(optDialog.getComponent(), "Yes", true); + AbstractGuiTest.pressButtonByText(optDialog.getComponent(), "Yes", true); waitForTasks(); waitForSwing(); } @@ -323,7 +323,8 @@ public class FrontEndTestEnv { } public List getTools() { - PluginTool[] tools = frontEndTool.getProject().getToolManager().getActiveWorkspace().getTools(); + PluginTool[] tools = + frontEndTool.getProject().getToolManager().getActiveWorkspace().getTools(); return new ArrayList<>(Arrays.asList(tools)); } @@ -371,9 +372,9 @@ public class FrontEndTestEnv { } JButton okButton = - (JButton) AbstractGenericTest.findAbstractButtonByText(dialog.getComponent(), "OK"); + (JButton) AbstractGuiTest.findAbstractButtonByText(dialog.getComponent(), "OK"); assertNotNull(okButton); - AbstractGenericTest.pressButton(okButton); + AbstractGuiTest.pressButton(okButton); waitForTasks(); DomainFile df = node.getDomainFile(); @@ -441,7 +442,7 @@ public class FrontEndTestEnv { */ public DataTreeHelper getReadOnlyProjectTreeHelper(String tabName) { String dataTreeName = "Data Tree: " + tabName; - DataTree tree = (DataTree) AbstractGenericTest + DataTree tree = (DataTree) AbstractGuiTest .findComponentByName(frontEndTool.getToolFrame(), dataTreeName); return tree != null ? new DataTreeHelper(tree, true) : null; } @@ -451,7 +452,7 @@ public class FrontEndTestEnv { * @return READ-ONLY project view tree helper for first view found or null if none displayed */ public DataTreeHelper getFirstReadOnlyProjectTreeHelper() { - for (DataTree tree : AbstractGenericTest.findComponents(frontEndTool.getToolFrame(), + for (DataTree tree : AbstractGuiTest.findComponents(frontEndTool.getToolFrame(), DataTree.class)) { if (tree.getName().startsWith("Data Tree:")) { return new DataTreeHelper(tree, true);