Merge remote-tracking branch 'origin/GP-2841-dragonmacher-program-name-tooltips--SQUASHED'

This commit is contained in:
Ryan Kurtz
2023-01-13 13:10:11 -05:00
2 changed files with 50 additions and 34 deletions
@@ -35,7 +35,7 @@ import ghidra.util.layout.HorizontalLayout;
import resources.Icons;
/**
* Panel to show a "tab" for an object. ChangeListeners are notified when a tab is selected.
* Panel to show a "tab" for an object. ChangeListeners are notified when a tab is selected.
*/
public class MultiTabPanel extends JPanel {
private static final String FONT_TABS_ID = "font.plugin.tabs";
@@ -49,17 +49,13 @@ public class MultiTabPanel extends JPanel {
private final static Icon HIGHLIGHT_CLOSE_ICON = new GIcon("icon.plugin.programmanager.close.highlight");
private final static Icon LIST_ICON = new GIcon("icon.plugin.programmanager.list");
private final static Icon TRANSIENT_ICON = new GIcon("icon.plugin.programmanager.transient");
//@formatter:on
private final static Color TEXT_SELECTION_COLOR =
new GColor("color.fg.listing.tabs.text.selected");
private final static Color TEXT_NON_SELECTION_COLOR =
new GColor("color.fg.listing.tabs.text.unselected");
private final static Color TEXT_SELECTION_COLOR = new GColor("color.fg.listing.tabs.text.selected");
private final static Color TEXT_NON_SELECTION_COLOR = new GColor("color.fg.listing.tabs.text.unselected");
private final static Color BG_SELECTION_COLOR = SELECTED_TAB_COLOR;
private final static Color BG_NON_SELECTION_COLOR =
new GColor("color.bg.listing.tabs.unselected");
private static final Color BG_COLOR_MORE_TABS_HOVER =
new GColor("color.bg.listing.tabs.more.tabs.hover");
private final static Color BG_NON_SELECTION_COLOR = new GColor("color.bg.listing.tabs.unselected");
private static final Color BG_COLOR_MORE_TABS_HOVER = new GColor("color.bg.listing.tabs.more.tabs.hover");
//@formatter:on
private static final String DEFAULT_HIDDEN_COUNT_STR = "99";
@@ -85,7 +81,6 @@ public class MultiTabPanel extends JPanel {
private boolean ignoreFocus;
MultiTabPanel(MultiTabPlugin multiTabPlugin) {
super();
this.multiTabPlugin = multiTabPlugin;
setLayout(new HorizontalLayout(0));
@@ -145,7 +140,7 @@ public class MultiTabPanel extends JPanel {
}
/**
* Refresh label displayed in the tab for the given object.
* Refresh label displayed in the tab for the given object.
* @param program object associated with a tab
*/
void refresh(Program program) {
@@ -555,8 +550,8 @@ public class MultiTabPanel extends JPanel {
newVisibleTabList.add(panel);
}
// check for the boundary condition where all elements would fit in the display if we
// don't show the label indicating tabs are hidden. The boundary case is when there
// check for the boundary condition where all elements would fit in the display if we
// don't show the label indicating tabs are hidden. The boundary case is when there
// is only one hidden element that could potentially be put into the view
if (allTabsList.size() - newVisibleTabList.size() == 1) {
TabPanel lastPanel = allTabsList.get(allTabsList.size() - 1);
@@ -599,7 +594,7 @@ public class MultiTabPanel extends JPanel {
usedWidth += panel.getPreferredSize().width;
}
// remove items from the end of the visible list until we have room for the current tab
// remove items from the end of the visible list until we have room for the current tab
for (int i = newVisibleTabList.size() - 1; i >= 0; i--) {
TabPanel lastPanel = newVisibleTabList.remove(i);
int width = lastPanel.getPreferredSize().width;
@@ -790,7 +785,7 @@ public class MultiTabPanel extends JPanel {
list.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent focusEvent) {
// close the window when the user focuses another component
// close the window when the user focuses another component
if (focusEvent.getOppositeComponent() != filterField) {
hideListWindowDueToFocusChange();
}
@@ -912,7 +907,7 @@ public class MultiTabPanel extends JPanel {
//==================================================================================================
// Inner Classes
//==================================================================================================
//==================================================================================================
private class TabPanel extends JPanel {
private Color defaultBgColor;
@@ -963,7 +958,7 @@ public class MultiTabPanel extends JPanel {
}
}
// a panel that paints below it's bounds in order to connect the panel and the border
// a panel that paints below it's bounds in order to connect the panel and the border
// below it visually
private class SelectedPanel extends TabPanel {
private SelectedPanel(Color backgroundColor, Program program, JLabel nameLabel,
@@ -1005,8 +1000,8 @@ public class MultiTabPanel extends JPanel {
}
}
// This class doesn't paint the bottom border in order to make the object appear to be
// connected to the component below. This class also paints its side borders below its
// This class doesn't paint the bottom border in order to make the object appear to be
// connected to the component below. This class also paints its side borders below its
// bounds for the same reason.
class BottomlessBevelBorder extends BevelBorder {
public BottomlessBevelBorder() {
@@ -1014,7 +1009,7 @@ public class MultiTabPanel extends JPanel {
}
@Override
// overridden to reduce the space below, since there is no component
// overridden to reduce the space below, since there is no component
public Insets getBorderInsets(Component c) {
Insets borderInsets = super.getBorderInsets(c);
borderInsets.bottom = 0;
@@ -1079,7 +1074,7 @@ public class MultiTabPanel extends JPanel {
g.setColor(getHighlightOuterColor(c));
g.drawLine(0, h - 1, w - 1, h - 1);
// bottom inner
// bottom inner
g.setColor(getShadowInnerColor(c));
g.translate(-x, -y);
@@ -58,7 +58,7 @@ public class MultiTabPlugin extends Plugin implements DomainObjectListener {
// Unusual Code Alert!: We can't initialize these in the fields above because calling
// DockingUtils calls into Swing code. Further, we don't want Swing code being accessed
// when the Plugin classes are loaded, as they get loaded in the headless environment.
//
//
private final KeyStroke NEXT_TAB_KEYSTROKE =
KeyStroke.getKeyStroke(KeyEvent.VK_F9, DockingUtils.CONTROL_KEY_MODIFIER_MASK);
private final KeyStroke PREVIOUS_TAB_KEYSTROKE =
@@ -96,14 +96,14 @@ public class MultiTabPlugin extends Plugin implements DomainObjectListener {
goToProgramAction.setMenuBarData(
new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, "Go To Program..." }, null,
ToolConstants.MENU_NAVIGATION_GROUP_WINDOWS, MenuData.NO_MNEMONIC, firstGroup));
goToProgramAction.setKeyBindingData(
new KeyBindingData(KeyEvent.VK_F7, InputEvent.CTRL_DOWN_MASK));
goToProgramAction
.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F7, InputEvent.CTRL_DOWN_MASK));
goToProgramAction.setEnabled(false);
goToProgramAction.setDescription(
"Shows the program selection dialog with the current program selected");
goToProgramAction.setHelpLocation(
new HelpLocation("ProgramManagerPlugin", "Go_To_Program"));
goToProgramAction
.setHelpLocation(new HelpLocation("ProgramManagerPlugin", "Go_To_Program"));
goToNextProgramAction = new DockingAction("Go To Next Program", getName()) {
@Override
@@ -133,7 +133,7 @@ public class MultiTabPlugin extends Plugin implements DomainObjectListener {
goToPreviousProgramAction.setHelpLocation(
new HelpLocation("ProgramManagerPlugin", "Go_To_Next_And_Previous_Program"));
// this timer is to give the user time to select successive programs before activating one
// this timer is to give the user time to select successive programs before activating one
selectHighlightedProgramTimer = new Timer(750, e -> selectHighlightedProgram());
selectHighlightedProgramTimer.setRepeats(false);
@@ -146,11 +146,11 @@ public class MultiTabPlugin extends Plugin implements DomainObjectListener {
goToLastActiveProgramAction.setMenuBarData(new MenuData(
new String[] { ToolConstants.MENU_NAVIGATION, "Go To Last Active Program" }, null,
ToolConstants.MENU_NAVIGATION_GROUP_WINDOWS, MenuData.NO_MNEMONIC, secondGroup));
goToLastActiveProgramAction.setKeyBindingData(
new KeyBindingData(KeyEvent.VK_F6, InputEvent.CTRL_DOWN_MASK));
goToLastActiveProgramAction
.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F6, InputEvent.CTRL_DOWN_MASK));
goToLastActiveProgramAction.setEnabled(false);
goToLastActiveProgramAction.setDescription(
"Activates the last program used before the current program");
goToLastActiveProgramAction
.setDescription("Activates the last program used before the current program");
goToLastActiveProgramAction.setHelpLocation(
new HelpLocation("ProgramManagerPlugin", "Go_To_Last_Active_Program"));
@@ -192,10 +192,31 @@ public class MultiTabPlugin extends Plugin implements DomainObjectListener {
String getStringUsedInList(Program program) {
DomainFile df = program.getDomainFile();
String changeIndicator = program.isChanged() ? "*" : "";
String pathString = getShortPath(df);
if (!df.isInWritableProject()) {
return df.toString() + " [Read-Only]" + changeIndicator;
return pathString + " [Read-Only]" + changeIndicator;
}
return df.toString() + changeIndicator;
return pathString + changeIndicator;
}
private String getShortPath(DomainFile df) {
String pathString = df.toString();
int length = pathString.length();
if (length < 100) {
return pathString;
}
String[] pathParts = pathString.split("/");
if (pathParts.length == 2) { // at least 2 for project name and filename
return pathString;
}
String projectName = df.getProjectLocator().getName();
int parentFolderIndex = pathParts.length - 2;
String parentName = pathParts[parentFolderIndex];
String filename = df.getName();
pathString = projectName + ":/.../" + parentName + "/" + filename;
return pathString;
}
String getToolTip(Program program) {