Merge remote-tracking branch 'origin/GP-1-dragonmacher-tab-icon-fix'

This commit is contained in:
Ryan Kurtz
2026-02-02 13:25:16 -05:00
6 changed files with 46 additions and 19 deletions

View File

@@ -90,6 +90,7 @@ class ViewPanel extends JPanel implements ChangeListener {
tabbedPane.insertTab(name, null, viewComponent, null, insertIndex);
tabbedPane.setTabComponentAt(insertIndex, new DockingTabRenderer(tabbedPane, name,
name, e -> closeView(getViewProviderForComponent(viewComponent), true)));
tabbedPane.setTitleAt(insertIndex, name);
}
finally {
tabbedPane.addChangeListener(this);
@@ -252,6 +253,7 @@ class ViewPanel extends JPanel implements ChangeListener {
if (c == vps.getViewComponent()) {
DockingTabRenderer renderer = (DockingTabRenderer) tabbedPane.getTabComponentAt(i);
renderer.setTitle(viewName, viewName);
tabbedPane.setTitleAt(i, viewName);
break;
}
}
@@ -465,6 +467,7 @@ class ViewPanel extends JPanel implements ChangeListener {
DockingTabRenderer renderer =
(DockingTabRenderer) tabbedPane.getTabComponentAt(selectedIndex);
renderer.setTitle(newName, newName);
tabbedPane.setTitleAt(selectedIndex, newName);
map.remove(oldName);
map.put(newName, vps);
}

View File

@@ -751,16 +751,21 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
Function function = controller.getDecompileData().getFunction();
String programName = (program != null) ? program.getDomainFile().getName() : "";
String title = "Decompiler";
String functionName = "No Function";
String tabText = "Decompiler";
String subTitle = "";
if (function != null) {
title = "Decompile: " + function.getName();
functionName = function.getName();
title = "Decompile: " + functionName;
subTitle = " (" + programName + ")";
}
if (!isConnected()) {
title = "[" + title + "]";
tabText = "[" + functionName + "]";
}
setTitle(title);
setSubTitle(subTitle);
setTabText(tabText);
}
private void initializeDecompilerOptions() {

View File

@@ -29,7 +29,6 @@ import docking.action.*;
import docking.options.OptionsService;
import docking.widgets.fieldpanel.FieldPanel;
import edu.uci.ics.jung.graph.Graph;
import generic.stl.Pair;
import generic.theme.GIcon;
import ghidra.app.context.ListingActionContext;
import ghidra.app.nav.*;
@@ -426,41 +425,47 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
}
private void updateTitle() {
Pair<String, String> result = getTitleFromGraphData("Function Graph");
String title = result.first;
String subTitle = result.second;
GraphTitle graphTitle = getTitleFromGraphData("Function Graph");
String title = graphTitle.title;
String subTitle = graphTitle.subTitle;
String tabText = "Function Graph";
if (!isConnected()) {
title = "[" + title + "]";
tabText = "[" + graphTitle.functionName + "]";
}
setTitle(title);
setSubTitle(subTitle);
setTabText(tabText);
}
private Pair<String, String> getTitleFromGraphData(String title) {
private GraphTitle getTitleFromGraphData(String title) {
FGData graphData = controller.getFunctionGraphData();
Pair<String, String> result = new Pair<>(title, "");
if (graphData == null) {
return result;
return new GraphTitle(title, "", "");
}
Function function = graphData.getFunction();
if (function == null) {
return result;
return new GraphTitle(title, "", "");
}
FunctionGraph functionGraph = graphData.getFunctionGraph();
Graph<FGVertex, FGEdge> graph = functionGraph;
String first = "Function Graph";
String functionName = function.getName();
String programName =
(currentProgram != null) ? currentProgram.getDomainFile().getName() : "";
String second = function.getName() + " - " + graph.getVertexCount() + " vertices (" +
String subTitle = functionName + " - " + graph.getVertexCount() + " vertices (" +
programName + ")";
return new Pair<>(first, second);
return new GraphTitle(title, subTitle, functionName);
}
private record GraphTitle(String title, String subTitle, String functionName) {
}
void doSetProgram(Program newProgram) {

View File

@@ -323,10 +323,11 @@ class ComponentNode extends Node {
tabRenderer.installPopupMenu(createTabPopupMenu(activeComponents, placeholder));
tabbedPane.setTabComponentAt(i, tabRenderer);
Icon icon = placeholder.getIcon();
if (icon != null) {
tabRenderer.setIcon(icon);
}
tabbedPane.setTitleAt(i, tabText);
tabbedPane.setIconAt(i, icon);
tabRenderer.setIcon(icon);
if (placeholder == top) {
activeIndex = i;
@@ -575,11 +576,14 @@ class ComponentNode extends Node {
}
DockingTabRenderer renderer = (DockingTabRenderer) pane.getTabComponentAt(index);
renderer.setIcon(placeholder.getIcon());
Icon icon = placeholder.getIcon();
renderer.setIcon(icon);
pane.setIconAt(index, icon);
String tabText = placeholder.getTabText();
String fullTitle = placeholder.getTitle();
renderer.setTitle(tabText, fullTitle);
pane.setTitleAt(index, tabText);
}
public void iconChanged(ComponentPlaceholder placeholder) {

View File

@@ -146,9 +146,17 @@ public class DockingTabRenderer extends JPanel {
// don't include both when the tab text is a subset of the title
titleLabel.setToolTipText(fullTitle);
}
else {
// both are different, include both
titleLabel.setToolTipText("<html><b>" + tabText + "</b> - [" + fullTitle + "]");
else { // both are different, include both
// Guilty Knowledge: we know that some providers use '[]' for the title and tab text
// of disconnected providers.
//
// We would like to use the '[]' characters to separate the tab text from the title.
// Strip off the client brackets and use ours for the title part of the tooltip.
String rawTabText = tabText.replaceAll("\\[", "").replaceAll("\\]", "");
String rawTitle = fullTitle.replaceAll("\\[", "").replaceAll("\\]", "");
String html = "<html><b>%s</b> - [%s]".formatted(rawTabText, rawTitle);
titleLabel.setToolTipText(html);
}
}

View File

@@ -144,6 +144,7 @@ class ProjectDataPanel extends JSplitPane implements ProjectViewListener {
int index = readOnlyTab.indexOfComponent(dtp);
readOnlyTab.setTabComponentAt(index, new DockingTabRenderer(readOnlyTab, viewName,
viewName, e -> viewRemoved(dtp, getProjectURL(dtp), true)));
readOnlyTab.setTitleAt(index, viewName);
readOnlyViews.put(view, dtp);
}
catch (Exception e) {
@@ -232,6 +233,7 @@ class ProjectDataPanel extends JSplitPane implements ProjectViewListener {
int index = readOnlyTab.indexOfComponent(newPanel);
readOnlyTab.setTabComponentAt(index, new DockingTabRenderer(readOnlyTab, viewName,
viewName, e -> viewRemoved(newPanel, getProjectURL(newPanel), true)));
readOnlyTab.setTitleAt(index, viewName);
readOnlyTab.setSelectedIndex(0);
readOnlyViews.put(projectData.getProjectLocator(), newPanel);
setViewsVisible(true);