Merge remote-tracking branch 'origin/GP-4227_ghidragon_keyboard_nav--SQUASHED'

This commit is contained in:
Ryan Kurtz 2024-01-29 17:17:01 -05:00
commit 590fcdcb7f
18 changed files with 1448 additions and 150 deletions

View file

@ -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.
@ -17,9 +16,9 @@
package ghidra.app.plugin;
public class GenericPluginCategoryNames {
public static final String COMMON = "Common";
public static final String SUPPORT = "Support";
public static final String TESTING = "Testing";
public static final String MISC = "Miscellaneous";
public static final String EXAMPLES = "Examples";
public static final String COMMON = "Common";
public static final String SUPPORT = "Support";
public static final String TESTING = "Testing";
public static final String MISC = "Miscellaneous";
public static final String EXAMPLES = "Examples";
}

View file

@ -26,6 +26,7 @@ public interface PluginCategoryNames {
String SEARCH = "Search";
String TREE = "Program Tree";
String TESTING = GenericPluginCategoryNames.TESTING;
String DIAGNOSTIC = "Diagnostic";
String DIFF = "Code Difference";
String MISC = GenericPluginCategoryNames.MISC;
String USER_ANNOTATION = "User Annotation";

View file

@ -501,7 +501,8 @@ public abstract class PluginTool extends AbstractDockingTool {
pluginMgr.close();
if (project != null) {
if (project.getToolManager() != null) {
project.getToolManager().disconnectTool(this);
project.getToolManager()
.disconnectTool(this);
}
}
@ -720,7 +721,8 @@ public abstract class PluginTool extends AbstractDockingTool {
*/
public boolean threadIsBackgroundTaskThread() {
ThreadGroup taskGroup = taskMgr.getTaskThreadGroup();
ThreadGroup group = Thread.currentThread().getThreadGroup();
ThreadGroup group = Thread.currentThread()
.getThreadGroup();
while (group != null && group != taskGroup) {
group = group.getParent();
}
@ -1050,8 +1052,28 @@ public abstract class PluginTool extends AbstractDockingTool {
addAction(saveAsAction);
}
protected void addExportToolAction() {
/**
* Adds actions to the tool for transferring focus to the first component in the next
* or previous dockable component provider.
*/
protected void addNextPreviousProviderActions() {
// @formatter:off
new ActionBuilder("Jump to Next Dockable Provider", ToolConstants.TOOL_OWNER)
.keyBinding(KeyStroke.getKeyStroke("control J"))
.description("Transfer focus to the next major component in this windows")
.onAction(e -> nextDockableComponent(true))
.buildAndInstall(this);
new ActionBuilder("Jump to Previous Dockable Provider", ToolConstants.TOOL_OWNER)
.keyBinding("shift control J")
.description("Transfer focus to the previous major component in this windows")
.onAction(e -> nextDockableComponent(false))
.buildAndInstall(this);
// @formatter:on
}
protected void addExportToolAction() {
String menuGroup = "Tool";
String exportPullright = "Export";
setMenuGroup(new String[] { ToolConstants.MENU_FILE, exportPullright }, menuGroup);
@ -1310,7 +1332,8 @@ public abstract class PluginTool extends AbstractDockingTool {
* @param height height in pixels
*/
public void setSize(int width, int height) {
winMgr.getMainWindow().setSize(new Dimension(width, height));
winMgr.getMainWindow()
.setSize(new Dimension(width, height));
}
/**
@ -1318,7 +1341,8 @@ public abstract class PluginTool extends AbstractDockingTool {
* @return dimension of this tool's frame
*/
public Dimension getSize() {
return winMgr.getMainWindow().getSize();
return winMgr.getMainWindow()
.getSize();
}
/**
@ -1327,7 +1351,8 @@ public abstract class PluginTool extends AbstractDockingTool {
* @param y screen y coordinate
*/
public void setLocation(int x, int y) {
winMgr.getMainWindow().setLocation(x, y);
winMgr.getMainWindow()
.setLocation(x, y);
}
/**
@ -1335,7 +1360,8 @@ public abstract class PluginTool extends AbstractDockingTool {
* @return location of this tool's frame
*/
public Point getLocation() {
return winMgr.getMainWindow().getLocation();
return winMgr.getMainWindow()
.getLocation();
}
private void updateTitle() {
@ -1527,6 +1553,63 @@ public abstract class PluginTool extends AbstractDockingTool {
return restoringDataState;
}
/**
* Transfers focus to the first component in the next/previous dockable component provider.
* @param forward true to go to next provider, false to go to previous provider
*/
private void nextDockableComponent(boolean forward) {
KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component focusOwner = focusManager.getPermanentFocusOwner();
Component next = findNextProviderComponent(focusOwner, forward);
// If going backwards, go back one more provider, then go forward to get the first
// component in the resulting provider. This makes it so that when going backwards, you
// still get the first component in the component provider and not the last.
if (!forward) {
next = findNextProviderComponent(next, false);
next = findNextProviderComponent(next, true);
}
if (next != null) {
next.requestFocus();
}
}
private Component findNextProviderComponent(Component component, boolean forward) {
if (component == null) {
return null;
}
DockingWindowManager windowManager = getWindowManager();
ComponentProvider startingProvider = windowManager.getComponentProvider(component);
Component next = getNext(component, forward);
while (next != null && next != component) {
// Skip JTabbedPanes. Assume the user prefers that the component inside the tabbed
// pane gets focus, not the tabbed pane itself so the user does not have to navigate
// twice to get the internal component.
if (next instanceof JTabbedPane) {
next = getNext(next, forward);
continue;
}
ComponentProvider nextProvider = windowManager.getComponentProvider(next);
if (nextProvider != startingProvider) {
return next;
}
next = getNext(next, forward);
}
return null;
}
private Component getNext(Component component, boolean forward) {
KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Window window = focusManager.getFocusedWindow();
FocusTraversalPolicy policy = window.getFocusTraversalPolicy();
if (forward) {
return policy.getComponentAfter(window, component);
}
return policy.getComponentBefore(window, component);
}
//==================================================================================================
// Inner Classes
//==================================================================================================

View file

@ -95,6 +95,7 @@ public class GhidraTool extends PluginTool {
addManagePluginsAction();
addOptionsAction();
addHelpActions();
addNextPreviousProviderActions();
}
@Override