diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServicePlugin.java index 94d0e740b0..62922cf1c3 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/model/DebuggerModelServicePlugin.java @@ -15,7 +15,7 @@ */ package ghidra.app.plugin.core.debug.service.model; -import static ghidra.app.plugin.core.debug.gui.DebuggerResources.showError; +import static ghidra.app.plugin.core.debug.gui.DebuggerResources.*; import java.io.IOException; import java.lang.invoke.MethodHandles; @@ -61,15 +61,8 @@ import ghidra.util.classfinder.ClassSearcher; import ghidra.util.datastruct.CollectionChangeListener; import ghidra.util.datastruct.ListenerSet; -@PluginInfo( - shortDescription = "Debugger models manager service", - description = "Manage debug sessions, connections, and trace recording", - category = PluginCategoryNames.DEBUGGER, - packageName = DebuggerPluginPackage.NAME, - status = PluginStatus.HIDDEN, - servicesRequired = {}, - servicesProvided = { - DebuggerModelService.class, }) +@PluginInfo(shortDescription = "Debugger models manager service", description = "Manage debug sessions, connections, and trace recording", category = PluginCategoryNames.DEBUGGER, packageName = DebuggerPluginPackage.NAME, status = PluginStatus.HIDDEN, servicesRequired = {}, servicesProvided = { + DebuggerModelService.class, }) public class DebuggerModelServicePlugin extends Plugin implements DebuggerModelServiceInternal, ApplicationLevelOnlyPlugin { @@ -111,7 +104,7 @@ public class DebuggerModelServicePlugin extends Plugin proxy.fireFocusEvent(focused); } } - }; + } protected class ListenerOnRecorders implements TraceRecorderListener { @Override @@ -186,6 +179,7 @@ public class DebuggerModelServicePlugin extends Plugin protected void createActions() { actionDisconnectAll = DisconnectAllAction.builder(this, this) .menuPath("Debugger", DisconnectAllAction.NAME) + .menuIcon(null) // our pattern is to no use icons in the main app window .onAction(this::activatedDisconnectAll) .buildAndInstall(tool); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index 840271f4bb..807b5fb0eb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -38,6 +38,7 @@ import docking.widgets.textpane.GHtmlTextPane; import docking.widgets.tree.*; import docking.widgets.tree.support.GTreeSelectionEvent.EventOrigin; import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; import ghidra.app.plugin.core.datamgr.actions.*; import ghidra.app.plugin.core.datamgr.actions.associate.*; import ghidra.app.plugin.core.datamgr.archive.*; @@ -442,6 +443,7 @@ public class DataTypesProvider extends ComponentProviderAdapter { previewPane = new GHtmlTextPane(); previewPane.setEditable(false); previewPane.setBorder(BorderFactory.createLoweredBevelBorder()); + previewPane.setBackground(Colors.BACKGROUND); // This listener responds to the user hovering/clicking the preview's hyperlinks previewPane.addHyperlinkListener(event -> { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java index e70bc184b9..31ff691576 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/AbstractInstructionTable.java @@ -91,9 +91,9 @@ public abstract class AbstractInstructionTable extends GhidraTable { * Returns the data object at the given cell location. We need to check * first to make sure the row/col values map to a valid cell. * - * @param row - * @param col - * @return + * @param row the row + * @param col the column + * @return the value */ public InstructionTableDataObject getCellData(int row, int col) { if (getModel() == null) { @@ -118,10 +118,6 @@ public abstract class AbstractInstructionTable extends GhidraTable { return renderer; } - /** - * - * @return - */ public JToolBar getToolbar() { return this.toolbar; } @@ -132,13 +128,16 @@ public abstract class AbstractInstructionTable extends GhidraTable { */ @Override protected void initDefaultRenderers() { + super.initDefaultRenderers(); setDefaultRenderer(InstructionTableDataObject.class, renderer); - defaultGTableRendererList.add(renderer); } /** * Returns the value of the {@link InstructionTableDataObject} for the given * cell (indicated by row and column name). + * @param row the row + * @param colName the column name + * @return the value */ protected String getColumnValue(int row, String colName) { for (int i = 0; i < this.getColumnCount(); i++) { @@ -161,11 +160,13 @@ public abstract class AbstractInstructionTable extends GhidraTable { /** * Clients must implement to create all the data objects used to render the * table. + * @return the row objects */ protected abstract InstructionTableDataObject[][] createDataObjects(); /** * Clients must implement to have a toolbar visible above the table. + * @return the toolbar */ protected abstract JToolBar createToolbar(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java index 884a93febd..ebb81e91ad 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptTableModel.java @@ -259,7 +259,7 @@ class GhidraScriptTableModel extends GDynamicColumnTableModel extends AbstractGCellRenderer implements ListC setBackground(Palette.CYAN); } else { - setBackground(getOSDependentBackgroundColor(list, index)); + setBackground(getAlternatingBackgroundColor(list, index)); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java index d842a3b25a..b427b7a031 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java @@ -28,6 +28,7 @@ import java.util.List; import javax.swing.*; import javax.swing.event.*; +import javax.swing.plaf.TableUI; import javax.swing.table.*; import docking.*; @@ -39,6 +40,7 @@ import docking.widgets.OptionDialog; import docking.widgets.dialogs.SettingsDialog; import docking.widgets.filechooser.GhidraFileChooser; import generic.theme.GIcon; +import generic.theme.GThemeDefaults.Colors; import ghidra.docking.settings.*; import ghidra.framework.preferences.Preferences; import ghidra.util.*; @@ -92,11 +94,22 @@ public class GTable extends JTable { private AutoLookup autoLookup = createAutoLookup(); - /** A list of default renderers created by this table */ - protected List defaultGTableRendererList = new ArrayList<>(); private boolean htmlRenderingEnabled; private String preferenceKey; + private MouseListener selectRowListener = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + int row = rowAtPoint(e.getPoint()); + if (row >= 0) { + if (!isRowSelected(row)) { + setRowSelectionInterval(row, row); + } + } + } + } + }; private GTableMouseListener headerMouseListener; private JPopupMenu tableHeaderPopupMenu; private boolean columnHeaderPopupEnabled = true; @@ -118,7 +131,7 @@ public class GTable extends JTable { * Constructs a new GTable */ public GTable() { - init(); + // default constructor } /** @@ -127,6 +140,11 @@ public class GTable extends JTable { */ public GTable(TableModel dm) { super(dm); + } + + @Override + public void setUI(TableUI ui) { + super.setUI(ui); init(); } @@ -418,6 +436,9 @@ public class GTable extends JTable { } private void init() { + + setBackground(Colors.BACKGROUND); + ToolTipManager.sharedInstance().unregisterComponent(this); ToolTipManager.sharedInstance().registerComponent(this); setTableHeader(new GTableHeader(this)); @@ -434,25 +455,18 @@ public class GTable extends JTable { setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); - addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON3) { - int row = rowAtPoint(e.getPoint()); - if (row >= 0) { - if (!isRowSelected(row)) { - setRowSelectionInterval(row, row); - } - } - } - } - }); + removeMouseListener(selectRowListener); + addMouseListener(selectRowListener); removeActionKeyStrokes(); // updating the row height requires the 'isInitialized' to be set, so do it first isInitialized = true; initializeRowHeight(); + + // this call is needed if the UI is switched, as we must tell the parent scroll pane that + // the header has been changed + configureEnclosingScrollPane(); } private void removeActionKeyStrokes() { @@ -627,9 +641,11 @@ public class GTable extends JTable { return renderer; // already wrapped } if (renderer instanceof GTableCellRenderer) { - setDefaultRenderer(columnClass, renderer); + // not sure why this was here; keeping around for a bit just in case + // setDefaultRenderer(columnClass, renderer); return renderer; } + DefaultTableCellRendererWrapper wrapper = new DefaultTableCellRendererWrapper(renderer); setDefaultRenderer(columnClass, wrapper); // cache for later use return wrapper; @@ -649,13 +665,10 @@ public class GTable extends JTable { setDefaultRenderer(Short.class, gTableCellRenderer); setDefaultRenderer(Integer.class, gTableCellRenderer); setDefaultRenderer(Long.class, gTableCellRenderer); - setDefaultRenderer(Float.class, gTableCellRenderer); setDefaultRenderer(Double.class, gTableCellRenderer); setDefaultRenderer(Boolean.class, new GBooleanCellRenderer()); - - defaultGTableRendererList.add(gTableCellRenderer); } private void disableGridLines() { @@ -788,14 +801,6 @@ public class GTable extends JTable { * HTML content, which they do not do by default. * *

- * As mentioned above, this class only enables/disables the HTML rendering on - * {@link GTableCellRenderer} instances that were created by this class (or subclasses) - * during initialization in {@link #initDefaultRenderers()} and that have been added to the - * {@link #defaultGTableRendererList}. If users of this class have changed or added new - * renderers, then those renderers will not be changed by calling this method. Typically, - * this method should be called just after created an instance of this class, which will work - * as described by this method. - *

* HTML rendering is disabled by default. * * @param enable true to enable HTML rendering; false to disable it @@ -803,9 +808,9 @@ public class GTable extends JTable { public void setHTMLRenderingEnabled(boolean enable) { htmlRenderingEnabled = enable; - for (TableCellRenderer renderer : defaultGTableRendererList) { - if (renderer instanceof GTableCellRenderer) { - GTableCellRenderer gRenderer = (GTableCellRenderer) renderer; + Collection renderers = defaultRenderersByColumnClass.values(); + for (Object object : renderers) { + if (object instanceof GTableCellRenderer gRenderer) { gRenderer.setHTMLRenderingEnabled(enable); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java index a6a2568fd5..06ce360c9c 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableCellRenderer.java @@ -168,7 +168,7 @@ public class GTableCellRenderer extends AbstractGCellRenderer implements TableCe setBackground(BG_DRAG); } else { - setBackground(getOSDependentBackgroundColor(table, row)); + setBackground(getAlternatingBackgroundColor(table, row)); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableHeaderRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableHeaderRenderer.java index 1e80335dff..b153d3e33a 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableHeaderRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTableHeaderRenderer.java @@ -55,6 +55,10 @@ public class GTableHeaderRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (table == null) { + return this; // not sure when this can happen, but Java class protect against this case + } + JTableHeader header = table.getTableHeader(); delegate = header.getDefaultRenderer(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java index 4243008e37..20829a5d12 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/tree/GTree.java @@ -217,6 +217,9 @@ public class GTree extends JPanel implements BusyListener, ThemeListener { } private void init() { + + setBackground(BACKGROUND); + tree = new AutoScrollTree(model); setLayout(new BorderLayout()); diff --git a/Ghidra/Framework/Gui/data/gui.theme.properties b/Ghidra/Framework/Gui/data/gui.theme.properties index 29647c4ed3..8a0a75c63a 100644 --- a/Ghidra/Framework/Gui/data/gui.theme.properties +++ b/Ghidra/Framework/Gui/data/gui.theme.properties @@ -3,6 +3,9 @@ color.bg = white // note: this is the text/widget bg color color.fg = black +// On some LaFs the tables and tree use the bg color we define. Make that consistent for all LaFs. +[color]Viewport.background = color.bg + color.cursor.focused = red color.cursor.unfocused = pink @@ -13,7 +16,7 @@ color.bg.uneditable = system.color.bg.application // TODO see if there exists an color.bg.filtered = yellow color.fg.hint = gray -color.bg.tooltip = rgb(255, 255, 230) +color.bg.tooltip = [color]ToolTip.background color.fg.messages.hint = color.fg.hint color.fg.messages.alert = orange @@ -32,7 +35,7 @@ color.fg.table.unselected = white color.fg.error.table.unselected = color.fg.error color.fg.error.table.selected = lightpink -color.bg.tree = [color]Tree.textBackground +color.bg.tree = color.bg color.bg.tree.selected = [color]Tree.selectionBackground // Fonts @@ -123,3 +126,24 @@ color.fg.table.uneditable.unselected = lightgray color.bg.tree = color.bg color.bg.tree.selected = [color]Tree.selectionBackground + + +[Flat Dark] + +// the default inactive selection color is too close to the bg color to be easily visible +color.flat.selection.inactive = #0F4C6A + + +[CDE/Motif] + +color.bg = [color]window // gray for motif +color.fg = [color]textText + + +[Nimbus] + +// Nimbus uses the ToolTipPainter class to paint tooltips. That class does not read the property +// we use for tooltips, which is 'ToolTip.background', even though that is defined by the LaF. +// Setting the 'info' value here to changes the key the painter users to paint tooltips. The info +// value seems to only be used for tooltips, which means this change affects no other components. +[color]info = [color]ToolTip.background diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeDefaults.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeDefaults.java index c95fc657c9..468aaba96a 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeDefaults.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/GThemeDefaults.java @@ -24,13 +24,11 @@ import java.awt.Color; * Colors.Java.BORDER */ public class GThemeDefaults { - public static final String STANDARD_DEFAULTS = "Standard Defaults"; // core defaults map name - public static final String DARK = "Dark"; // defaults map name for dark based themes public static class Ids { public static class Java { - public static final String BORDER = "system.color.border"; // TODO + public static final String BORDER = "system.color.border"; } public static class Fonts {