diff --git a/Ghidra/Features/Decompiler/data/decompiler.theme.properties b/Ghidra/Features/Decompiler/data/decompiler.theme.properties index 902487d72e..d1cb359e89 100644 --- a/Ghidra/Features/Decompiler/data/decompiler.theme.properties +++ b/Ghidra/Features/Decompiler/data/decompiler.theme.properties @@ -13,6 +13,24 @@ color.fg.decompiler.global = darkCyan color.bg.decompiler.middle.mouse = rgba(255,255,0,.5) color.bg.decompiler.current.variable = rgba(255,255,0,0.5) +color.fg.line.numbers = gray + +color.bg.decompiler.highlights.default = rgba(255, 255, 0, .5) +color.bg.decompiler.highlights.special = sandybrown +color.bg.decompiler.highlights.search = mediumslateblue + +color.bg.decompiler.pcode.dfg.vertex.default = red +color.bg.decompiler.pcode.dfg.vertex.selected = deeppink +color.bg.decompiler.pcode.dfg.vertex.constant = darkgreen +color.bg.decompiler.pcode.dfg.vertex.register = navy +color.bg.decompiler.pcode.dfg.vertex.unique = black +color.bg.decompiler.pcode.dfg.vertex.persistent = darkorange +color.bg.decompiler.pcode.dfg.vertex.address.tied = orange +color.bg.decompiler.pcode.dfg.vertex.op = red +color.bg.decompiler.pcode.dfg.edge.default = navy +color.bg.decompiler.pcode.dfg.edge.selected = deeppink +color.bg.decompiler.pcode.dfg.edge.within.block = black +color.bg.decompiler.pcode.dfg.edge.between.blocks = red [Dark Defaults] diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java b/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java index 3a72b6a72a..09d7b29b26 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/RecoverClassesFromRTTIScript.java @@ -54,18 +54,11 @@ import java.io.File; import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; -import classrecovery.DecompilerScriptUtils; -import classrecovery.RTTIClassRecoverer; -import classrecovery.RTTIGccClassRecoverer; -import classrecovery.RTTIWindowsClassRecoverer; -import classrecovery.RecoveredClass; -import classrecovery.RecoveredClassHelper; +import classrecovery.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.decompiler.DecompInterface; import ghidra.app.plugin.core.analysis.AutoAnalysisManager; import ghidra.app.plugin.core.analysis.DecompilerFunctionAnalyzer; @@ -81,29 +74,11 @@ import ghidra.app.util.importer.MessageLog; import ghidra.app.util.opinion.ElfLoader; import ghidra.framework.options.Options; import ghidra.framework.plugintool.PluginTool; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressSet; -import ghidra.program.model.address.AddressSetView; -import ghidra.program.model.data.CategoryPath; -import ghidra.program.model.data.DataType; -import ghidra.program.model.data.DataTypeComponent; -import ghidra.program.model.data.DataTypeManager; -import ghidra.program.model.data.Structure; -import ghidra.program.model.listing.Function; -import ghidra.program.model.listing.Parameter; -import ghidra.program.model.listing.Program; +import ghidra.program.model.address.*; +import ghidra.program.model.data.*; +import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryBlock; -import ghidra.service.graph.AttributedEdge; -import ghidra.service.graph.AttributedGraph; -import ghidra.service.graph.AttributedVertex; -import ghidra.service.graph.GraphDisplay; -import ghidra.service.graph.GraphDisplayOptions; -import ghidra.service.graph.GraphDisplayOptionsBuilder; -import ghidra.service.graph.GraphDisplayProvider; -import ghidra.service.graph.GraphType; -import ghidra.service.graph.GraphTypeBuilder; -import ghidra.service.graph.VertexShape; -import ghidra.util.WebColors; +import ghidra.service.graph.*; import ghidra.util.exception.CancelledException; import ghidra.util.exception.GraphException; import ghidra.util.task.TaskMonitor; @@ -401,13 +376,12 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return analysisMode; } - - @Override - public void analyzeChanges(Program program) { - AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program); - mgr.startAnalysis(monitor, false); - } + @Override + public void analyzeChanges(Program program) { + AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program); + mgr.startAnalysis(monitor, false); + } /** * Method to create a class hierarchy graph where the parents are at the top of the graph and @@ -486,7 +460,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { edge.setEdgeType(NON_VIRTUAL_INHERITANCE); } - } } @@ -508,13 +481,13 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { display = service.getGraphDisplay(false, TaskMonitor.DUMMY); GraphDisplayOptions graphOptions = new GraphDisplayOptionsBuilder(graph.getGraphType()) - .vertex(NO_INHERITANCE, VertexShape.RECTANGLE, WebColors.BLUE) - .vertex(SINGLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.GREEN) - .vertex(MULTIPLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.RED) - .edge(NON_VIRTUAL_INHERITANCE, WebColors.LIME_GREEN) - .edge(VIRTUAL_INHERITANCE, WebColors.ORANGE) - .defaultVertexColor(WebColors.PURPLE) - .defaultEdgeColor(WebColors.PURPLE) + .vertex(NO_INHERITANCE, VertexShape.RECTANGLE, Palette.BLUE) + .vertex(SINGLE_INHERITANCE, VertexShape.RECTANGLE, Palette.GREEN) + .vertex(MULTIPLE_INHERITANCE, VertexShape.RECTANGLE, Palette.RED) + .edge(NON_VIRTUAL_INHERITANCE, Palette.LIME) + .edge(VIRTUAL_INHERITANCE, Palette.ORANGE) + .defaultVertexColor(Palette.PURPLE) + .defaultEdgeColor(Palette.PURPLE) .defaultLayoutAlgorithm("Compact Hierarchical") .build(); @@ -534,7 +507,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return doOutput; } - private void printClassHierarchyLists(List recoveredClasses) throws CancelledException { @@ -551,9 +523,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - - - /** * Script works on versions of ghidra including and after 9.2 except for 9.2.1 because a method * was accidentally removed from FillOutStructureCmd that is needed @@ -579,8 +548,11 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } boolean isCompilerSpecGcc = - currentProgram.getCompilerSpec().getCompilerSpecID().getIdAsString().equalsIgnoreCase( - "gcc"); + currentProgram.getCompilerSpec() + .getCompilerSpecID() + .getIdAsString() + .equalsIgnoreCase( + "gcc"); if (isCompilerSpecGcc) { return true; } @@ -598,8 +570,9 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { byte[] gccBytes = { (byte) 0x47, (byte) 0x43, (byte) 0x43, (byte) 0x3a }; byte[] maskBytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; - Address found = currentProgram.getMemory().findBytes(commentBlock.getStart(), - commentBlock.getEnd(), gccBytes, maskBytes, true, monitor); + Address found = currentProgram.getMemory() + .findBytes(commentBlock.getStart(), + commentBlock.getEnd(), gccBytes, maskBytes, true, monitor); if (found == null) { isGcc = false; } @@ -621,8 +594,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return isWindows; } - - /** * Method to determine if somehow the constructor list and destructor list for a class contain * overlapping functions @@ -637,12 +608,18 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { recoverClassesFromRTTI.getAllClassDestructors(recoveredClass); List commonFunctions1 = - allClassConstructors.stream().distinct().filter(allClassDestructors::contains).collect( - Collectors.toList()); + allClassConstructors.stream() + .distinct() + .filter(allClassDestructors::contains) + .collect( + Collectors.toList()); List commonFunctions2 = - allClassDestructors.stream().distinct().filter(allClassConstructors::contains).collect( - Collectors.toList()); + allClassDestructors.stream() + .distinct() + .filter(allClassConstructors::contains) + .collect( + Collectors.toList()); if (commonFunctions1.isEmpty() && commonFunctions2.isEmpty()) { return false; @@ -661,8 +638,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { analyzer.added(currentProgram, set, monitor, new MessageLog()); } - - /** * Get the version of Ghidra that was used to analyze this program * @return a string containing the version number of Ghidra used to analyze the current program @@ -673,7 +648,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return options.getString("Created With Ghidra Version", null); } - /** * Method to bookmark all of the constructor/destructor/indeterminate functions * @param recoveredClasses List of classes @@ -686,7 +660,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { bookmarkRemainingIndeterminateConstructorsAndDestructors(recoveredClasses); } - /** * Method to print class hierarchy of the form child : parent: grandparent : etc... * @param stringBuffer the buffer to add the newly created string to @@ -707,7 +680,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { Map> classHierarchyMap = recoveredClass.getClassHierarchyMap(); - List parents = new ArrayList(classHierarchyMap.keySet()); + List parents = new ArrayList<>(classHierarchyMap.keySet()); // if single inheritance - simple linear case if (recoveredClass.hasSingleInheritance()) { @@ -742,9 +715,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } - - - /** * Method to retrieve the AddressSet of the current program's initialized memory * @return the AddressSet of the current program's initialized memory @@ -765,8 +735,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return dataAddresses; } - - /** * Method to bookmark found constructor functions * @param recoveredClasses List of classes @@ -810,7 +778,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - /** * Method to add/append analysis bookmarks with the given comment to the given list of functions * @param functions List of functions @@ -831,7 +798,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - /** * Method to optionally print to console or output to file various types of class information * depending on the options set at top of script @@ -894,7 +860,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - private void outputClassDefinitions(List recoveredClasses, PrintWriter out) throws CancelledException { for (RecoveredClass recoveredClass : recoveredClasses) { @@ -904,7 +869,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - } /** @@ -938,7 +902,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - /** * Method to print class hierarchies for the given list of classes starting with the lowest child classes in each family of classes * @param recoveredClasses the list of classes @@ -947,7 +910,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { private void printClassHierarchiesFromLowestChildren( List recoveredClasses) throws CancelledException { - StringBuffer wholeBuffer = new StringBuffer(); wholeBuffer.append("\r\n"); for (RecoveredClass recoveredClass : recoveredClasses) { @@ -1006,7 +968,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - /** * Method to print counts of various class items for the given classes, such as number of constructors, destructors, etc... * @param recoveredClasses list of classes @@ -1014,7 +975,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { */ private void printCounts(List recoveredClasses) throws CancelledException { - println("Total number of constructors: " + recoverClassesFromRTTI.getNumberOfConstructors(recoveredClasses)); println("Total number of inlined constructors: " + @@ -1050,7 +1010,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } - /** * Method to get the total number of * @param recoveredClasses list of classes @@ -1099,7 +1058,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } } - /** * Method to output the class, it's parents and it's children for each of the listed classes * @param recoveredClasses the given classes @@ -1219,7 +1177,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { stringBuffer.append("\tNone\r\n"); } - // print child classes stringBuffer.append("\r\n"); stringBuffer.append("child class(es):\r\n"); @@ -1279,7 +1236,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { // print const/dest that couldn't be classified correctly List indeterminateList = recoveredClass.getIndeterminateList(); if (indeterminateList.size() > 0) { - stringBuffer.append("\r\nindeterminate constructor(s) or destructor(s):\r\n"); + stringBuffer.append("\r\nindeterminate constructor(s) or destructor(s):\r\n"); for (Function indeterminateFunction : indeterminateList) { monitor.checkCanceled(); stringBuffer.append("\t" + indeterminateFunction.getName() + " " + @@ -1332,7 +1289,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return stringBuffer; } - /** * Method to get the function signature string, from the decompiler if possible, otherwise from * the listing @@ -1387,7 +1343,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return stringBuffer.toString(); } - /** * Method to create a string containing a C++-like representation of the given class * @param recoveredClass the given class @@ -1397,7 +1352,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { private StringBuffer createClassDefinitionString(RecoveredClass recoveredClass) throws CancelledException { - StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("\r\n\r\n"); @@ -1405,7 +1359,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { stringBuffer.append("\r\n{\r\n"); - // print constructor signature(s) stringBuffer.append("constructor(s):\r\n"); List constructorList = recoveredClass.getConstructorList(); @@ -1474,7 +1427,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { } stringBuffer.append("};\r\n"); - // Then recursively process the child classes if (recoveredClass.hasChildClass()) { List childClasses = recoveredClass.getChildClasses(); @@ -1487,6 +1439,4 @@ public class RecoverClassesFromRTTIScript extends GhidraScript { return stringBuffer; } - - } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java index c38949cb56..889b9348dc 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/DecompileOptions.java @@ -349,7 +349,8 @@ public class DecompileOptions { private static final String SEARCH_HIGHLIGHT_MSG = "Display.Color for Highlighting Find Matches"; - private static final Color SEARCH_HIGHLIGHT_DEF = new Color(100, 100, 255); + private static final Color SEARCH_HIGHLIGHT_DEF = + new GColor("color.bg.decompiler.highlights.search"); private Color defaultSearchHighlightColor = SEARCH_HIGHLIGHT_DEF; // Color applied to a token to indicate warning/error diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangFieldElement.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangFieldElement.java index 920475991c..7ac8a4ebfe 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangFieldElement.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangFieldElement.java @@ -21,6 +21,7 @@ import java.awt.Graphics; import javax.swing.JComponent; import docking.widgets.fieldpanel.field.*; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.decompiler.ClangToken; public class ClangFieldElement extends AbstractTextFieldElement { @@ -49,7 +50,7 @@ public class ClangFieldElement extends AbstractTextFieldElement { if (token.isMatchingToken()) { // paint a bounding box around the token - g.setColor(Color.GRAY); + g.setColor(Palette.GRAY); int offset = 1; g.drawRect(x - offset, y - getHeightAbove() - offset, getStringWidth() + (offset * 2), getHeightAbove() + getHeightBelow() + (offset * 2)); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangHighlightController.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangHighlightController.java index bae9a14109..29314cebaf 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangHighlightController.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/ClangHighlightController.java @@ -25,6 +25,7 @@ import org.apache.commons.collections4.map.LazyMap; import docking.widgets.EventTrigger; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GColor; import ghidra.app.decompiler.*; import ghidra.program.model.listing.Function; import ghidra.program.model.pcode.HighFunction; @@ -63,7 +64,8 @@ import util.CollectionUtils; */ public abstract class ClangHighlightController { - public static Color DEFAULT_HIGHLIGHT_COLOR = new Color(255, 255, 0, 128); + public static Color DEFAULT_HIGHLIGHT_COLOR = + new GColor("color.bg.decompiler.highlights.default"); public static ClangHighlightController dummyIfNull(ClangHighlightController c) { if (c == null) { diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java index dff0039508..3093467b74 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/DecompilerPanel.java @@ -63,7 +63,8 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field private final static Color NON_FUNCTION_BACKGROUND_COLOR_DEF = new GColor("color.bg.undefined"); // Default color for specially highlighted tokens - private final static Color SPECIAL_COLOR_DEF = new Color(255, 100, 0, 128); + private final static Color SPECIAL_COLOR_DEF = + new GColor("color.bg.decompiler.highlights.special"); private final DecompilerController controller; private final DecompileOptions options; diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/HighlightToken.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/HighlightToken.java index 29acf550de..7ed8e5ca58 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/HighlightToken.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/HighlightToken.java @@ -42,6 +42,6 @@ public class HighlightToken { @Override public String toString() { - return token.toString() + "; color=" + color; + return token.toString() + "; highlight=" + color; } } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/TokenHighlightColors.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/TokenHighlightColors.java index ad40804a16..8be5cc1d89 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/TokenHighlightColors.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/decompiler/component/TokenHighlightColors.java @@ -18,21 +18,27 @@ package ghidra.app.decompiler.component; import java.awt.Color; import java.util.*; +import generic.theme.Gui; + /** * A class to create and store colors related to token names */ public class TokenHighlightColors { - private int minColorSaturation = 100; - private int defaultColorAlpha = 100; private Map colorsByName = new HashMap<>(); private List recentColors = new ArrayList<>(); private Color generateColor() { - return new Color((int) (minColorSaturation + Math.random() * (256 - minColorSaturation)), - (int) (minColorSaturation + Math.random() * (256 - minColorSaturation)), - (int) (minColorSaturation + Math.random() * (256 - minColorSaturation)), - defaultColorAlpha); + + float h = (float) Math.random(); // 0-360 + float s = .25f; // saturation; gray to full color; full color is too harsh for highlights + float b = 1f; // brightness; black to full color + if (Gui.getActiveTheme().useDarkDefaults()) { + s = .5f; // a bit more color against a dark background + b = .5f; // less brightness, as the background is not as bright + } + + return Color.getHSBColor(h, s, b); } public Color getColor(String text) { diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/PCodeDfgDisplayOptions.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/PCodeDfgDisplayOptions.java index b2b11dce56..55c6125508 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/PCodeDfgDisplayOptions.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/actions/PCodeDfgDisplayOptions.java @@ -18,9 +18,11 @@ package ghidra.app.plugin.core.decompile.actions; import static ghidra.app.plugin.core.decompile.actions.PCodeDfgGraphType.*; import static ghidra.service.graph.VertexShape.*; +import java.awt.Color; + +import generic.theme.GColor; import ghidra.framework.plugintool.PluginTool; import ghidra.service.graph.*; -import ghidra.util.WebColors; /** * {@link GraphDisplayOptions} for {@link PCodeDfgGraphType} @@ -28,6 +30,32 @@ import ghidra.util.WebColors; public class PCodeDfgDisplayOptions extends GraphDisplayOptions { public static final String SHAPE_ATTRIBUTE = "Shape"; + private static final Color BG_VERTEX_DEFAULT = + new GColor("color.bg.decompiler.pcode.dfg.vertex.default"); + private static final Color BG_VERTEX_SELECTED = + new GColor("color.bg.decompiler.pcode.dfg.vertex.selected"); + private static final Color BG_VERTEX_CONSTANT = + new GColor("color.bg.decompiler.pcode.dfg.vertex.constant"); + private static final Color BG_VERTEX_REGISTER = + new GColor("color.bg.decompiler.pcode.dfg.vertex.register"); + private static final Color BG_VERTEX_UNIQUE = + new GColor("color.bg.decompiler.pcode.dfg.vertex.unique"); + private static final Color BG_VERTEX_PERSISTENT = + new GColor("color.bg.decompiler.pcode.dfg.vertex.persistent"); + private static final Color BG_VERTEX_ADDRESS_TIED = + new GColor("color.bg.decompiler.pcode.dfg.vertex.address.tied"); + private static final Color BG_VERTEX_OP = + new GColor("color.bg.decompiler.pcode.dfg.vertex.op"); + + private static final Color BG_EDGE_DEFAULT = + new GColor("color.bg.decompiler.pcode.dfg.edge.default"); + private static final Color BG_EDGE_SELECTED = + new GColor("color.bg.decompiler.pcode.dfg.edge.selected"); + private static final Color BG_EDGE_WITHIN_BLOCK = + new GColor("color.bg.decompiler.pcode.dfg.edge.within.block"); + private static final Color BG_EDGE_BETWEEN_BLOCKS = + new GColor("color.bg.decompiler.pcode.dfg.edge.between.blocks"); + /** * constructor * @param tool if non-null, will load values from tool options @@ -39,10 +67,10 @@ public class PCodeDfgDisplayOptions extends GraphDisplayOptions { @Override protected void initializeDefaults() { setDefaultVertexShape(ELLIPSE); - setDefaultVertexColor(WebColors.RED); - setDefaultEdgeColor(WebColors.NAVY); - setVertexSelectionColor(WebColors.DEEP_PINK); - setEdgeSelectionColor(WebColors.DEEP_PINK); + setDefaultVertexColor(BG_VERTEX_DEFAULT); + setDefaultEdgeColor(BG_EDGE_DEFAULT); + setVertexSelectionColor(BG_VERTEX_SELECTED); + setEdgeSelectionColor(BG_EDGE_SELECTED); setDefaultLayoutAlgorithmName(LayoutAlgorithmNames.MIN_CROSS_COFFMAN_GRAHAM); setUsesIcons(false); setArrowLength(15); @@ -50,16 +78,16 @@ public class PCodeDfgDisplayOptions extends GraphDisplayOptions { setVertexShapeOverrideAttributeKey(SHAPE_ATTRIBUTE); setMaxNodeCount(1000); - configureVertexType(DEFAULT_VERTEX, VertexShape.ELLIPSE, WebColors.RED); - configureVertexType(CONSTANT, VertexShape.ELLIPSE, WebColors.DARK_GREEN); - configureVertexType(REGISTER, VertexShape.ELLIPSE, WebColors.NAVY); - configureVertexType(UNIQUE, VertexShape.ELLIPSE, WebColors.BLACK); - configureVertexType(PERSISTENT, VertexShape.ELLIPSE, WebColors.DARK_ORANGE); - configureVertexType(ADDRESS_TIED, VertexShape.ELLIPSE, WebColors.ORANGE); - configureVertexType(OP, VertexShape.ELLIPSE, WebColors.RED); + configureVertexType(DEFAULT_VERTEX, VertexShape.ELLIPSE, BG_VERTEX_DEFAULT); + configureVertexType(CONSTANT, VertexShape.ELLIPSE, BG_VERTEX_CONSTANT); + configureVertexType(REGISTER, VertexShape.ELLIPSE, BG_VERTEX_REGISTER); + configureVertexType(UNIQUE, VertexShape.ELLIPSE, BG_VERTEX_UNIQUE); + configureVertexType(PERSISTENT, VertexShape.ELLIPSE, BG_VERTEX_PERSISTENT); + configureVertexType(ADDRESS_TIED, VertexShape.ELLIPSE, BG_VERTEX_ADDRESS_TIED); + configureVertexType(OP, VertexShape.ELLIPSE, BG_VERTEX_OP); - configureEdgeType(DEFAULT_EDGE, WebColors.BLUE); - configureEdgeType(WITHIN_BLOCK, WebColors.BLACK); - configureEdgeType(BETWEEN_BLOCKS, WebColors.RED); + configureEdgeType(DEFAULT_EDGE, BG_EDGE_DEFAULT); + configureEdgeType(WITHIN_BLOCK, BG_EDGE_WITHIN_BLOCK); + configureEdgeType(BETWEEN_BLOCKS, BG_EDGE_BETWEEN_BLOCKS); } } diff --git a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java index 844ce66f58..f0dd1dca60 100644 --- a/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java +++ b/Ghidra/Features/Decompiler/src/test.slow/java/ghidra/app/decompiler/component/DecompilerClangTest.java @@ -35,6 +35,7 @@ import docking.widgets.dialogs.InputDialog; import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; +import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.cmd.comments.SetCommentCmd; import ghidra.app.decompiler.*; import ghidra.app.decompiler.DecompileOptions.NamespaceStrategy; @@ -927,7 +928,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { String secondaryHighlightText = token.getText(); assertEquals("_printf", secondaryHighlightText); - Color myColor = Color.PINK; + Color myColor = Palette.PINK; highlightWithColorChooser(myColor); assertAllFieldsSecondaryHighlighted(token, myColor); } @@ -964,7 +965,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { String secondaryHighlightText = token.getText(); assertEquals("_printf", secondaryHighlightText); - Color myColor = Color.PINK; + Color myColor = Palette.PINK; highlightWithColorChooser(myColor); removeSecondaryHighlight(); @@ -1130,7 +1131,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1180,7 +1181,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { assertPrimaryHighlights("(\"call_structure_A: %s\\n\",a->name)"); String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1242,7 +1243,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { assertAllFieldsSecondaryHighlighted(secondrayToken, secondaryHlColor); String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1304,7 +1305,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { assertAllFieldsSecondaryHighlighted(secondaryToken, secondaryHlColor); String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1352,7 +1353,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText1 = "_printf"; - Color hlColor1 = Color.PINK; + Color hlColor1 = Palette.PINK; CTokenHighlightMatcher hlMatcher1 = token -> { if (token.getText().contains(hlText1)) { return hlColor1; @@ -1370,7 +1371,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { assertNoFieldsSecondaryHighlighted(hlText1); String hlText2 = "name"; - Color hlColor2 = Color.GREEN; + Color hlColor2 = Palette.GREEN; CTokenHighlightMatcher hlMatcher2 = token -> { if (token.getText().contains(hlText2)) { return hlColor2; @@ -1424,7 +1425,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { assertPrimaryHighlights("(\"call_structure_A: %s\\n\",a->name)"); String hlText = "_printf"; - Color hlColor1 = Color.PINK; + Color hlColor1 = Palette.PINK; CTokenHighlightMatcher hlMatcher1 = token -> { if (token.getText().contains(hlText)) { return hlColor1; @@ -1436,7 +1437,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { DecompilerHighlighter highlighter1 = hlService.createHighlighter(spyMatcher1); highlighter1.applyHighlights(); - Color hlColor2 = Color.GREEN; + Color hlColor2 = Palette.GREEN; CTokenHighlightMatcher hlMatcher2 = token -> { if (token.getText().contains(hlText)) { return hlColor2; @@ -1485,7 +1486,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1532,7 +1533,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1590,7 +1591,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1638,7 +1639,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1688,7 +1689,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; @@ -1736,7 +1737,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest { decompile("100000d60"); // '_call_structure_A' String hlText = "_printf"; - Color hlColor = Color.PINK; + Color hlColor = Palette.PINK; CTokenHighlightMatcher hlMatcher = token -> { if (token.getText().contains(hlText)) { return hlColor; diff --git a/Ghidra/Framework/Docking/data/docking.palette.theme.properties b/Ghidra/Framework/Docking/data/docking.palette.theme.properties index 8ba50f2732..933aa43144 100644 --- a/Ghidra/Framework/Docking/data/docking.palette.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.palette.theme.properties @@ -30,6 +30,7 @@ color.palette.orange = orange color.palette.palegreen = palegreen color.palette.palevioletred = PaleVioletRed color.palette.pink = pink +color.palette.purple = purple color.palette.red = red color.palette.yellow = yellow color.palette.yellowgreen = yellowgreen diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java index dd45f8c16d..7fb6a09f39 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/ColorPropertyEditor.java @@ -26,20 +26,31 @@ import ghidra.util.Swing; * Property Editor for Colors. Uses a {@link GhidraColorChooser} as its custom component */ public class ColorPropertyEditor extends PropertyEditorSupport { + private GhidraColorChooser colorChooser; private void colorChanged() { - // run later - allows debugging without hanging amazon aws + // run later - allows debugging without hanging the UI in some environments Swing.runLater(() -> setValue(colorChooser.getColor())); } @Override public Component getCustomEditor() { + if (colorChooser != null) { + return colorChooser; + } + colorChooser = new GhidraColorChooser(); colorChooser.getSelectionModel().addChangeListener(e -> colorChanged()); return colorChooser; } + public void saveState() { + if (colorChooser != null) { + colorChooser.addColorToHistory(colorChooser.getColor()); + } + } + @Override public boolean supportsCustomEditor() { return true; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java index b892ff2919..b4a9030eee 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/GhidraColorChooser.java @@ -44,10 +44,16 @@ public class GhidraColorChooser extends JColorChooser { this.title = title; } + public void addColorToHistory(Color c) { + recentColorCache.addColor(c); + maybeInstallSettableColorSwatchChooserPanel(); + } + public void setColorHistory(List colors) { for (Color color : colors) { recentColorCache.addColor(color); } + maybeInstallSettableColorSwatchChooserPanel(); } public List getColorHistory() { @@ -66,8 +72,6 @@ public class GhidraColorChooser extends JColorChooser { @SuppressWarnings("deprecation") public Color showDialog(Component centerOverComponent) { - maybeInstallSettableColorSwatchChooserPanel(); - OKListener okListener = new OKListener(); JDialog dialog = createDialog(centerOverComponent, title, true, this, okListener, null); doSetActiveTab(dialog); @@ -123,7 +127,7 @@ public class GhidraColorChooser extends JColorChooser { } private void maybeInstallSettableColorSwatchChooserPanel() { - if (recentColorCache.size() == 0) { + if (recentColorCache.isEmpty()) { return; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java index cadc6022b3..69ef32f4c5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ColorValueEditor.java @@ -19,7 +19,6 @@ import java.awt.Color; import java.beans.PropertyChangeListener; import docking.options.editor.ColorPropertyEditor; -import docking.theme.*; import generic.theme.*; /** @@ -45,4 +44,8 @@ public class ColorValueEditor extends ThemeValueEditor { return new ColorValue(id, color); } + @Override + protected void storeState() { + ((ColorPropertyEditor) editor).saveState(); + } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java index 439465113f..38d8700ebd 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeValueEditor.java @@ -34,7 +34,7 @@ public abstract class ThemeValueEditor { protected ThemeValue currentThemeValue; private EditorDialog dialog; private String typeName; - private PropertyEditor editor; + protected PropertyEditor editor; /** * Constructor @@ -67,6 +67,14 @@ public abstract class ThemeValueEditor { } + /** + * Called when the user has pressed ok. This allows sub-classes to store any state for + * future dialog invocations. + */ + protected void storeState() { + // for sub-classes + } + /** * Returns the actual value (Color, Font, or Icon) * @param id the theme property id for the value @@ -136,6 +144,7 @@ public abstract class ThemeValueEditor { @Override protected void okCallback() { close(); + storeState(); dialog = null; } @@ -145,5 +154,6 @@ public abstract class ThemeValueEditor { close(); dialog = null; } + } } diff --git a/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java b/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java index dd645e1a73..e72e8da2de 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/theme/GThemeDefaults.java @@ -100,6 +100,7 @@ public class GThemeDefaults { public static final GColor MAGENTA = getColor("magenta"); public static final GColor ORANGE = getColor("orange"); public static final GColor PINK = getColor("pink"); + public static final GColor PURPLE = getColor("purple"); public static final GColor RED = getColor("red"); public static final GColor WHITE = getColor("white"); public static final GColor YELLOW = getColor("yellow");