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

View File

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

View File

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

View File

@@ -323,10 +323,11 @@ class ComponentNode extends Node {
tabRenderer.installPopupMenu(createTabPopupMenu(activeComponents, placeholder)); tabRenderer.installPopupMenu(createTabPopupMenu(activeComponents, placeholder));
tabbedPane.setTabComponentAt(i, tabRenderer); tabbedPane.setTabComponentAt(i, tabRenderer);
Icon icon = placeholder.getIcon(); Icon icon = placeholder.getIcon();
if (icon != null) { tabbedPane.setTitleAt(i, tabText);
tabRenderer.setIcon(icon); tabbedPane.setIconAt(i, icon);
} tabRenderer.setIcon(icon);
if (placeholder == top) { if (placeholder == top) {
activeIndex = i; activeIndex = i;
@@ -575,11 +576,14 @@ class ComponentNode extends Node {
} }
DockingTabRenderer renderer = (DockingTabRenderer) pane.getTabComponentAt(index); 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 tabText = placeholder.getTabText();
String fullTitle = placeholder.getTitle(); String fullTitle = placeholder.getTitle();
renderer.setTitle(tabText, fullTitle); renderer.setTitle(tabText, fullTitle);
pane.setTitleAt(index, tabText);
} }
public void iconChanged(ComponentPlaceholder placeholder) { 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 // don't include both when the tab text is a subset of the title
titleLabel.setToolTipText(fullTitle); titleLabel.setToolTipText(fullTitle);
} }
else { else { // both are different, include both
// both are different, include both
titleLabel.setToolTipText("<html><b>" + tabText + "</b> - [" + fullTitle + "]"); // 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); int index = readOnlyTab.indexOfComponent(dtp);
readOnlyTab.setTabComponentAt(index, new DockingTabRenderer(readOnlyTab, viewName, readOnlyTab.setTabComponentAt(index, new DockingTabRenderer(readOnlyTab, viewName,
viewName, e -> viewRemoved(dtp, getProjectURL(dtp), true))); viewName, e -> viewRemoved(dtp, getProjectURL(dtp), true)));
readOnlyTab.setTitleAt(index, viewName);
readOnlyViews.put(view, dtp); readOnlyViews.put(view, dtp);
} }
catch (Exception e) { catch (Exception e) {
@@ -232,6 +233,7 @@ class ProjectDataPanel extends JSplitPane implements ProjectViewListener {
int index = readOnlyTab.indexOfComponent(newPanel); int index = readOnlyTab.indexOfComponent(newPanel);
readOnlyTab.setTabComponentAt(index, new DockingTabRenderer(readOnlyTab, viewName, readOnlyTab.setTabComponentAt(index, new DockingTabRenderer(readOnlyTab, viewName,
viewName, e -> viewRemoved(newPanel, getProjectURL(newPanel), true))); viewName, e -> viewRemoved(newPanel, getProjectURL(newPanel), true)));
readOnlyTab.setTitleAt(index, viewName);
readOnlyTab.setSelectedIndex(0); readOnlyTab.setSelectedIndex(0);
readOnlyViews.put(projectData.getProjectLocator(), newPanel); readOnlyViews.put(projectData.getProjectLocator(), newPanel);
setViewsVisible(true); setViewsVisible(true);