diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CreateTypeDefDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CreateTypeDefDialog.java index a021ff11c4..9ad9767e82 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CreateTypeDefDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/CreateTypeDefDialog.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ import javax.swing.tree.TreePath; import docking.DialogComponentProvider; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.GLabel; -import docking.widgets.list.GListCellRenderer; +import docking.widgets.list.GComboBoxCellRenderer; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.tree.ArchiveNode; import ghidra.app.plugin.core.datamgr.tree.DataTypeTreeNode; @@ -68,8 +68,7 @@ public class CreateTypeDefDialog extends DialogComponentProvider { panel.add(nameTextField); // data type info - dataTypeEditor = - new DataTypeSelectionEditor(plugin.getTool(), AllowedDataTypes.ALL); + dataTypeEditor = new DataTypeSelectionEditor(plugin.getTool(), AllowedDataTypes.ALL); panel.add(new GLabel("Data type:")); panel.add(dataTypeEditor.getEditorComponent()); @@ -88,8 +87,8 @@ public class CreateTypeDefDialog extends DialogComponentProvider { dataTypeEditor.setDefaultSelectedTreePath(selectedTreePath); dataTypeManagerBox = new GhidraComboBox<>(); - dataTypeManagerBox.setRenderer( - GListCellRenderer.createDefaultCellTextRenderer(dtm -> dtm.getName())); + dataTypeManagerBox + .setRenderer(GComboBoxCellRenderer.createDefaultTextRenderer(dtm -> dtm.getName())); DataTypeManager[] dataTypeManagers = plugin.getDataTypeManagers(); for (DataTypeManager manager : dataTypeManagers) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/AssociateDataTypeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/AssociateDataTypeAction.java index 0e7fe9bfa1..a11a16ca18 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/AssociateDataTypeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/associate/AssociateDataTypeAction.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,6 +30,7 @@ import docking.action.MenuData; import docking.widgets.OptionDialog; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.GLabel; +import docking.widgets.list.GComboBoxCellRenderer; import docking.widgets.tree.GTreeNode; import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin; import ghidra.app.plugin.core.datamgr.DataTypesActionContext; @@ -203,15 +204,15 @@ public class AssociateDataTypeAction extends DockingAction { private JComponent buildWorkPanel() { - archivesBox.setRenderer(new DefaultListCellRenderer() { + archivesBox.setRenderer(new GComboBoxCellRenderer<>() { @Override - public Component getListCellRendererComponent(JList list, Object value, - int index, boolean isSelected, boolean cellHasFocus) { + public Component getListCellRendererComponent(JList list, + Archive value, int index, boolean isSelected, boolean cellHasFocus) { JLabel renderer = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - Archive a = (Archive) value; + Archive a = value; renderer.setText(a.getName()); return renderer; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java index 31dd8fee4e..c216d8d37b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/EncodedStringsDialog.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,6 +33,7 @@ import docking.DialogComponentProvider; import docking.widgets.checkbox.GCheckBox; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.*; +import docking.widgets.list.GComboBoxCellRenderer; import docking.widgets.list.GListCellRenderer; import docking.widgets.spinner.IntegerSpinner; import docking.widgets.table.threaded.ThreadedTableModelListener; @@ -664,7 +665,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { translateComboBox.setSelectedItem(defaultSTS); } - translateComboBox.setRenderer(GListCellRenderer.createDefaultCellTextRenderer( + translateComboBox.setRenderer(GComboBoxCellRenderer.createDefaultTextRenderer( sts -> sts != null ? sts.getTranslationServiceName() : "")); } @@ -1153,7 +1154,7 @@ public class EncodedStringsDialog extends DialogComponentProvider { return "%s%s (%d)".formatted(name, example, count); }; - setRenderer(GListCellRenderer.createDefaultCellTextRenderer(cellToTextMappingFunction)); + setRenderer(GListCellRenderer.createDefaultTextRenderer(cellToTextMappingFunction)); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java index a6115a91ab..a0b6087f75 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterDialog.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -38,7 +38,7 @@ import docking.widgets.button.BrowseButton; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.dialogs.MultiLineMessageDialog; import docking.widgets.label.GLabel; -import docking.widgets.list.GListCellRenderer; +import docking.widgets.list.GComboBoxCellRenderer; import generic.theme.GIcon; import generic.theme.Gui; import ghidra.app.services.ProgramManager; @@ -259,7 +259,7 @@ public class ImporterDialog extends DialogComponentProvider { loaderComboBox.addItemListener(e -> selectedLoaderChanged()); loaderComboBox.setEnterKeyForwarding(true); loaderComboBox.setRenderer( - GListCellRenderer.createDefaultCellTextRenderer(loader -> loader.getName())); + GComboBoxCellRenderer.createDefaultTextRenderer(loader -> loader.getName())); if (!orderedLoaders.isEmpty()) { loaderComboBox.setSelectedIndex(0); @@ -572,8 +572,8 @@ public class ImporterDialog extends DialogComponentProvider { } private void chooseProjectFolder() { - DataTreeDialog dataTreeDialog = new DataTreeDialog(getComponent(), - "Choose a project folder", CHOOSE_FOLDER); + DataTreeDialog dataTreeDialog = + new DataTreeDialog(getComponent(), "Choose a project folder", CHOOSE_FOLDER); dataTreeDialog.setSelectedFolder(destinationFolder); dataTreeDialog.showComponent(); DomainFolder folder = dataTreeDialog.getDomainFolder(); diff --git a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/plugin/MultiFunctionComparisonPanel.java b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/plugin/MultiFunctionComparisonPanel.java index 89ac1ace8b..b032584ca5 100644 --- a/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/plugin/MultiFunctionComparisonPanel.java +++ b/Ghidra/Features/CodeCompare/src/main/java/ghidra/features/codecompare/plugin/MultiFunctionComparisonPanel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,6 +23,7 @@ import java.awt.event.ItemListener; import javax.swing.*; +import docking.widgets.list.GComboBoxCellRenderer; import ghidra.features.base.codecompare.model.FunctionComparisonModel; import ghidra.features.base.codecompare.model.FunctionComparisonModelListener; import ghidra.features.base.codecompare.panel.CodeComparisonPanel; @@ -209,7 +210,7 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel * Cell renderer for combo boxes that changes the default display to show * both the function name and the program it comes from */ - private class FunctionListCellRenderer extends DefaultListCellRenderer { + private class FunctionListCellRenderer extends GComboBoxCellRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java index ced3039cf1..5db8765187 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -216,7 +216,7 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel { public ThemeIconRenderer() { - setBaseFontId("font.monospaced"); + setFont(getFixedWidthFont()); } @Override @@ -273,5 +273,5 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel implements DropDownTextFieldDa private DataToStringConverter searchConverter; private DataToStringConverter descriptionConverter; private ListCellRenderer renderer = - GListCellRenderer.createDefaultCellTextRenderer(value -> searchConverter.getString(value)); + GListCellRenderer.createDefaultTextRenderer(value -> searchConverter.getString(value)); public static DefaultDropDownSelectionDataModel getStringModel(List strings) { return new DefaultDropDownSelectionDataModel<>(strings, diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java index 386a80aacd..8096629abe 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filechooser/GhidraFileChooser.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -393,7 +393,7 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement JLabel filterLabel = new GLabel("Type:"); filterCombo = new GComboBox<>(); - filterCombo.setRenderer(GListCellRenderer.createDefaultCellTextRenderer( + filterCombo.setRenderer(GListCellRenderer.createDefaultTextRenderer( fileFilter -> fileFilter != null ? fileFilter.getDescription() : "")); filterModel = (DefaultComboBoxModel) filterCombo.getModel(); addFileFilter(GhidraFileFilter.ALL); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filter/FilterOptionsEditorDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filter/FilterOptionsEditorDialog.java index 18a744319a..0441e14dcc 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/filter/FilterOptionsEditorDialog.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/filter/FilterOptionsEditorDialog.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ import docking.widgets.checkbox.GCheckBox; import docking.widgets.combobox.GComboBox; import docking.widgets.label.GIconLabel; import docking.widgets.label.GLabel; -import docking.widgets.list.GListCellRenderer; +import docking.widgets.list.GComboBoxCellRenderer; import ghidra.util.HelpLocation; import ghidra.util.layout.*; @@ -268,8 +268,8 @@ public class FilterOptionsEditorDialog extends DialogComponentProvider { } globbingCheckbox = new GCheckBox("Allow Globbing"); - globbingCheckbox.setToolTipText( - "Toggles whether globbing chars (?*) are literal or wildcards"); + globbingCheckbox + .setToolTipText("Toggles whether globbing chars (?*) are literal or wildcards"); if (initialFilterOptions.isGlobbingAllowed()) { globbingCheckbox.setSelected(true); } @@ -331,9 +331,9 @@ public class FilterOptionsEditorDialog extends DialogComponentProvider { setBorder(BorderFactory.createEmptyBorder(5, 4, 10, 4)); pathCheckbox = new GCheckBox("Use Path"); - pathCheckbox.setToolTipText("" + - "Allows filtering on node paths, for example '*/folder/node' or " + - "'*folder1*folder2*node'"); + pathCheckbox.setToolTipText( + "" + "Allows filtering on node paths, for example '*/folder/node' or " + + "'*folder1*folder2*node'"); if (initialFilterOptions.shouldUsePath()) { pathCheckbox.setSelected(true); } @@ -456,8 +456,8 @@ public class FilterOptionsEditorDialog extends DialogComponentProvider { // Delimiter Row JLabel delimiterCharacterFieldName = new GLabel("Delimiter:"); - delimiterCharacterFieldName.setToolTipText( - "Set the character used to separate filter terms."); + delimiterCharacterFieldName + .setToolTipText("Set the character used to separate filter terms."); delimiterCharacterCB = new GComboBox<>(FilterOptions.VALID_MULTITERM_DELIMITERS_ARRAY); delimiterCharacterCB.setRenderer(new DelimiterListCellRenderer()); @@ -499,7 +499,7 @@ public class FilterOptionsEditorDialog extends DialogComponentProvider { add(optionsPaneDisableLayer); } - private class DelimiterListCellRenderer extends GListCellRenderer { + private class DelimiterListCellRenderer extends GComboBoxCellRenderer { public DelimiterListCellRenderer() { setHTMLRenderingEnabled(true); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GComboBoxCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GComboBoxCellRenderer.java new file mode 100644 index 0000000000..3851c28390 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GComboBoxCellRenderer.java @@ -0,0 +1,77 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.widgets.list; + +import java.awt.Color; +import java.awt.Font; +import java.util.function.Function; + +import generic.theme.*; + +/** + * Provides a common implementation of a combo box drop-down list renderer, for use with + * JComboBoxes. + *

+ * HTML rendering defaults to disabled. See {@link #setHTMLRenderingEnabled(boolean)}. + * + * @param the element-type this list models. + */ +public class GComboBoxCellRenderer extends GListCellRenderer { + + private static final Color COMBO_BOX_BACKGROUND_COLOR = new GColor("color.bg.combobox.row"); + + /** + * Returns a new GComboBoxCellRenderer that maps the list's data instance to a string used in + * the cell. + *

+ * Use this if you only need to provide a way to get the string value from the type being shown + * in the list. + * + * @param cellToTextMappingFunction a function that maps your custom type to a string value + * @return new GComboBoxCellRenderer instance + */ + public static GComboBoxCellRenderer createDefaultTextRenderer( + Function cellToTextMappingFunction) { + return new GComboBoxCellRenderer<>() { + @Override + protected String getItemText(E value) { + return cellToTextMappingFunction.apply(value); + } + }; + } + + // overridden to return the combo box-specific background color + @Override + protected Color getDefaultBackgroundColor() { + return COMBO_BOX_BACKGROUND_COLOR; + } + + @Override + protected void checkForInvalidSetFont(Font f) { + + // + // The Metal LaF will use the combo's renderer to paint the contents when it is not + // editable. (It uses the cell editor when it is editable.) The UI in this case will call + // renderer.setFont(comboBox.getFont()) before painting. We don't want to generate font + // warnings when this is the case, since we have no control over that behavior. + // + if (ThemeManager.getInstance().getLookAndFeelType() == LafType.METAL) { + return; + } + + super.checkForInvalidSetFont(f); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java index 0df606e176..03f5ddddb7 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/list/GListCellRenderer.java @@ -15,12 +15,15 @@ */ package docking.widgets.list; +import java.awt.Color; import java.awt.Component; import java.util.function.Function; import javax.swing.*; +import javax.swing.border.Border; import docking.widgets.AbstractGCellRenderer; +import generic.theme.GColor; import generic.theme.GThemeDefaults.Colors.Palette; /** @@ -32,6 +35,8 @@ import generic.theme.GThemeDefaults.Colors.Palette; */ public class GListCellRenderer extends AbstractGCellRenderer implements ListCellRenderer { + private static final Color LIST_BACKGROUND_COLOR = new GColor("color.bg.list.row"); + /** * Returns a new ListCellRenderer that maps the list's data instance to a string used in the cell. *

@@ -41,7 +46,7 @@ public class GListCellRenderer extends AbstractGCellRenderer implements ListC * @param cellToTextMappingFunction a function that maps your custom type to a string value * @return new GListCellRenderer instance */ - public static GListCellRenderer createDefaultCellTextRenderer( + public static GListCellRenderer createDefaultTextRenderer( Function cellToTextMappingFunction) { return new GListCellRenderer<>() { @Override @@ -58,6 +63,26 @@ public class GListCellRenderer extends AbstractGCellRenderer implements ListC // lists don't need alternation for rows, as they don't use long columnar data setShouldAlternateRowBackgroundColors(false); + + // Base our borders on those used by the list. ComboBoxes do not change the list borders in + // the Look and Feel. + noFocusBorder = getBorder("List.noFocusBorder"); + focusBorder = getBorder("List.focusCellHighlightBorder"); + } + + private Border getBorder(String id) { + Border border = UIManager.getBorder(id); + if (border == null) { + // A reasonable default value picked based on examining the existing LaFs + border = BorderFactory.createEmptyBorder(2, 4, 2, 4); + } + return border; + } + + // overridden to return the list-specific background color + @Override + protected Color getDefaultBackgroundColor() { + return LIST_BACKGROUND_COLOR; } /** diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java index d3c1d067dc..6efb5add02 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ColumnFilterPanel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,7 +25,7 @@ import javax.swing.border.BevelBorder; import docking.widgets.EmptyBorderButton; import docking.widgets.combobox.GhidraComboBox; import docking.widgets.label.GDLabel; -import docking.widgets.list.GListCellRenderer; +import docking.widgets.list.GComboBoxCellRenderer; import generic.theme.GThemeDefaults.Colors.Messages; import ghidra.util.layout.VerticalLayout; import resources.Icons; @@ -72,18 +72,11 @@ class ColumnFilterPanel extends JPanel { DefaultComboBoxModel> model = new DefaultComboBoxModel<>(v); columnFilterComboBox = new GhidraComboBox<>(model); - columnFilterComboBox.setRenderer(new GListCellRenderer<>() { - + columnFilterComboBox.setRenderer(new GComboBoxCellRenderer<>() { @Override protected String getItemText(ColumnFilterData value) { return value == null ? "" : value.getName(); } - - @Override - public boolean shouldAlternateRowBackgroundColor() { - // alternating colors look odd in this combo box - return false; - } }); columnFilterComboBox.setSelectedItem(filterEntry.getColumnFilterData()); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ConstraintFilterPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ConstraintFilterPanel.java index 175433bbe8..3779f65944 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ConstraintFilterPanel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/dialog/ConstraintFilterPanel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ import javax.swing.*; import docking.widgets.EmptyBorderButton; import docking.widgets.combobox.GComboBox; -import docking.widgets.list.GListCellRenderer; +import docking.widgets.list.GComboBoxCellRenderer; import docking.widgets.table.constraint.ColumnConstraint; import resources.Icons; @@ -119,17 +119,11 @@ public class ConstraintFilterPanel extends JPanel { constraintComboBox.addActionListener(constraintComboBoxListener); } - private class ConstraintComboBoxCellRenderer extends GListCellRenderer> { - + private class ConstraintComboBoxCellRenderer + extends GComboBoxCellRenderer> { @Override protected String getItemText(ColumnConstraint value) { return value.getName(); } - - @Override - public boolean shouldAlternateRowBackgroundColor() { - // alternating colors look odd in this combo box - return false; - } } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constrainteditor/BooleanConstraintEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constrainteditor/BooleanConstraintEditor.java index f0cb5bcd9c..047f11f7ca 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constrainteditor/BooleanConstraintEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constrainteditor/BooleanConstraintEditor.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ import javax.swing.JPanel; import org.apache.commons.lang3.StringUtils; import docking.widgets.combobox.GComboBox; -import docking.widgets.list.GListCellRenderer; +import docking.widgets.list.GComboBoxCellRenderer; import docking.widgets.table.constraint.BooleanMatchColumnConstraint; import docking.widgets.table.constraint.ColumnConstraint; @@ -48,8 +48,8 @@ public class BooleanConstraintEditor extends AbstractColumnConstraintEditor(new Boolean[] { Boolean.TRUE, Boolean.FALSE }); - comboBox.setRenderer(GListCellRenderer.createDefaultCellTextRenderer( - b -> StringUtils.capitalize(b.toString()))); + comboBox.setRenderer(GComboBoxCellRenderer + .createDefaultTextRenderer(b -> StringUtils.capitalize(b.toString()))); comboBox.addItemListener(e -> valueChanged()); panel.add(comboBox, BorderLayout.CENTER); diff --git a/Ghidra/Framework/Gui/data/gui.theme.properties b/Ghidra/Framework/Gui/data/gui.theme.properties index 149af8a9bb..25283c911d 100644 --- a/Ghidra/Framework/Gui/data/gui.theme.properties +++ b/Ghidra/Framework/Gui/data/gui.theme.properties @@ -26,6 +26,10 @@ color.fg.table.uneditable.unselected = color.palette.lightgray color.fg.error.table.unselected = color.fg.error color.fg.error.table.selected = color.palette.lightpink +// allow list and combobox renderers to vary independently of tables, which some LaFs use +color.bg.list.row = color.bg.table.row +color.bg.combobox.row = color.bg.table.row + color.bg.tree = [color]system.color.bg.view color.bg.tree.drag = color.palette.lavender color.bg.tree.selected = [color]system.color.bg.selected.view @@ -128,7 +132,10 @@ icon.make.selection = stack.png +[Metal] +// the Metal LaF overrides combo box rendering with this line: "ComboBox.background", control +color.bg.combobox.row = [color]system.color.bg.control [Flat Dark] diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeManager.java index 052d403211..c04510fa90 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeManager.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ApplicationThemeManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -370,6 +370,11 @@ public class ApplicationThemeManager extends ThemeManager { lookAndFeelManager.registerFont(component, fontId, fontStyle); } + @Override + public void unRegisterFont(JComponent component, String fontId) { + lookAndFeelManager.unRegisterFont(component, fontId); + } + private void installFlatLookAndFeels() { UIManager.installLookAndFeel(LafType.FLAT_LIGHT.getName(), FlatLightLaf.class.getName()); UIManager.installLookAndFeel(LafType.FLAT_DARK.getName(), FlatDarkLaf.class.getName()); diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/Gui.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/Gui.java index fb7ead0812..1c024fe820 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/Gui.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/Gui.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -190,6 +190,20 @@ public class Gui { themeManager.registerFont(component, fontId, fontStyle); } + /** + * Removes the component and font id binding made in a previous call to + * {@link #registerFont(Component, String)}. + *

+ * Clients need to call this method if they decide to change the font id being used for a given + * component. Must clients do not need to use this method. + * + * @param component the component to remove + * @param fontId the id of the font previously registered + */ + public static void unRegisterFont(JComponent component, String fontId) { + themeManager.unRegisterFont(component, fontId); + } + /** * Returns true if the active theme is using dark defaults * @return true if the active theme is using dark defaults diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java index 29343c19fc..508d76da55 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -592,6 +592,16 @@ public abstract class ThemeManager { // do nothing } + /** + * Removes the component and font id binding made in a previous call to + * {@link #registerFont(Component, String)}. + * @param component the component to remove + * @param fontId the id of the font previously registered + */ + public void unRegisterFont(JComponent component, String fontId) { + // do nothing + } + /** * Returns true if the current theme use dark default values. * @return true if the current theme use dark default values. diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java index 96caf98907..6387fd966e 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/ComponentFontRegistry.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,7 @@ package generic.theme.laf; import java.awt.Component; import java.awt.Font; +import java.util.Iterator; import java.util.Objects; import generic.theme.Gui; @@ -60,6 +61,21 @@ public class ComponentFontRegistry { components.add(sc); } + /** + * Removes the given component from this registry. + * @param component the component + */ + public void removeComponent(Component component) { + Iterator it = components.iterator(); + while (it.hasNext()) { + StyledComponent sc = it.next(); + if (component == sc.component) { + it.remove(); + break; + } + } + } + /** * Updates the font for all components bound to this registry's font id. */ diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java index d6a82e4143..dc54e4c4d6 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/laf/LookAndFeelManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -237,6 +237,21 @@ public abstract class LookAndFeelManager { register.addComponent(component, fontStyle); } + /** + * Removes the given component and id binding from this class. + * @param component the component to remove + * @param fontId the id used when originally registered + * @see #registerFont(Component, String) + */ + public void unRegisterFont(JComponent component, String fontId) { + componentToIdMap.remove(component); + + ComponentFontRegistry registry = fontRegistryMap.get(fontId); + if (registry != null) { + registry.removeComponent(component); + } + } + private void checkForAlreadyRegistered(Component component, String newFontId) { String existingFontId = componentToIdMap.get(component); if (existingFontId != null) { @@ -397,9 +412,7 @@ public abstract class LookAndFeelManager { UIDefaults defaults = UIManager.getDefaults(); Set> set = defaults.entrySet(); - Iterator> iterator = set.iterator(); - while (iterator.hasNext()) { - Entry entry = iterator.next(); + for (Entry entry : set) { Object key = entry.getKey(); if (key.toString().toLowerCase().indexOf("font") != -1) { @@ -440,5 +453,4 @@ public abstract class LookAndFeelManager { } return colorKeys; } - } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolConnectionPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolConnectionPanel.java index 893f94246c..a544be00aa 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolConnectionPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/ToolConnectionPanel.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -224,9 +224,9 @@ class ToolConnectionPanel extends JPanel implements ListSelectionListener { }); eventList.setCellRenderer(new DataCellRenderer()); producerList.setCellRenderer( - GListCellRenderer.createDefaultCellTextRenderer(tool -> tool.getName())); + GListCellRenderer.createDefaultTextRenderer(tool -> tool.getName())); consumerList.setCellRenderer( - GListCellRenderer.createDefaultCellTextRenderer(tool -> tool.getName())); + GListCellRenderer.createDefaultTextRenderer(tool -> tool.getName())); producerModel = (DefaultListModel) producerList.getModel(); consumerModel = (DefaultListModel) consumerList.getModel(); }