GP-4466 consolidated focus handling between ComponentProvider and DockableComponent

This commit is contained in:
ghidragon 2024-03-28 18:26:18 -04:00
parent c131adc670
commit 495dc4df66
8 changed files with 41 additions and 84 deletions

View file

@ -24,7 +24,8 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.*; import java.util.*;
import javax.swing.*; import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
@ -39,7 +40,8 @@ import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
import docking.widgets.fieldpanel.support.*; import docking.widgets.fieldpanel.support.*;
import generic.theme.GIcon; import generic.theme.GIcon;
import ghidra.app.context.ListingActionContext; import ghidra.app.context.ListingActionContext;
import ghidra.app.nav.*; import ghidra.app.nav.ListingPanelContainer;
import ghidra.app.nav.LocationMemento;
import ghidra.app.plugin.core.clipboard.CodeBrowserClipboardProvider; import ghidra.app.plugin.core.clipboard.CodeBrowserClipboardProvider;
import ghidra.app.plugin.core.codebrowser.actions.*; import ghidra.app.plugin.core.codebrowser.actions.*;
import ghidra.app.plugin.core.codebrowser.hover.ListingHoverService; import ghidra.app.plugin.core.codebrowser.hover.ListingHoverService;
@ -164,6 +166,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
codeViewerClipboardProvider = newClipboardProvider(); codeViewerClipboardProvider = newClipboardProvider();
tool.addPopupActionProvider(this); tool.addPopupActionProvider(this);
setDefaultFocusComponent(listingPanel.getFieldPanel());
} }
protected CodeBrowserClipboardProvider newClipboardProvider() { protected CodeBrowserClipboardProvider newClipboardProvider() {
@ -884,11 +887,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
return true; return true;
} }
@Override
public void requestFocus() {
listingPanel.getFieldPanel().requestFocus();
}
@Override @Override
public void writeDataState(SaveState saveState) { public void writeDataState(SaveState saveState) {
super.writeDataState(saveState); super.writeDataState(saveState);

View file

@ -399,19 +399,6 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter implement
return component; return component;
} }
@Override
public void requestFocus() {
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component focusOwner = kfm.getFocusOwner();
if (focusOwner != null) {
if (SwingUtilities.isDescendingFrom(focusOwner, component)) {
return; // nothing to do
}
}
component.requestFocus();
}
public void setCurrentProgram(Program program) { public void setCurrentProgram(Program program) {
currentProgram = program; currentProgram = program;
} }

View file

@ -366,13 +366,7 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
public boolean isVisible() { public boolean isVisible() {
return tool.isVisible(this); return tool.isVisible(this);
} }
@Override
public void requestFocus() {
panel.getCurrentComponent().requestFocus();
tool.toFront(this);
}
//================================================================================================== //==================================================================================================
// End Navigatable interface methods */ // End Navigatable interface methods */
//================================================================================================== //==================================================================================================

View file

@ -165,6 +165,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
plugin.getTool().addServiceListener(serviceListener); plugin.getTool().addServiceListener(serviceListener);
programListener = new DecompilerProgramListener(controller, redecompileUpdater); programListener = new DecompilerProgramListener(controller, redecompileUpdater);
setDefaultFocusComponent(controller.getDecompilerPanel());
} }
//================================================================================================== //==================================================================================================
@ -287,12 +288,6 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
pendingViewerPosition = decompMemento.getViewerPosition(); pendingViewerPosition = decompMemento.getViewerPosition();
} }
@Override
public void requestFocus() {
controller.getDecompilerPanel().requestFocus();
tool.toFront(this);
}
//================================================================================================== //==================================================================================================
// DecompilerHighlightService interface methods // DecompilerHighlightService interface methods
//================================================================================================== //==================================================================================================

View file

@ -133,6 +133,8 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
new SwingUpdateManager(250, 750, () -> setPendingLocationFromUpdateManager()); new SwingUpdateManager(250, 750, () -> setPendingLocationFromUpdateManager());
clipboardProvider = new FGClipboardProvider(tool, controller); clipboardProvider = new FGClipboardProvider(tool, controller);
setDefaultFocusComponent(controller.getViewComponent());
} }
@Override @Override
@ -1286,16 +1288,6 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
return true; return true;
} }
@Override
public void requestFocus() {
if (!isVisible()) {
return; // we will popup incorrectly without this check
}
controller.requestFocus();
tool.toFront(this);
}
@Override @Override
public boolean isFocusedProvider() { public boolean isFocusedProvider() {
return focusStatusDelegate.get(); return focusStatusDelegate.get();

View file

@ -497,10 +497,6 @@ public class FGController implements ProgramLocationListener, ProgramSelectionLi
return functionGraphData.hasResults(); return functionGraphData.hasResults();
} }
public void requestFocus() {
view.requestFocus();
}
public void cleanup() { public void cleanup() {
clear(); clear();
disposeCache(); disposeCache();

View file

@ -115,6 +115,7 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
private String inceptionInformation; private String inceptionInformation;
private String registeredFontId; private String registeredFontId;
private Component defaultFocusComponent;
private ThemeListener themeListener = this::themeChanged; private ThemeListener themeListener = this::themeChanged;
@ -225,21 +226,35 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
return instanceID; return instanceID;
} }
// Default implementation public final void requestFocus() {
public void requestFocus() { if (!isVisible()) {
return;
JComponent component = getComponent();
if (component == null) {
return; // this shouldn't happen; this implies we have been disposed
} }
dockingTool.toFront();
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); if (defaultFocusComponent != null) {
Component focusOwner = kfm.getFocusOwner(); DockingWindowManager.requestFocus(defaultFocusComponent);
if (focusOwner != null && SwingUtilities.isDescendingFrom(focusOwner, component)) {
return; return;
} }
component.requestFocus(); JComponent component = getComponent();
Container parent = component == null ? null : component.getParent();
if (parent == null) {
return; // we are either disposed or not added to the tool yet
}
Container focusCycleRoot = parent.getFocusCycleRootAncestor();
FocusTraversalPolicy focusTraversalPolicy = focusCycleRoot.getFocusTraversalPolicy();
Component componentAfter = focusTraversalPolicy.getComponentAfter(focusCycleRoot, parent);
// Only request focus if next component in focus traversal belongs to this provider
if (componentAfter != null && SwingUtilities.isDescendingFrom(componentAfter, parent)) {
DockingWindowManager.requestFocus(componentAfter);
}
}
protected void setDefaultFocusComponent(Component component) {
this.defaultFocusComponent = component;
} }
/** /**

View file

@ -20,7 +20,6 @@ import java.awt.dnd.*;
import java.awt.event.*; import java.awt.event.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.FocusManager;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import ghidra.util.CascadedDropTarget; import ghidra.util.CascadedDropTarget;
@ -46,7 +45,7 @@ public class DockableComponent extends JPanel implements ContainerListener {
private MouseListener popupListener; private MouseListener popupListener;
private ComponentPlaceholder placeholder; private ComponentPlaceholder placeholder;
private JComponent providerComp; private JComponent providerComp;
private Component focusedComponent; private Component lastFocusedComponent;
private DockingWindowManager winMgr; private DockingWindowManager winMgr;
private ActionToGuiMapper actionMgr; private ActionToGuiMapper actionMgr;
private DropTarget dockableDropTarget; private DropTarget dockableDropTarget;
@ -142,10 +141,6 @@ public class DockableComponent extends JPanel implements ContainerListener {
return helpLocation; return helpLocation;
} }
public Component getFocusedComponent() {
return focusedComponent;
}
void showContextMenu(PopupMenuContext popupContext) { void showContextMenu(PopupMenuContext popupContext) {
actionMgr.showPopupMenu(placeholder, popupContext); actionMgr.showPopupMenu(placeholder, popupContext);
} }
@ -448,15 +443,16 @@ public class DockableComponent extends JPanel implements ContainerListener {
@Override @Override
// we aren't focusable, so pass focus to a valid child component // we aren't focusable, so pass focus to a valid child component
public void requestFocus() { public void requestFocus() {
focusedComponent = findFocusedComponent(); if (lastFocusedComponent != null && lastFocusedComponent.isShowing()) {
if (focusedComponent != null) { lastFocusedComponent.requestFocus();
DockingWindowManager.requestFocus(focusedComponent); return;
} }
placeholder.getProvider().requestFocus();
} }
void setFocusedComponent(Component newFocusedComponet) { void setFocusedComponent(Component newFocusedComponet) {
// remember it so we can restore it later when necessary // remember it so we can restore it later when necessary
focusedComponent = newFocusedComponet; lastFocusedComponent = newFocusedComponet;
} }
private void componentSelected(Component component) { private void componentSelected(Component component) {
@ -467,22 +463,6 @@ public class DockableComponent extends JPanel implements ContainerListener {
} }
} }
// find the first available component that can take focus
private Component findFocusedComponent() {
if (focusedComponent != null && focusedComponent.isShowing()) {
return focusedComponent;
}
DefaultFocusManager dfm = (DefaultFocusManager) FocusManager.getCurrentManager();
Component component = dfm.getComponentAfter(this, this);
// component must be a child of this DockableComponent
if (component != null && SwingUtilities.isDescendingFrom(component, this)) {
return component;
}
return null;
}
@Override @Override
public void componentAdded(ContainerEvent e) { public void componentAdded(ContainerEvent e) {
initializeComponents(e.getChild()); initializeComponents(e.getChild());