Skip to content

Commit 6a74016

Browse files
committed
GO-2841 - Updated handling of long program paths in Listing tabs
1 parent 58ccc22 commit 6a74016

File tree

2 files changed

+50
-34
lines changed

2 files changed

+50
-34
lines changed

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiTabPanel.java

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import resources.Icons;
3636

3737
/**
38-
* Panel to show a "tab" for an object. ChangeListeners are notified when a tab is selected.
38+
* Panel to show a "tab" for an object. ChangeListeners are notified when a tab is selected.
3939
*/
4040
public class MultiTabPanel extends JPanel {
4141
private static final String FONT_TABS_ID = "font.plugin.tabs";
@@ -49,17 +49,13 @@ public class MultiTabPanel extends JPanel {
4949
private final static Icon HIGHLIGHT_CLOSE_ICON = new GIcon("icon.plugin.programmanager.close.highlight");
5050
private final static Icon LIST_ICON = new GIcon("icon.plugin.programmanager.list");
5151
private final static Icon TRANSIENT_ICON = new GIcon("icon.plugin.programmanager.transient");
52-
//@formatter:on
5352

54-
private final static Color TEXT_SELECTION_COLOR =
55-
new GColor("color.fg.listing.tabs.text.selected");
56-
private final static Color TEXT_NON_SELECTION_COLOR =
57-
new GColor("color.fg.listing.tabs.text.unselected");
53+
private final static Color TEXT_SELECTION_COLOR = new GColor("color.fg.listing.tabs.text.selected");
54+
private final static Color TEXT_NON_SELECTION_COLOR = new GColor("color.fg.listing.tabs.text.unselected");
5855
private final static Color BG_SELECTION_COLOR = SELECTED_TAB_COLOR;
59-
private final static Color BG_NON_SELECTION_COLOR =
60-
new GColor("color.bg.listing.tabs.unselected");
61-
private static final Color BG_COLOR_MORE_TABS_HOVER =
62-
new GColor("color.bg.listing.tabs.more.tabs.hover");
56+
private final static Color BG_NON_SELECTION_COLOR = new GColor("color.bg.listing.tabs.unselected");
57+
private static final Color BG_COLOR_MORE_TABS_HOVER = new GColor("color.bg.listing.tabs.more.tabs.hover");
58+
//@formatter:on
6359

6460
private static final String DEFAULT_HIDDEN_COUNT_STR = "99";
6561

@@ -85,7 +81,6 @@ public class MultiTabPanel extends JPanel {
8581
private boolean ignoreFocus;
8682

8783
MultiTabPanel(MultiTabPlugin multiTabPlugin) {
88-
super();
8984
this.multiTabPlugin = multiTabPlugin;
9085
setLayout(new HorizontalLayout(0));
9186

@@ -145,7 +140,7 @@ Program getSelectedProgram() {
145140
}
146141

147142
/**
148-
* Refresh label displayed in the tab for the given object.
143+
* Refresh label displayed in the tab for the given object.
149144
* @param program object associated with a tab
150145
*/
151146
void refresh(Program program) {
@@ -555,8 +550,8 @@ private List<TabPanel> getTabsThatFitInView() {
555550
newVisibleTabList.add(panel);
556551
}
557552

558-
// check for the boundary condition where all elements would fit in the display if we
559-
// don't show the label indicating tabs are hidden. The boundary case is when there
553+
// check for the boundary condition where all elements would fit in the display if we
554+
// don't show the label indicating tabs are hidden. The boundary case is when there
560555
// is only one hidden element that could potentially be put into the view
561556
if (allTabsList.size() - newVisibleTabList.size() == 1) {
562557
TabPanel lastPanel = allTabsList.get(allTabsList.size() - 1);
@@ -599,7 +594,7 @@ private List<TabPanel> ensureCurrentProgramTabInView(Program activeProgram,
599594
usedWidth += panel.getPreferredSize().width;
600595
}
601596

602-
// remove items from the end of the visible list until we have room for the current tab
597+
// remove items from the end of the visible list until we have room for the current tab
603598
for (int i = newVisibleTabList.size() - 1; i >= 0; i--) {
604599
TabPanel lastPanel = newVisibleTabList.remove(i);
605600
int width = lastPanel.getPreferredSize().width;
@@ -790,7 +785,7 @@ else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
790785
list.addFocusListener(new FocusAdapter() {
791786
@Override
792787
public void focusLost(FocusEvent focusEvent) {
793-
// close the window when the user focuses another component
788+
// close the window when the user focuses another component
794789
if (focusEvent.getOppositeComponent() != filterField) {
795790
hideListWindowDueToFocusChange();
796791
}
@@ -912,7 +907,7 @@ private String getProgramName(Program program) {
912907

913908
//==================================================================================================
914909
// Inner Classes
915-
//==================================================================================================
910+
//==================================================================================================
916911

917912
private class TabPanel extends JPanel {
918913
private Color defaultBgColor;
@@ -963,7 +958,7 @@ void paintHighlightedColor(boolean paintHighlight) {
963958
}
964959
}
965960

966-
// a panel that paints below it's bounds in order to connect the panel and the border
961+
// a panel that paints below it's bounds in order to connect the panel and the border
967962
// below it visually
968963
private class SelectedPanel extends TabPanel {
969964
private SelectedPanel(Color backgroundColor, Program program, JLabel nameLabel,
@@ -1005,16 +1000,16 @@ void paintHighlightedColor(boolean paintHighlight) {
10051000
}
10061001
}
10071002

1008-
// This class doesn't paint the bottom border in order to make the object appear to be
1009-
// connected to the component below. This class also paints its side borders below its
1003+
// This class doesn't paint the bottom border in order to make the object appear to be
1004+
// connected to the component below. This class also paints its side borders below its
10101005
// bounds for the same reason.
10111006
class BottomlessBevelBorder extends BevelBorder {
10121007
public BottomlessBevelBorder() {
10131008
super(RAISED);
10141009
}
10151010

10161011
@Override
1017-
// overridden to reduce the space below, since there is no component
1012+
// overridden to reduce the space below, since there is no component
10181013
public Insets getBorderInsets(Component c) {
10191014
Insets borderInsets = super.getBorderInsets(c);
10201015
borderInsets.bottom = 0;
@@ -1079,7 +1074,7 @@ protected void paintRaisedBevel(Component c, Graphics g, int x, int y, int width
10791074
g.setColor(getHighlightOuterColor(c));
10801075
g.drawLine(0, h - 1, w - 1, h - 1);
10811076

1082-
// bottom inner
1077+
// bottom inner
10831078
g.setColor(getShadowInnerColor(c));
10841079

10851080
g.translate(-x, -y);

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/MultiTabPlugin.java

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public class MultiTabPlugin extends Plugin implements DomainObjectListener {
5858
// Unusual Code Alert!: We can't initialize these in the fields above because calling
5959
// DockingUtils calls into Swing code. Further, we don't want Swing code being accessed
6060
// when the Plugin classes are loaded, as they get loaded in the headless environment.
61-
//
61+
//
6262
private final KeyStroke NEXT_TAB_KEYSTROKE =
6363
KeyStroke.getKeyStroke(KeyEvent.VK_F9, DockingUtils.CONTROL_KEY_MODIFIER_MASK);
6464
private final KeyStroke PREVIOUS_TAB_KEYSTROKE =
@@ -96,14 +96,14 @@ public void actionPerformed(ActionContext context) {
9696
goToProgramAction.setMenuBarData(
9797
new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, "Go To Program..." }, null,
9898
ToolConstants.MENU_NAVIGATION_GROUP_WINDOWS, MenuData.NO_MNEMONIC, firstGroup));
99-
goToProgramAction.setKeyBindingData(
100-
new KeyBindingData(KeyEvent.VK_F7, InputEvent.CTRL_DOWN_MASK));
99+
goToProgramAction
100+
.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F7, InputEvent.CTRL_DOWN_MASK));
101101

102102
goToProgramAction.setEnabled(false);
103103
goToProgramAction.setDescription(
104104
"Shows the program selection dialog with the current program selected");
105-
goToProgramAction.setHelpLocation(
106-
new HelpLocation("ProgramManagerPlugin", "Go_To_Program"));
105+
goToProgramAction
106+
.setHelpLocation(new HelpLocation("ProgramManagerPlugin", "Go_To_Program"));
107107

108108
goToNextProgramAction = new DockingAction("Go To Next Program", getName()) {
109109
@Override
@@ -133,7 +133,7 @@ public void actionPerformed(ActionContext context) {
133133
goToPreviousProgramAction.setHelpLocation(
134134
new HelpLocation("ProgramManagerPlugin", "Go_To_Next_And_Previous_Program"));
135135

136-
// this timer is to give the user time to select successive programs before activating one
136+
// this timer is to give the user time to select successive programs before activating one
137137
selectHighlightedProgramTimer = new Timer(750, e -> selectHighlightedProgram());
138138
selectHighlightedProgramTimer.setRepeats(false);
139139

@@ -146,11 +146,11 @@ public void actionPerformed(ActionContext context) {
146146
goToLastActiveProgramAction.setMenuBarData(new MenuData(
147147
new String[] { ToolConstants.MENU_NAVIGATION, "Go To Last Active Program" }, null,
148148
ToolConstants.MENU_NAVIGATION_GROUP_WINDOWS, MenuData.NO_MNEMONIC, secondGroup));
149-
goToLastActiveProgramAction.setKeyBindingData(
150-
new KeyBindingData(KeyEvent.VK_F6, InputEvent.CTRL_DOWN_MASK));
149+
goToLastActiveProgramAction
150+
.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F6, InputEvent.CTRL_DOWN_MASK));
151151
goToLastActiveProgramAction.setEnabled(false);
152-
goToLastActiveProgramAction.setDescription(
153-
"Activates the last program used before the current program");
152+
goToLastActiveProgramAction
153+
.setDescription("Activates the last program used before the current program");
154154
goToLastActiveProgramAction.setHelpLocation(
155155
new HelpLocation("ProgramManagerPlugin", "Go_To_Last_Active_Program"));
156156

@@ -192,10 +192,31 @@ private void selectHighlightedProgram() {
192192
String getStringUsedInList(Program program) {
193193
DomainFile df = program.getDomainFile();
194194
String changeIndicator = program.isChanged() ? "*" : "";
195+
String pathString = getShortPath(df);
195196
if (!df.isInWritableProject()) {
196-
return df.toString() + " [Read-Only]" + changeIndicator;
197+
return pathString + " [Read-Only]" + changeIndicator;
198+
}
199+
return pathString + changeIndicator;
200+
}
201+
202+
private String getShortPath(DomainFile df) {
203+
String pathString = df.toString();
204+
int length = pathString.length();
205+
if (length < 100) {
206+
return pathString;
197207
}
198-
return df.toString() + changeIndicator;
208+
209+
String[] pathParts = pathString.split("/");
210+
if (pathParts.length == 2) { // at least 2 for project name and filename
211+
return pathString;
212+
}
213+
214+
String projectName = df.getProjectLocator().getName();
215+
int parentFolderIndex = pathParts.length - 2;
216+
String parentName = pathParts[parentFolderIndex];
217+
String filename = df.getName();
218+
pathString = projectName + ":/.../" + parentName + "/" + filename;
219+
return pathString;
199220
}
200221

201222
String getToolTip(Program program) {

0 commit comments

Comments
 (0)