mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-5149 - Fix for toggling visibility of component providers
This commit is contained in:
parent
7ec765c854
commit
dbca3b35cd
4 changed files with 44 additions and 54 deletions
|
@ -1076,6 +1076,10 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
|
||||
private class ShowProviderAction extends DockingAction {
|
||||
|
||||
/** Number of milliseconds to track user requests */
|
||||
private static final int TIME_WINDOW = 2000;
|
||||
private SortedSet<Long> clickTimes = new TreeSet<>();
|
||||
|
||||
ShowProviderAction(boolean supportsKeyBindings) {
|
||||
super(name, owner,
|
||||
supportsKeyBindings ? KeyBindingType.SHARED : KeyBindingType.UNSUPPORTED);
|
||||
|
@ -1100,19 +1104,37 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
|
|||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
|
||||
if (isShowing()) {
|
||||
boolean isFrustrated = isFrustrated();
|
||||
boolean isFocused = isFocused();
|
||||
if (isFocused && !isFrustrated) {
|
||||
// the user has decided to hide this component and is not madly clicking
|
||||
setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
DockingWindowManager myDwm = DockingWindowManager.getInstance(getComponent());
|
||||
if (myDwm == null) {
|
||||
// this can happen when the tool loses focus
|
||||
dockingTool.showComponentProvider(ComponentProvider.this, true);
|
||||
return;
|
||||
}
|
||||
boolean emphasize = getComponent().isShowing() && isFrustrated;
|
||||
Tool tool = getTool();
|
||||
DockingWindowManager myDwm = tool.getWindowManager();
|
||||
myDwm.showComponent(ComponentProvider.this, true, emphasize);
|
||||
}
|
||||
|
||||
myDwm.showComponent(ComponentProvider.this, true, true);
|
||||
private boolean isFrustrated() {
|
||||
long time = System.currentTimeMillis();
|
||||
clickTimes.add(time);
|
||||
|
||||
// grab all click times within the time window
|
||||
long secondsAgo = time - TIME_WINDOW;
|
||||
SortedSet<Long> recentClicks = clickTimes.tailSet(secondsAgo);
|
||||
clickTimes.retainAll(recentClicks); // drop old click times
|
||||
int clickCount = recentClicks.size();
|
||||
return clickCount > 2; // rapid clicking within the time window
|
||||
}
|
||||
|
||||
private boolean isFocused() {
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
Component focusOwner = kfm.getFocusOwner();
|
||||
JComponent myComponent = getComponent();
|
||||
return focusOwner != null && SwingUtilities.isDescendingFrom(focusOwner, myComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -107,6 +107,15 @@ public class DockableHeader extends GenericHeader
|
|||
super.setSelected(hasFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (focusAnimator != null) {
|
||||
focusAnimator.stop();
|
||||
focusAnimator = null;
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void installRenameAction(MouseListener listener) {
|
||||
titlePanel.installRenameAction(listener);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
private PlaceholderManager placeholderManager;
|
||||
private LRUSet<ComponentPlaceholder> lastFocusedPlaceholders = new LRUSet<>(20);
|
||||
|
||||
private ActivatedInfo activatedInfo = new ActivatedInfo();
|
||||
private ComponentPlaceholder focusedPlaceholder;
|
||||
private ComponentPlaceholder nextFocusedPlaceholder;
|
||||
private ComponentProvider defaultProvider;
|
||||
|
@ -959,7 +958,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
placeholder.show(visibleState);
|
||||
|
||||
if (visibleState) {
|
||||
movePlaceholderToFront(placeholder, false);
|
||||
movePlaceholderToFront(placeholder, shouldEmphasize);
|
||||
if (placeholder.getNode() == null) {
|
||||
root.addToNewWindow(placeholder);
|
||||
}
|
||||
|
@ -978,12 +977,10 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
|
||||
private void movePlaceholderToFront(ComponentPlaceholder placeholder, boolean emphasisze) {
|
||||
placeholder.toFront();
|
||||
|
||||
if (emphasisze) {
|
||||
activatedInfo.activated(placeholder);
|
||||
}
|
||||
|
||||
toFront(root.getWindow(placeholder));
|
||||
if (emphasisze) {
|
||||
placeholder.emphasize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1448,10 +1445,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
focusedPlaceholder.setSelected(false);
|
||||
}
|
||||
|
||||
// Activating placeholders is done to help users find widgets hiding in plain sight.
|
||||
// Assume that the user is no longer seeking a provider if they are clicking around.
|
||||
activatedInfo.clear();
|
||||
|
||||
focusedPlaceholder = placeholder;
|
||||
|
||||
// put the last focused placeholder at the front of the list for restoring focus work later
|
||||
|
@ -2518,39 +2511,4 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||
});
|
||||
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Inner Classes
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* A class that tracks placeholders that are activated (brought to the front). If a placeholder
|
||||
* is activated too frequently, this class will emphasize that window, under the assumption that
|
||||
* the user doesn't see the window.
|
||||
*/
|
||||
private class ActivatedInfo {
|
||||
|
||||
private long lastCalledTimestamp;
|
||||
private ComponentPlaceholder lastActivatedPlaceholder;
|
||||
|
||||
void activated(ComponentPlaceholder placeholder) {
|
||||
if (lastActivatedPlaceholder == placeholder) {
|
||||
// repeat call--see if it was quickly called again (a sign of confusion/frustration)
|
||||
long elapsedTime = System.currentTimeMillis() - lastCalledTimestamp;
|
||||
if (elapsedTime < 3000) { // somewhat arbitrary time window
|
||||
placeholder.emphasize();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.lastActivatedPlaceholder = placeholder;
|
||||
}
|
||||
lastCalledTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
lastActivatedPlaceholder = null;
|
||||
lastCalledTimestamp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue