GP-3254 - Added a Front End tool option to disable application-wide

tooltips
This commit is contained in:
dragonmacher 2023-04-24 19:51:52 -04:00
parent 528c0a8b94
commit fabdc3739c
6 changed files with 85 additions and 15 deletions

View file

@ -1095,7 +1095,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
setHover(isSelected()); setHover(isSelected());
} }
void setHover(boolean enabled) { private void setHover(boolean enabled) {
getToolBarData().setIcon(enabled ? HOVER_ON_ICON : HOVER_OFF_ICON); getToolBarData().setIcon(enabled ? HOVER_ON_ICON : HOVER_OFF_ICON);
setHoverEnabled(enabled); setHoverEnabled(enabled);
} }

View file

@ -80,6 +80,10 @@ public abstract class AbstractHoverProvider implements HoverProvider {
} }
} }
public boolean isForcePopups() {
return false; // the default implementation is to be disabled if tip windows are disabled
}
private boolean hasEnabledHoverServices() { private boolean hasEnabledHoverServices() {
for (HoverService hoverService : hoverServices) { for (HoverService hoverService : hoverServices) {
if (hoverService.hoverModeSelected()) { if (hoverService.hoverModeSelected()) {
@ -162,6 +166,10 @@ public abstract class AbstractHoverProvider implements HoverProvider {
Rectangle fieldBounds) { Rectangle fieldBounds) {
lastField = field; lastField = field;
if (!enabled) {
return;
}
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Window activeWindow = kfm.getActiveWindow(); Window activeWindow = kfm.getActiveWindow();
if (activeWindow == null) { if (activeWindow == null) {
@ -187,9 +195,10 @@ public abstract class AbstractHoverProvider implements HoverProvider {
} }
}); });
boolean force = isForcePopups();
boolean isToolTip = comp instanceof JToolTip; boolean isToolTip = comp instanceof JToolTip;
if (isToolTip) { if (isToolTip) {
popupWindow.showPopup(event); popupWindow.showPopup(event, force);
} }
else { else {
@ -206,7 +215,7 @@ public abstract class AbstractHoverProvider implements HoverProvider {
Rectangle keepVisibleArea = new Rectangle(event.getPoint()); Rectangle keepVisibleArea = new Rectangle(event.getPoint());
keepVisibleArea.grow(horizontalPad, verticalPad); keepVisibleArea.grow(horizontalPad, verticalPad);
popupWindow.showOffsetPopup(event, keepVisibleArea); popupWindow.showOffsetPopup(event, keepVisibleArea, force);
} }
} }

View file

@ -39,6 +39,11 @@ public class ListingHoverProvider extends AbstractHoverProvider {
super.removeHoverService(hoverService); super.removeHoverService(hoverService);
} }
@Override
public boolean isForcePopups() {
return true; // our enablement is controlled only by a user-level toolbar action
}
@Override @Override
protected ProgramLocation getHoverLocation(FieldLocation fieldLocation, Field field, protected ProgramLocation getHoverLocation(FieldLocation fieldLocation, Field field,
Rectangle fieldBounds, MouseEvent event) { Rectangle fieldBounds, MouseEvent event) {
@ -46,7 +51,8 @@ public class ListingHoverProvider extends AbstractHoverProvider {
ProgramLocation loc = null; ProgramLocation loc = null;
if (field instanceof ListingField) { if (field instanceof ListingField) {
ListingField listingField = (ListingField) field; ListingField listingField = (ListingField) field;
loc = listingField.getFieldFactory().getProgramLocation(fieldLocation.getRow(), loc = listingField.getFieldFactory()
.getProgramLocation(fieldLocation.getRow(),
fieldLocation.getCol(), listingField); fieldLocation.getCol(), listingField);
} }

View file

@ -40,6 +40,7 @@ import docking.widgets.tree.support.GTreeRenderer;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import ghidra.docking.util.LookAndFeelUtils; import ghidra.docking.util.LookAndFeelUtils;
import ghidra.util.HTMLUtilities; import ghidra.util.HTMLUtilities;
import ghidra.util.Swing;
import resources.ResourceManager; import resources.ResourceManager;
/** /**
@ -353,14 +354,38 @@ public class DockingUtils {
c.setBackground(Palette.NO_COLOR); c.setBackground(Palette.NO_COLOR);
} }
/**
* Sets the application-wide Java tooltip enablement.
* @param enabled true if enabled; false prevents all Java tooltips
*/
public static void setTipWindowEnabled(boolean enabled) {
Swing.runLater(() -> ToolTipManager.sharedInstance().setEnabled(enabled));
}
/**
* Returns true if application-wide Java tooltips are enabled.
* @return true if application-wide Java tooltips are enabled.
*/
public static boolean isTipWindowEnabled() {
return Swing.runNow(() -> ToolTipManager.sharedInstance().isEnabled());
}
/** Hides any open tooltip window */ /** Hides any open tooltip window */
public static void hideTipWindow() { public static void hideTipWindow() {
// This is a hack, since Java's manager doesn't have this method
javax.swing.ToolTipManager.sharedInstance().setEnabled(false);
javax.swing.ToolTipManager.sharedInstance().setEnabled(true);
// TODO: Ultimately, the ESCAPE key binding in the Java TTM should hide any visible tooltips. We Swing.runLater(() -> {
// need to look into why this isn't working. ToolTipManager ttm = ToolTipManager.sharedInstance();
if (!ttm.isEnabled()) {
return; // nothing to do
}
//
// This is a hack, since Java's manager doesn't have this method. Calling
// setEnabled(false) will close any open tooltips.
//
ttm.setEnabled(false);
ttm.setEnabled(true);
});
} }
} }

View file

@ -25,6 +25,7 @@ import java.util.List;
import javax.swing.*; import javax.swing.*;
import javax.swing.Timer; import javax.swing.Timer;
import docking.DockingUtils;
import docking.widgets.shapes.*; import docking.widgets.shapes.*;
import generic.theme.GThemeDefaults.Colors.Palette; import generic.theme.GThemeDefaults.Colors.Palette;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
@ -226,13 +227,33 @@ public class PopupWindow {
closeTimer.setRepeats(false); closeTimer.setRepeats(false);
} }
public void showOffsetPopup(MouseEvent e, Rectangle keepVisibleSize) { public void showOffsetPopup(MouseEvent e, Rectangle keepVisibleSize, boolean forceShow) {
if (forceShow || DockingUtils.isTipWindowEnabled()) {
doShowPopup(e, keepVisibleSize, DEFAULT_WINDOW_PLACER); doShowPopup(e, keepVisibleSize, DEFAULT_WINDOW_PLACER);
} }
}
/**
* Shows this popup window unless popups are disabled as reported by
* {@link DockingUtils#isTipWindowEnabled()}.
* @param e the event
*/
public void showPopup(MouseEvent e) { public void showPopup(MouseEvent e) {
showPopup(e, false);
}
/**
* Shows this popup window unless popups are disabled as reported by
* {@link DockingUtils#isTipWindowEnabled()}. If {@code forceShow} is true, then the popup
* will be shown regardless of the state returned by {@link DockingUtils#isTipWindowEnabled()}.
* @param e the event
* @param forceShow true to show the popup even popups are disabled application-wide
*/
public void showPopup(MouseEvent e, boolean forceShow) {
if (forceShow || DockingUtils.isTipWindowEnabled()) {
doShowPopup(e, null, DEFAULT_WINDOW_PLACER); doShowPopup(e, null, DEFAULT_WINDOW_PLACER);
} }
}
private void doShowPopup(MouseEvent e, Rectangle keepVisibleSize, PopupWindowPlacer placer) { private void doShowPopup(MouseEvent e, Rectangle keepVisibleSize, PopupWindowPlacer placer) {
hideAllWindows(); hideAllWindows();

View file

@ -90,6 +90,7 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
public static final String DEFAULT_TOOL_LAUNCH_MODE = "Default Tool Launch Mode"; public static final String DEFAULT_TOOL_LAUNCH_MODE = "Default Tool Launch Mode";
public static final String AUTOMATICALLY_SAVE_TOOLS = "Automatically Save Tools"; public static final String AUTOMATICALLY_SAVE_TOOLS = "Automatically Save Tools";
private static final String USE_ALERT_ANIMATION_OPTION_NAME = "Use Notification Animation"; private static final String USE_ALERT_ANIMATION_OPTION_NAME = "Use Notification Animation";
private static final String SHOW_TOOLTIPS_OPTION_NAME = "Show Tooltips";
// TODO: Experimental Option !! // TODO: Experimental Option !!
private static final String ENABLE_COMPRESSED_DATABUFFER_OUTPUT = private static final String ENABLE_COMPRESSED_DATABUFFER_OUTPUT =
@ -338,11 +339,13 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
options.registerOption(USE_ALERT_ANIMATION_OPTION_NAME, true, help, options.registerOption(USE_ALERT_ANIMATION_OPTION_NAME, true, help,
"Signals that user notifications should be animated. This makes notifications more " + "Signals that user notifications should be animated. This makes notifications more " +
"distinguishable."); "distinguishable.");
options.registerOption(ENABLE_COMPRESSED_DATABUFFER_OUTPUT, Boolean.FALSE, help, options.registerOption(SHOW_TOOLTIPS_OPTION_NAME, true, help,
"Controls the display of tooltip popup windows.");
options.registerOption(ENABLE_COMPRESSED_DATABUFFER_OUTPUT, false, help,
"When enabled data buffers sent to Ghidra Server are compressed (see server " + "When enabled data buffers sent to Ghidra Server are compressed (see server " +
"configuration for other direction)"); "configuration for other direction)");
options.registerOption(RESTORE_PREVIOUS_PROJECT_NAME, Boolean.TRUE, help, options.registerOption(RESTORE_PREVIOUS_PROJECT_NAME, true, help,
"Restore the previous project when Ghidra starts."); "Restore the previous project when Ghidra starts.");
defaultLaunchMode = options.getEnum(DEFAULT_TOOL_LAUNCH_MODE, defaultLaunchMode); defaultLaunchMode = options.getEnum(DEFAULT_TOOL_LAUNCH_MODE, defaultLaunchMode);
@ -353,6 +356,9 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
boolean animationEnabled = options.getBoolean(USE_ALERT_ANIMATION_OPTION_NAME, true); boolean animationEnabled = options.getBoolean(USE_ALERT_ANIMATION_OPTION_NAME, true);
AnimationUtils.setAnimationEnabled(animationEnabled); AnimationUtils.setAnimationEnabled(animationEnabled);
boolean showToolTips = options.getBoolean(SHOW_TOOLTIPS_OPTION_NAME, true);
DockingUtils.setTipWindowEnabled(showToolTips);
boolean compressDataBuffers = boolean compressDataBuffers =
options.getBoolean(ENABLE_COMPRESSED_DATABUFFER_OUTPUT, false); options.getBoolean(ENABLE_COMPRESSED_DATABUFFER_OUTPUT, false);
DataBuffer.enableCompressedSerializationOutput(compressDataBuffers); DataBuffer.enableCompressedSerializationOutput(compressDataBuffers);
@ -374,6 +380,9 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
else if (USE_ALERT_ANIMATION_OPTION_NAME.equals(optionName)) { else if (USE_ALERT_ANIMATION_OPTION_NAME.equals(optionName)) {
AnimationUtils.setAnimationEnabled((Boolean) newValue); AnimationUtils.setAnimationEnabled((Boolean) newValue);
} }
else if (SHOW_TOOLTIPS_OPTION_NAME.equals(optionName)) {
DockingUtils.setTipWindowEnabled((Boolean) newValue);
}
else if (ENABLE_COMPRESSED_DATABUFFER_OUTPUT.equals(optionName)) { else if (ENABLE_COMPRESSED_DATABUFFER_OUTPUT.equals(optionName)) {
DataBuffer.enableCompressedSerializationOutput((Boolean) newValue); DataBuffer.enableCompressedSerializationOutput((Boolean) newValue);
} }