From e228b9bcbb663c7add69f5d7d781b4caf652c506 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 16 Jan 2026 18:08:35 +0000 Subject: [PATCH] GP-6025: Use fixed-width fonts in Value and Address columns. --- .../register/DebuggerRegistersProvider.java | 17 ++++--- .../debug/gui/stack/DebuggerStackPanel.java | 16 +++++++ .../gui/time/DebuggerSnapshotTablePanel.java | 45 +++++++++++++++++-- .../gui/watch/DebuggerWatchesProvider.java | 28 ++++++++---- 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java index 6de9fe339e..ab7390f161 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/register/DebuggerRegistersProvider.java @@ -141,11 +141,11 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter protected enum RegisterTableColumns implements EnumeratedTableColumn { - FAV("Fav", 1, Boolean.class, RegisterRow::isFavorite, RegisterRow::setFavorite, // - r -> true, SortDirection.DESCENDING), + FAV("Fav", 1, Boolean.class, RegisterRow::isFavorite, RegisterRow::setFavorite, r -> true, + SortDirection.DESCENDING), NUMBER("#", 1, Integer.class, RegisterRow::getNumber), NAME("Name", 40, String.class, RegisterRow::getName), - VALUE("Value", 100, BigInteger.class, RegisterRow::getValue, RegisterRow::setValue, // + VALUE("Value", 100, BigInteger.class, RegisterRow::getValue, RegisterRow::setValue, RegisterRow::isValueEditable, SortDirection.ASCENDING) { private static final RegisterValueCellRenderer RENDERER = new RegisterValueCellRenderer(); @@ -162,10 +162,11 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter return DEFS; } }, - TYPE("Type", 40, DataType.class, RegisterRow::getDataType, RegisterRow::setDataType, // + TYPE("Type", 40, DataType.class, RegisterRow::getDataType, RegisterRow::setDataType, r -> true, SortDirection.ASCENDING), - REPR("Repr", 100, String.class, RegisterRow::getRepresentation, RegisterRow::setRepresentation, // - RegisterRow::isRepresentationEditable, SortDirection.ASCENDING); + REPR("Repr", 100, String.class, RegisterRow::getRepresentation, + RegisterRow::setRepresentation, RegisterRow::isRepresentationEditable, + SortDirection.ASCENDING); private final String header; private final int width; @@ -414,6 +415,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter @Override public final Component getTableCellRendererComponent(GTableCellRenderingData data) { super.getTableCellRendererComponent(data); + setFont(getFixedWidthFont()); RegisterRow row = (RegisterRow) data.getRowObject(); if (!row.isKnown()) { if (data.isSelected()) { @@ -1099,9 +1101,6 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter result.add(pc); } for (Register reg : lang.getRegisters()) { - //if (reg.getGroup() != null) { - // continue; - //} if (reg.isProcessorContext()) { continue; } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java index e42bf5b02a..85473683ec 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/stack/DebuggerStackPanel.java @@ -66,6 +66,22 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel getProperty(ValueRow row) { + return new ValueAddressProperty(row) { + @Override + public Address getValue() { + TraceObjectValue entry = row.getAttributeEntry(attributeName); + return entry.getValue() instanceof Address addr ? addr : null; + } + + @Override + public boolean isModified() { + return row.isAttributeModified(attributeName); + } + }; + } } static Address computeProgramCounter(ValueRow row, long snap) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/DebuggerSnapshotTablePanel.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/DebuggerSnapshotTablePanel.java index 0cec92c03c..4547c352d7 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/DebuggerSnapshotTablePanel.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/time/DebuggerSnapshotTablePanel.java @@ -59,10 +59,11 @@ public class DebuggerSnapshotTablePanel extends JPanel { EVENT_THREAD("Event Thread", String.class, SnapshotRow::getEventThreadName, true), PC("PC", Address.class, SnapshotRow::getProgramCounter, true), MODULE("Module", String.class, SnapshotRow::getModuleName, true), - FUNCTION("Function", ghidra.program.model.listing.Function.class, SnapshotRow::getFunction, true), + FUNCTION("Function", ghidra.program.model.listing.Function.class, SnapshotRow::getFunction, + true), TIMESTAMP("Timestamp", Date.class, SnapshotRow::getTimeStamp, false), SCHEDULE("Schedule", TraceSchedule.class, SnapshotRow::getSchedule, false), - DESCRIPTION("Description", String.class, SnapshotRow::getDescription, // + DESCRIPTION("Description", String.class, SnapshotRow::getDescription, SnapshotRow::setDescription, true); private final String header; @@ -212,6 +213,39 @@ public class DebuggerSnapshotTablePanel extends JPanel { }; } + Font lastFixedWidthFont; + Font fixedWidthBoldFont; + Font fixedWidthItalicFont; + + Font computePlainFont(GTableCellRenderingData data) { + return data.getValue() instanceof Address ? getFixedWidthFont() : getDefaultFont(); + } + + void checkDeriveNewFonts() { + if (Objects.equals(lastFixedWidthFont, getFixedWidthFont())) { + return; + } + lastFixedWidthFont = getFixedWidthFont(); + fixedWidthBoldFont = lastFixedWidthFont.deriveFont(Font.BOLD); + fixedWidthItalicFont = lastFixedWidthFont.deriveFont(Font.ITALIC); + } + + Font computeBoldFont(GTableCellRenderingData data) { + if (data.getValue() instanceof Address) { + checkDeriveNewFonts(); + return fixedWidthBoldFont; + } + return getBoldFont(); + } + + Font computeItalicFont(GTableCellRenderingData data) { + if (data.getValue() instanceof Address) { + checkDeriveNewFonts(); + return fixedWidthItalicFont; + } + return getItalicFont(); + } + @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { super.getTableCellRendererComponent(data); @@ -221,10 +255,13 @@ public class DebuggerSnapshotTablePanel extends JPanel { return this; } if (current.getViewSnap() == row.getSnap()) { - setBold(); + setFont(computeBoldFont(data)); } else if (current.getSnap() == row.getSnap()) { - setItalic(); + setFont(computeItalicFont(data)); + } + else { + setFont(computePlainFont(data)); } TraceSnapshot snapshot = row.getSnapshot(); diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java index b4382b6688..4c09294e21 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java @@ -85,6 +85,7 @@ import ghidra.util.exception.CancelledException; import ghidra.util.table.GhidraTable; import ghidra.util.table.GhidraTableFilterPanel; import ghidra.util.table.column.AbstractGColumnRenderer; +import ghidra.util.table.column.GColumnRenderer; public class DebuggerWatchesProvider extends ComponentProviderAdapter implements DebuggerWatchesService { @@ -151,12 +152,24 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter implements EnumeratedTableColumn { EXPRESSION("Expression", String.class, WatchRow::getExpression, WatchRow::setExpression), COMMENT("Comment", String.class, WatchRow::getComment, WatchRow::setComment), - ADDRESS("Address", Address.class, WatchRow::getAddress), + ADDRESS("Address", Address.class, WatchRow::getAddress) { + @Override + public GColumnRenderer getRenderer() { + return CustomToStringCellRenderer.MONO_OBJECT; + } + }, SYMBOL("Symbol", Symbol.class, WatchRow::getSymbol), - VALUE("Value", String.class, WatchRow::getRawValueString, WatchRow::setRawValueString, // - WatchRow::isRawValueEditable), + VALUE("Value", String.class, WatchRow::getRawValueString, WatchRow::setRawValueString, + WatchRow::isRawValueEditable) { + private static final WatchValueCellRenderer RENDERER = new WatchValueCellRenderer(); + + @Override + public GColumnRenderer getRenderer() { + return RENDERER; + } + }, TYPE("Type", DataType.class, WatchRow::getDataType, WatchRow::setDataType), - REPR("Repr", String.class, WatchRow::getValueString, WatchRow::setValueString, // + REPR("Repr", String.class, WatchRow::getValueString, WatchRow::setValueString, WatchRow::isValueEditable), ERROR("Error", String.class, WatchRow::getErrorMessage); @@ -292,10 +305,11 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter } } - class WatchValueCellRenderer extends AbstractGColumnRenderer { + static class WatchValueCellRenderer extends AbstractGColumnRenderer { @Override public Component getTableCellRendererComponent(GTableCellRenderingData data) { super.getTableCellRendererComponent(data); + setFont(getFixedWidthFont()); WatchRow row = (WatchRow) data.getRowObject(); if (!row.isKnown()) { if (data.isSelected()) { @@ -453,10 +467,6 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter }); TableColumnModel columnModel = watchTable.getColumnModel(); - TableColumn addrCol = columnModel.getColumn(WatchTableColumns.ADDRESS.ordinal()); - addrCol.setCellRenderer(CustomToStringCellRenderer.MONO_OBJECT); - TableColumn valCol = columnModel.getColumn(WatchTableColumns.VALUE.ordinal()); - valCol.setCellRenderer(new WatchValueCellRenderer()); TableColumn typeCol = columnModel.getColumn(WatchTableColumns.TYPE.ordinal()); typeCol.setCellEditor(new WatchDataTypeEditor()); }