GP-2961 - Theme Fixes - Many changes to deal with odd rendering behavior in Nimbus and the Flat LaFs.

This commit is contained in:
dragonmacher 2022-12-29 14:51:25 -05:00
parent f443b2a907
commit fc301bb386
24 changed files with 274 additions and 167 deletions

View file

@ -28,8 +28,10 @@ color.fg.error.consoletextpane = color.fg.error
color.fg.infopanel.version = color.fg color.fg.infopanel.version = color.fg
color.fg.interpreterpanel = color.fg color.bg.interpreterconsole = color.bg
color.fg.interpreterpanel.error = color.fg.error color.fg.interpreterconsole = color.fg
color.fg.interpreterconsole.error = color.fg.error
color.bg.listing.highlighter.default = yellow color.bg.listing.highlighter.default = yellow
color.bg.listing.highlighter.scoped.read = rgb(204,204, 0) color.bg.listing.highlighter.scoped.read = rgb(204,204, 0)
color.bg.listing.highlighter.scoped.write = green color.bg.listing.highlighter.scoped.write = green
@ -207,3 +209,5 @@ color.bg.plugin.datamgr.edge.reference = deepskyblue
color.fg.plugin.equate.enum = deepskyblue color.fg.plugin.equate.enum = deepskyblue
color.bg.plugin.programdiff.highlight = darkRed color.bg.plugin.programdiff.highlight = darkRed

View file

@ -5,10 +5,12 @@
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<link rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css"> <link rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
</head> </head>
<body lang="EN-US">
<body>
<h1>Ghidra Bundles</h1> <h1>Ghidra Bundles</h1>
<h2>Dynamic modules</h2> <h2>Dynamic modules</h2>
<blockquote>
<p> Scripting brings a powerful form of dynamic extensibilty to Ghidra, <p> Scripting brings a powerful form of dynamic extensibilty to Ghidra,
where Java source code is (re)compiled, loaded, and run without exiting where Java source code is (re)compiled, loaded, and run without exiting
Ghidra. When a script grows large or requires external dependencies, it Ghidra. When a script grows large or requires external dependencies, it
@ -17,7 +19,7 @@
<p>To support modularity while preserving the dynamic nature of scripts, <p>To support modularity while preserving the dynamic nature of scripts,
Ghidra uses <a href="https://www.osgi.org">OSGi</a>. Without delving too Ghidra uses <a href="https://www.osgi.org">OSGi</a>. Without delving too
much into terminology, the key things to know are </p> much into terminology, the key things to know are </p>
<ol style="padding-left:8em"> <ol>
<li>The unit of modularity in OSGi is the <em>bundle</em>. Bundles are <li>The unit of modularity in OSGi is the <em>bundle</em>. Bundles are
<em>mostly independent</em> components with declared imports and exports. <em>mostly independent</em> components with declared imports and exports.
</li> </li>
@ -47,25 +49,34 @@
</li> </li>
</ol> </ol>
</blockquote>
<h2><a name="sourceBundles"/>Source bundles</h2> <h2><a name="sourceBundles"/>Source bundles</h2>
<blockquote>
<p>When a directory is added to the Bundle Manager, it is treated as a <p>When a directory is added to the Bundle Manager, it is treated as a
<em>source bundle</em>. When enabled, its Java contents are compiled to <em>source bundle</em>. When enabled, its Java contents are compiled to
</p>
<pre> <pre>
&lt;user home&gt;/.ghidra/.ghidra-&lt;version&gt;/osgi/compiled-bundles/&lt;hash&gt;/ &lt;user home&gt;/.ghidra/.ghidra-&lt;version&gt;/osgi/compiled-bundles/&lt;hash&gt;/
</pre> </pre>
<p>
where <code>&lt;hash&gt;</code> is a hash of the source bundle path. These compiled artifacts are then loaded where <code>&lt;hash&gt;</code> is a hash of the source bundle path. These compiled artifacts are then loaded
by the OSGi framework.</p> by the OSGi framework.
<h3>exploded bundles</h3> </p>
<h3>Exploded Bundles</h3>
<blockquote>
<p> <p>
Each such subdirectory of <code>compiled-bundles/</code> is an <em>exploded Each such subdirectory of <code>compiled-bundles/</code> is an <em>exploded
jar</em> -- by compressing it, we get a standard OSGi Jar bundle:</p> jar</em> -- by compressing it, we get a standard OSGi Jar bundle:</p>
<pre> <pre>
jar cMf mybundle.jar -C $HOME/.ghidra/.ghidra_&lt;version&gt;/osgi/compiled-bundles/&lt;hash&gt; . jar cMf mybundle.jar -C $HOME/.ghidra/.ghidra_&lt;version&gt;/osgi/compiled-bundles/&lt;hash&gt; .
</pre> </pre>
</blockquote>
<h3><a name="generated_files"/>generated files</h3> <h3><a name="generated_files"/>Generated Files</h3>
<blockquote>
<p>If there is no manifest in the source directory, Ghidra generates one <p>If there is no manifest in the source directory, Ghidra generates one
using <a href="https://bnd.bndtools.org/">bndlib</a> so that: using <a href="https://bnd.bndtools.org/">bndlib</a> so that:
</p> </p>
@ -77,13 +88,17 @@
<p> <p>
If no bundle activator is present, a stub is created and referenced in the generated manifest. If no bundle activator is present, a stub is created and referenced in the generated manifest.
</p> </p>
</blockquote>
</blockquote>
<h2><a name="dependency"/>Dependency</h2> <h2><a name="dependency"/>Dependency</h2>
<blockquote>
<p>Two types of code dependency are available when developing with OSGi, intra-bundle and <p>Two types of code dependency are available when developing with OSGi, intra-bundle and
inter-bundle.</p> inter-bundle.</p>
<h3>intra-bundle (<em>compile time</em>) dependency</h3> <h3>Intra-bundle (<em>compile time</em>) Dependency</h3>
<blockquote>
<p>Classes within a bundle, e.g. source files in a source bundle, can rely one another with <p>Classes within a bundle, e.g. source files in a source bundle, can rely one another with
Java's usual package <code>import</code>.</p> <p>This kind of dependency is resolved at Java's usual package <code>import</code>.</p> <p>This kind of dependency is resolved at
compile time -- if a class isn't imported or present, compilation will fail.</p> compile time -- if a class isn't imported or present, compilation will fail.</p>
@ -115,8 +130,10 @@
} }
} }
</pre> </pre>
</blockquote>
<h3><a name="inter-bundle-dependency" />inter-bundle (<em>run time</em>) dependency</h3> <h3><a name="inter-bundle-dependency" />Inter-bundle (<em>run time</em>) Dependency</h3>
<blockquote>
<p>To make use of code from <em>other</em> bundles, a bundle must declare its <p>To make use of code from <em>other</em> bundles, a bundle must declare its
dependencies. When a bundle is activated, the framework attempts to dependencies. When a bundle is activated, the framework attempts to
<em>resolve</em> its declared dependencies against active bundles. The <em>resolve</em> its declared dependencies against active bundles. The
@ -128,6 +145,7 @@
resolution.</p> resolution.</p>
<h4><code>@importpackage</code> in a script</h4> <h4><code>@importpackage</code> in a script</h4>
<blockquote>
<p>Ghidra's <code>@importpacakge</code> meta-data tag provides a convenient way to declare inter-bundle <p>Ghidra's <code>@importpacakge</code> meta-data tag provides a convenient way to declare inter-bundle
dependencies directly in a script. Set the value to a comma separated list of packages dependencies directly in a script. Set the value to a comma separated list of packages
to import from other bundles.</p> to import from other bundles.</p>
@ -161,8 +179,10 @@
} }
} }
</pre> </pre>
</blockquote>
<h4><code>Import-Package</code> in the manifest</h4> <h4><code>Import-Package</code> in the manifest</h4>
<blockquote>
<p>The underlying OSGi mechanism for declaring inter-bundle dependency is via the manifest.</p> <p>The underlying OSGi mechanism for declaring inter-bundle dependency is via the manifest.</p>
<p>You can find detailed descriptions of manifest attributes used by OSGi, like <code>Import-Package</code>, here <p>You can find detailed descriptions of manifest attributes used by OSGi, like <code>Import-Package</code>, here
@ -186,7 +206,10 @@
Bundle-Name: ab12cd89 Bundle-Name: ab12cd89
Bundle-Activator: GeneratedActivator Bundle-Activator: GeneratedActivator
</pre> </pre>
<p>
The manifest generated for <code>your_ghidra_scripts</code> is as follows: The manifest generated for <code>your_ghidra_scripts</code> is as follows:
</p>
<pre> <pre>
&lt;user home&gt;/.ghidra/.ghidra-&lt;version&gt;/osgi/compiled-bundles/ef34ab56/META-INF/MANIFEST.MF: &lt;user home&gt;/.ghidra/.ghidra-&lt;version&gt;/osgi/compiled-bundles/ef34ab56/META-INF/MANIFEST.MF:
Manifest-Version: 1.0 Manifest-Version: 1.0
@ -204,9 +227,12 @@
<p>For full control, users can include a manifest with their bundle's source, <p>For full control, users can include a manifest with their bundle's source,
e.g. <code>my_ghidra_scripts/META-INF/MANIFEST.MF</code>. </p> e.g. <code>my_ghidra_scripts/META-INF/MANIFEST.MF</code>. </p>
</blockquote>
</blockquote>
</blockquote>
<h2><a name="EnableBundles"/><a name="DisableBundles"/>Enabling and disabling bundles</h2> <h2><a name="EnableBundles"/><a name="DisableBundles"/>Enabling and disabling bundles</h2>
<blockquote>
<p>For a bundle's contents to be available (e.g. for loading classes), its <a <p>For a bundle's contents to be available (e.g. for loading classes), its <a
href="https://docs.osgi.org/specification/osgi.core/7.0.0/framework.lifecycle.html#d0e9143"> href="https://docs.osgi.org/specification/osgi.core/7.0.0/framework.lifecycle.html#d0e9143">
OSGi state</a> must be "<code>ACTIVE</CODE>". Ghidra generally takes care of this, but OSGi state</a> must be "<code>ACTIVE</CODE>". Ghidra generally takes care of this, but
@ -224,7 +250,7 @@
<p>The color of each bundle path reflects state as follows:</p> <p>The color of each bundle path reflects state as follows:</p>
<ul style="padding-left:8em"> <ul style="padding-left:8em">
<li> <span style="font-weight:bold;color:red">error</span> - e.g. the bundle file is missing <li> <span style="font-weight:bold;color:red">error</span> - e.g. the bundle file is missing
<li> <span style="font-weight:bold;color:#404040">disabled</span> - Ghidra knows the <li> <span style="font-weight:bold;">disabled</span> - Ghidra knows the
path, but that's it path, but that's it
<li> <span style="font-weight:bold;color:black">inactive</span> - scripts are visible in the script <li> <span style="font-weight:bold;color:black">inactive</span> - scripts are visible in the script
manager, but no classes are loaded. A bundle moves into this state when its manager, but no classes are loaded. A bundle moves into this state when its
@ -243,17 +269,19 @@
<li> (UNINSTALLED) - if the bundle is enabled, but the framework has released its handle. <li> (UNINSTALLED) - if the bundle is enabled, but the framework has released its handle.
This is typical for an inactive bundle This is typical for an inactive bundle
</ul> </ul>
</blockquote>
<h2><a name="AddBundles"/><a name="RemoveBundles"/>Adding and removing bundles from the manager</h2> <h2><a name="AddBundles"/><a name="RemoveBundles"/>Adding and removing bundles from the manager</h2>
<blockquote>
<p>Adding a directory to the bundle manager will also enable it, so scripts within become <p>Adding a directory to the bundle manager will also enable it, so scripts within become
available in the script manager.</p> available in the script manager.</p>
<p>Removing a bundle disables it, so its scripts will be removed from the script manager <p>Removing a bundle disables it, so its scripts will be removed from the script manager
and its dependents will become inactive.</p> and its dependents will become inactive.</p>
</blockquote>
<h2><a name="CleanBundles"/>Cleaning bundles</h2> <h2><a name="CleanBundles"/>Cleaning bundles</h2>
<blockquote>
<p>When Ghidra builds a source bundle, the results are written to the <p>When Ghidra builds a source bundle, the results are written to the
directory <br> directory <br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;user home&gt;/.ghidra/.ghidra-&lt;version&gt;/osgi/compiled-bundles/&lt;hash&gt;</code>. <br> &nbsp;&nbsp;&nbsp;&nbsp;<code>&lt;user home&gt;/.ghidra/.ghidra-&lt;version&gt;/osgi/compiled-bundles/&lt;hash&gt;</code>. <br>
@ -265,13 +293,23 @@
<p>If a source bundle's imports aren't available during build, some source files can <p>If a source bundle's imports aren't available during build, some source files can
produce errors. In order to force Ghidra to recompile, one must either modify the files produce errors. In order to force Ghidra to recompile, one must either modify the files
with errors or <em>clean</em> the bundle then re-enable.</p> with errors or <em>clean</em> the bundle then re-enable.</p>
</blockquote>
<h2><a name="RefreshBundles"/>Refresh bundles</h2> <h2><a name="RefreshBundles"/>Refresh bundles</h2>
<blockquote>
<p>Refresh will deactivate, clean, then reactivate every enabled bundle.</p> <p>Refresh will deactivate, clean, then reactivate every enabled bundle.</p>
</blockquote>
<P class="relatedtopic">Related Topics:</P>
<UL>
<LI><A href="help/topics/GhidraScriptMgrPlugin/GhidraScriptMgrPlugin.htm">Scripting</A></LI>
</UL>
<P>&nbsp;</P>
<BR>
<BR>
<BR>
</body> </body>
</html> </html>

View file

@ -734,6 +734,10 @@
<LI><A href="help/topics/ProgramTreePlugin/program_tree.htm">Program Tree</A></LI> <LI><A href="help/topics/ProgramTreePlugin/program_tree.htm">Program Tree</A></LI>
<LI><A href="help/topics/Selection/Selecting.htm">Selection &amp; Highlighting</A></LI> <LI><A href="help/topics/Selection/Selecting.htm">Selection &amp; Highlighting</A></LI>
</UL><BR> </UL>
<P>&nbsp;</P>
<BR>
<BR>
<BR>
</BODY> </BODY>
</HTML> </HTML>

View file

@ -324,8 +324,7 @@
<UL> <UL>
<LI> <LI>
<P class="relatedtopic"><A href= <A href="help/topics/Tool/ToolOptions_Dialog.htm#KeyBindings_Option">Key Bindings</A>
"help/topics/Tool/ToolOptions_Dialog.htm#KeyBindings_Option">Key Bindings</A></P>
</LI> </LI>
</UL> </UL>

View file

@ -2,16 +2,12 @@
<HTML> <HTML>
<HEAD> <HEAD>
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<TITLE>Script Development</TITLE> <TITLE>Script Development</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=windows-1252"> <META http-equiv="Content-Type" content="text/html; charset=windows-1252">
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css"> <LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
<META name="generator" content="Microsoft FrontPage 4.0">
</HEAD> </HEAD>
<BODY lang="EN-US"> <BODY>
<H1><A name="script_development"></A>Ghidra Script Development</H1> <H1><A name="script_development"></A>Ghidra Script Development</H1>
<P>Ghidra provides built-in support for creating scripts using the Java language and <P>Ghidra provides built-in support for creating scripts using the Java language and
@ -192,5 +188,17 @@
<P>Returns a new instance of the GhidraScript</P> <P>Returns a new instance of the GhidraScript</P>
</BLOCKQUOTE> </BLOCKQUOTE>
</BLOCKQUOTE> </BLOCKQUOTE>
<P class="relatedtopic">Related Topics:</P>
<UL>
<LI><A href="GhidraScriptMgrPlugin.htm">Scripting</A></LI>
</UL>
<P>&nbsp;</P>
<BR>
<BR>
<BR>
</BODY> </BODY>
</HTML> </HTML>

View file

@ -50,8 +50,9 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener {
"This is the font that will be used in the Console. " + "This is the font that will be used in the Console. " +
"Double-click the font example to change it."; "Double-click the font example to change it.";
private static final Color NORMAL_COLOR = new GColor("color.fg.interpreterpanel"); private static final Color NORMAL_COLOR = new GColor("color.fg.interpreterconsole");
private static final Color ERROR_COLOR = new GColor("color.fg.interpreterpanel.error"); private static final Color ERROR_COLOR = new GColor("color.fg.interpreterconsole.error");
private static final Color BG_COLOR = new GColor("color.bg.interpreterconsole");
public enum TextType { public enum TextType {
STDOUT, STDERR, STDIN; STDOUT, STDERR, STDIN;
@ -127,6 +128,10 @@ public class InterpreterPanel extends JPanel implements OptionsChangeListener {
inputTextPane = new JTextPane(); inputTextPane = new JTextPane();
inputTextPane.setName("Interpreter Input Field"); inputTextPane.setName("Interpreter Input Field");
outputTextPane.setBackground(BG_COLOR);
promptTextPane.setBackground(BG_COLOR);
inputTextPane.setBackground(BG_COLOR);
history = new HistoryManagerImpl(); history = new HistoryManagerImpl();
outputScrollPane.setFocusable(false); outputScrollPane.setFocusable(false);

View file

@ -35,6 +35,7 @@ class TipOfTheDayDialog extends DialogComponentProvider {
private static final String FONT_ID = "font.plugin.tips"; private static final String FONT_ID = "font.plugin.tips";
private static final String FONT_LABEL_ID = "font.plugin.tips.label"; private static final String FONT_LABEL_ID = "font.plugin.tips.label";
private static final int _24_HOURS = 86400000; private static final int _24_HOURS = 86400000;
private TipOfTheDayPlugin plugin; private TipOfTheDayPlugin plugin;
private JCheckBox showTipsCheckbox; private JCheckBox showTipsCheckbox;
private JButton nextTipButton; private JButton nextTipButton;
@ -61,15 +62,16 @@ class TipOfTheDayDialog extends DialogComponentProvider {
tipArea.setWrapStyleWord(true); tipArea.setWrapStyleWord(true);
tipArea.setLineWrap(true); tipArea.setLineWrap(true);
tipArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); tipArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
tipArea.setBackground(Colors.BACKGROUND);
JScrollPane tipScroll = new JScrollPane(tipArea); JScrollPane tipScroll = new JScrollPane(tipArea);
tipScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); tipScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
tipScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); tipScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
tipScroll.setBorder(null); tipScroll.setBorder(BorderFactory.createEmptyBorder());
tipScroll.setPreferredSize(tipArea.getPreferredSize()); tipScroll.setPreferredSize(tipArea.getPreferredSize());
showTipsCheckbox = new GCheckBox("Show Tips on Startup?"); showTipsCheckbox = new GCheckBox("Show Tips on Startup?");
showTipsCheckbox.setSelected(true); // TODO (FixMe) Moved this before its listener to prevent project save for now. showTipsCheckbox.setSelected(true); // before adding the listener to prevent project save
showTipsCheckbox.addItemListener(e -> showTipsChanged()); showTipsCheckbox.addItemListener(e -> showTipsChanged());
nextTipButton = new JButton("Next Tip"); nextTipButton = new JButton("Next Tip");
@ -88,9 +90,10 @@ class TipOfTheDayDialog extends DialogComponentProvider {
BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10), BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10),
BorderFactory.createLineBorder(Java.BORDER)); BorderFactory.createLineBorder(Java.BORDER));
panel.setBorder(panelBorder); panel.setBorder(panelBorder);
panel.setBackground(Colors.BACKGROUND);
JLabel label = new GLabel("Did you know...", tipIcon, SwingConstants.LEFT); JLabel label = new GLabel("Did you know...", tipIcon, SwingConstants.LEFT);
label.setBackground(Colors.BACKGROUND);
label.setOpaque(true);
Gui.registerFont(label, FONT_LABEL_ID); Gui.registerFont(label, FONT_LABEL_ID);
panel.add(label, BorderLayout.NORTH); panel.add(label, BorderLayout.NORTH);

View file

@ -15,5 +15,7 @@ color.fg.plugin.python.syntax.special = darkgreen
icon.plugin.python = python.png icon.plugin.python = python.png
[Dark Defaults] [Dark Defaults]

View file

@ -2,9 +2,6 @@
<HTML> <HTML>
<HEAD> <HEAD>
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<TITLE>Python Interpreter</TITLE> <TITLE>Python Interpreter</TITLE>
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css"> <LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
</HEAD> </HEAD>
@ -165,5 +162,10 @@
<P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P> <P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P>
<P>&nbsp;</P>
<BR>
<BR>
<BR>
</BODY> </BODY>
</HTML> </HTML>

View file

@ -249,18 +249,6 @@ public class PythonCodeCompletionFactory {
includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT); includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT);
options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null, options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null,
INCLUDE_TYPES_DESCRIPTION); INCLUDE_TYPES_DESCRIPTION);
Iterator<?> iter = classes.iterator();
while (iter.hasNext()) {
Class<?> currentClass = (Class<?>) iter.next();
options.registerOption(
COMPLETION_LABEL + Options.DELIMITER + getSimpleName(currentClass),
classToColorMap.get(currentClass), null,
"Color to use for " + classDescription.get(currentClass) + ".");
classToColorMap.put(currentClass,
options.getColor(COMPLETION_LABEL + Options.DELIMITER + getSimpleName(currentClass),
classToColorMap.get(currentClass)));
}
} }
/** /**
@ -279,13 +267,7 @@ public class PythonCodeCompletionFactory {
*/ */
public static void changeOptions(Options options, String name, Object oldValue, public static void changeOptions(Options options, String name, Object oldValue,
Object newValue) { Object newValue) {
String classSimpleName = name.substring((COMPLETION_LABEL + Options.DELIMITER).length()); if (name.equals(INCLUDE_TYPES_LABEL)) {
Class<?> klass = simpleNameToClass.get(classSimpleName);
if (classToColorMap.containsKey(klass)) {
classToColorMap.put(klass, (Color) newValue);
}
else if (name.equals(INCLUDE_TYPES_LABEL)) {
includeTypes = ((Boolean) newValue).booleanValue(); includeTypes = ((Boolean) newValue).booleanValue();
} }
else { else {

View file

@ -1,58 +0,0 @@
/* ###
* 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.
*/
/*
Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but
px (pixel) or with no type marking.
*/
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
li { font-family:times new roman; font-size:14pt; }
h1 { color:#80a0c0; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#DDA0DD; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#6495ED; font-family:times new roman; font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
way it had been done in the beginning). The net effect is that the text is indented. In
modern HTML we would use CSS to do this. We need to support the Ghidra P tags, nested in
blockquote tags, as well as naked P tags. The following two lines accomplish this. Note
that the 'blockquote p' definition will inherit from the first 'p' definition.
*/
p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
blockquote p { margin-left: 10px; }
p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.relatedtopic { color:#9370DB; margin-left: 10px; font-size:14pt; }
p.RelatedTopic { color:#9370DB; margin-left: 10px; font-size:14pt; }
/*
We wish for a tables to have space between it and the preceding element, so that text
is not too close to the top of the table. Also, nest the table a bit so that it is clear
the table relates to the preceding text.
*/
table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; color: gray;}
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: #F5F5F5; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -16,8 +16,7 @@
package docking.action; package docking.action;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.swing.*; import javax.swing.*;
@ -29,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingWindowManager; import docking.DockingWindowManager;
import generic.theme.GColor;
import generic.util.action.ReservedKeyBindings; import generic.util.action.ReservedKeyBindings;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -154,6 +154,15 @@ public class ComponentThemeInspectorAction extends DockingAction {
spacer = "\t"; spacer = "\t";
} }
String bgText = Objects.toString(bg);
if (bg instanceof GColor gColor) {
bgText = gColor.toDebugString();
}
String fgText = Objects.toString(fg);
if (fg instanceof GColor gColor) {
fgText = gColor.toDebugString();
}
String tabs = '\n' + StringUtils.repeat(' ', (indent * 3)); String tabs = '\n' + StringUtils.repeat(' ', (indent * 3));
buffy.append(tabs) buffy.append(tabs)
.append(indentMarker) .append(indentMarker)
@ -161,11 +170,11 @@ public class ComponentThemeInspectorAction extends DockingAction {
.append(tabs) .append(tabs)
.append(spacer) .append(spacer)
.append("bg: ") .append("bg: ")
.append(bg) .append(bgText)
.append(tabs) .append(tabs)
.append(spacer) .append(spacer)
.append("fg: ") .append("fg: ")
.append(fg) .append(fgText)
.append('\n'); .append('\n');
} }

View file

@ -58,6 +58,7 @@ public class DefaultTableCellRendererWrapper extends GTableCellRenderer {
JComponent thisRenderer = (JComponent) super.getTableCellRendererComponent(data); JComponent thisRenderer = (JComponent) super.getTableCellRendererComponent(data);
rendererComponent.setForeground(thisRenderer.getForeground());
rendererComponent.setBackground(thisRenderer.getBackground()); rendererComponent.setBackground(thisRenderer.getBackground());
if (rendererComponent instanceof JComponent) { if (rendererComponent instanceof JComponent) {

View file

@ -8,6 +8,7 @@
##MODULE IP: Tango Icons - Public Domain ##MODULE IP: Tango Icons - Public Domain
.classpath||GHIDRA||||END| .classpath||GHIDRA||||END|
Module.manifest||GHIDRA||||END| Module.manifest||GHIDRA||||END|
data/gui.laf.overrides.theme.properties||GHIDRA||||END|
data/gui.palette.theme.properties||GHIDRA||||END| data/gui.palette.theme.properties||GHIDRA||||END|
data/gui.theme.properties||GHIDRA||||END| data/gui.theme.properties||GHIDRA||||END|
src/main/java/ghidra/framework/options/package.html||GHIDRA||||END| src/main/java/ghidra/framework/options/package.html||GHIDRA||||END|

View file

@ -0,0 +1,55 @@
[Defaults]
// TODO these are only here because they are used in the dark section; remove from here if done in
// source code instead; otherwise, update error reporting to not require an entry in the default
// section for values defined in specific LaF sections
color.flat.text.original.bg = white // default 'text' value in Flat Light
color.flat.selection.inactive.bg = #d3d3d3 // default value in Flat Light
[Dark Defaults]
[Flat Dark]
// the default inactive selection color is too close to the bg color to be easily visible
color.flat.selection.inactive.bg = #0F4C6A
//
// We would like widgets to use a bg color. By default widgets and some other items are all mapped
// to 'text'. The easiest way to change all widgets is to change the value of 'text'. Then, for
// any values that should still use the old value, we need to remap those. (The foreground colors
// for these are mapped to 'textText'. For now, that value seems good enough that we do not need
// to change it.)
//
color.flat.text.original.bg = #46494b // default 'text' value
[color]text = color.bg
[color]desktop = color.flat.text.original.bg
[color]TableHeader = color.flat.text.original.bg
[color]Checkbox.icon.background = color.flat.text.original.bg
[color]Checkbox.icon.selectedBackground = color.flat.text.original.bg
[color]CheckBox.icon[filled].checkmarkColor = color.flat.text.original.bg
[color]ComboBox.buttonBackground = color.flat.text.original.bg
[color]Spinner.background = color.flat.text.original.bg
[color]TextArea.background = color.bg
[color]TextArea.foreground = color.fg
[color]TextPane.background = color.bg
[color]TextPane.foreground = color.fg
[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

View file

@ -128,11 +128,6 @@ color.bg.tree = color.bg
color.bg.tree.selected = [color]Tree.selectionBackground 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] [CDE/Motif]
@ -140,10 +135,3 @@ color.bg = [color]window // gray for motif
color.fg = [color]textText 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

View file

@ -61,6 +61,11 @@ public class ColorValue extends ThemeValue<Color> {
return outputId + " = " + getSerializedValue(); return outputId + " = " + getSerializedValue();
} }
@Override
public boolean isExternal() {
return !id.startsWith(COLOR_ID_PREFIX);
}
/** /**
* Returns true if the given key string is a valid external key for a color value * Returns true if the given key string is a valid external key for a color value
* @param key the key string to test * @param key the key string to test
@ -93,7 +98,7 @@ public class ColorValue extends ThemeValue<Color> {
} }
@Override @Override
protected Color getUnresolvedReferenceValue(String id, String unresolvedId) { protected Color getUnresolvedReferenceValue(String primaryId, String unresolvedId) {
Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan(); Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan();
StackTraceElement[] trace = t.getStackTrace(); StackTraceElement[] trace = t.getStackTrace();
@ -104,7 +109,7 @@ public class ColorValue extends ThemeValue<Color> {
Msg.error(this, Msg.error(this,
"Could not resolve indirect color path for \"" + unresolvedId + "Could not resolve indirect color path for \"" + unresolvedId +
"\" for primary id \"" + id + "\", using last resort default", "\" for primary id \"" + primaryId + "\", using last resort default",
t); t);
return LAST_RESORT_DEFAULT; return LAST_RESORT_DEFAULT;
} }

View file

@ -57,6 +57,17 @@ public class FontValue extends ThemeValue<Font> {
this.modifier = modifier; this.modifier = modifier;
} }
@Override
public String getSerializationString() {
String outputId = toExternalId(id);
return outputId + " = " + getValueOutput();
}
@Override
public boolean isExternal() {
return !id.startsWith(FONT_ID_PREFIX);
}
@Override @Override
public Font get(GThemeValueMap values) { public Font get(GThemeValueMap values) {
Font font = super.get(values); Font font = super.get(values);
@ -66,12 +77,6 @@ public class FontValue extends ThemeValue<Font> {
return font; return font;
} }
@Override
public String getSerializationString() {
String outputId = toExternalId(id);
return outputId + " = " + getValueOutput();
}
private String getValueOutput() { private String getValueOutput() {
if (referenceId != null) { if (referenceId != null) {
String refId = toExternalId(referenceId); String refId = toExternalId(referenceId);
@ -107,7 +112,7 @@ public class FontValue extends ThemeValue<Font> {
* @param key the key to associate the parsed value with * @param key the key to associate the parsed value with
* @param value the font value to parse * @param value the font value to parse
* @return a FontValue with the given key and the parsed value * @return a FontValue with the given key and the parsed value
* @throws ParseException * @throws ParseException if there is an exception parsing
*/ */
public static FontValue parse(String key, String value) throws ParseException { public static FontValue parse(String key, String value) throws ParseException {
String id = fromExternalId(key); String id = fromExternalId(key);
@ -148,10 +153,10 @@ public class FontValue extends ThemeValue<Font> {
} }
@Override @Override
protected Font getUnresolvedReferenceValue(String id, String unresolvedId) { protected Font getUnresolvedReferenceValue(String primaryId, String unresolvedId) {
Msg.warn(this, Msg.warn(this,
"Could not resolve indirect font path for \"" + unresolvedId + "Could not resolve indirect font path for \"" + unresolvedId +
"\" for primary id \"" + id + "\", using last resort default"); "\" for primary id \"" + primaryId + "\", using last resort default");
return LAST_RESORT_DEFAULT; return LAST_RESORT_DEFAULT;
} }

View file

@ -74,6 +74,17 @@ public class IconValue extends ThemeValue<Icon> {
this.modifier = modifier; this.modifier = modifier;
} }
@Override
public String getSerializationString() {
String outputId = toExternalId(id);
return outputId + " = " + getValueOutput();
}
@Override
public boolean isExternal() {
return !id.startsWith(ICON_ID_PREFIX);
}
@Override @Override
public Icon get(GThemeValueMap values) { public Icon get(GThemeValueMap values) {
Icon icon = super.get(values); Icon icon = super.get(values);
@ -83,12 +94,6 @@ public class IconValue extends ThemeValue<Icon> {
return icon; return icon;
} }
@Override
public String getSerializationString() {
String outputId = toExternalId(id);
return outputId + " = " + getValueOutput();
}
/** /**
* Returns true if the given key string is a valid external key for an icon value * Returns true if the given key string is a valid external key for an icon value
* @param key the key string to test * @param key the key string to test
@ -197,10 +202,10 @@ public class IconValue extends ThemeValue<Icon> {
} }
@Override @Override
protected Icon getUnresolvedReferenceValue(String id, String unresolvedId) { protected Icon getUnresolvedReferenceValue(String primaryId, String unresolvedId) {
Msg.warn(this, Msg.warn(this,
"Could not resolve indirect icon path for \"" + unresolvedId + "Could not resolve indirect icon path for \"" + unresolvedId +
"\" for primary id \"" + id + "\", using last resort default"); "\" for primary id \"" + primaryId + "\", using last resort default");
return LAST_RESORT_DEFAULT; return LAST_RESORT_DEFAULT;
} }

View file

@ -79,6 +79,7 @@ public class ThemePropertyFileReader extends AbstractThemeReader {
return customSectionsMap; return customSectionsMap;
} }
@Override
protected void processNoSection(Section section) throws IOException { protected void processNoSection(Section section) throws IOException {
if (!section.isEmpty()) { if (!section.isEmpty()) {
error(section.getLineNumber(), error(section.getLineNumber(),
@ -125,20 +126,29 @@ public class ThemePropertyFileReader extends AbstractThemeReader {
private void validate(String name, GThemeValueMap valuesMap) { private void validate(String name, GThemeValueMap valuesMap) {
for (String id : valuesMap.getColorIds()) { for (String id : valuesMap.getColorIds()) {
if (!defaults.containsColor(id)) { if (!defaults.containsColor(id)) {
ColorValue value = valuesMap.getColor(id);
if (!value.isExternal()) {
reportMissingDefaultsError("Color", name, id); reportMissingDefaultsError("Color", name, id);
} }
} }
}
for (String id : valuesMap.getFontIds()) { for (String id : valuesMap.getFontIds()) {
if (!defaults.containsFont(id)) { if (!defaults.containsFont(id)) {
FontValue value = valuesMap.getFont(id);
if (!value.isExternal()) {
reportMissingDefaultsError("Font", name, id); reportMissingDefaultsError("Font", name, id);
} }
} }
}
for (String id : valuesMap.getIconIds()) { for (String id : valuesMap.getIconIds()) {
if (!defaults.containsIcon(id)) { if (!defaults.containsIcon(id)) {
IconValue value = valuesMap.getIcon(id);
if (!value.isExternal()) {
reportMissingDefaultsError("Icon", name, id); reportMissingDefaultsError("Icon", name, id);
} }
} }
} }
}
private void reportMissingDefaultsError(String type, String name, String id) { private void reportMissingDefaultsError(String type, String name, String id) {
String message = type + " id found in \"" + name + String message = type + " id found in \"" + name +

View file

@ -41,6 +41,13 @@ public abstract class ThemeValue<T> implements Comparable<ThemeValue<T>> {
this.value = value; this.value = value;
} }
/**
* True if this value is one that is one that is defined outside of the application, such as a
* Java Look and Feel key.
* @return true if external
*/
public abstract boolean isExternal();
/** /**
* Returns the identifier for this ThemeValue. * Returns the identifier for this ThemeValue.
* @return the identifier for this ThemeValue. * @return the identifier for this ThemeValue.
@ -189,11 +196,11 @@ public abstract class ThemeValue<T> implements Comparable<ThemeValue<T>> {
/** /**
* Returns the T to be used if the indirect reference couldn't be resolved. * Returns the T to be used if the indirect reference couldn't be resolved.
* @param id the id we are trying to get a value foe * @param primaryId the id we are trying to get a value for
* @param unresolvedId the reference id that couldn't be resolved * @param unresolvedId the reference id that couldn't be resolved
* @return the default value to be used if the indirect reference couldn't be resolved. * @return the default value to be used if the indirect reference couldn't be resolved.
*/ */
protected abstract T getUnresolvedReferenceValue(String id, String unresolvedId); protected abstract T getUnresolvedReferenceValue(String primaryId, String unresolvedId);
/** /**
* Returns the ThemeValue referred to by this ThemeValue. Needs to be overridden by * Returns the ThemeValue referred to by this ThemeValue. Needs to be overridden by

View file

@ -21,7 +21,7 @@ color.fg.help.selector.h1 = #66AAF4
color.fg.help.selector.h2 = #9999F9 color.fg.help.selector.h2 = #9999F9
color.fg.help.selector.h3 = #FF99CC color.fg.help.selector.h3 = #FF99CC
color.fg.help.selector.p.provided.by.plugin = #CCCCCC color.fg.help.selector.p.provided.by.plugin = #CCCCCC
color.fg.help.selector.p.related.topic = #800080 color.fg.help.selector.p.related.topic = #9370DB
color.fg.help.selector.th = #EDF3FE color.fg.help.selector.th = #EDF3FE
color.fg.help.selector.code = gray color.fg.help.selector.code = gray
color.fg.help.selector.code.path = #5BA5E3 color.fg.help.selector.code.path = #5BA5E3

View file

@ -14,17 +14,50 @@
* limitations under the License. * limitations under the License.
*/ */
/* /*
WARNING!
Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but
px (pixel) or with no type marking. px (pixel) or with no type marking.
The blockquote tag is used heavily to control indentation throughout the help docs. Place the
blockquote tag around other elements to create a standard indentation. The default values of
blockquote are:
blockquote {
display: block;
margin-top: 1em;
margin-bottom: 1em;
margin-left: 40px;
margin-right: 40px;
}
*/ */
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
li { font-family:times new roman; font-size:14pt; }
h1 { color:#80a0c0; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } /*
h2 { margin: 10px; margin-top: 20px; color:#DDA0DD; font-family:times new roman; font-size:18pt; font-weight:bold; } Add some indentation for lists to show their relation to the preceding text. The value is
h3 { margin-left: 10px; margin-top: 20px; color:#6495ED; font-family:times new roman; font-size:14pt; font-weight:bold; } chosen based on the left margin of the body and the blockquote.
*/
ul { margin-left: 50px; }
ol { margin-left: 50px; }
li { font-family:times new roman; font-size:14pt; margin-left: 5px; }
h1 { color:#66AAF4; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#9999F9; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#FF99CC; font-family:times new roman; font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
A class to be used for showing screenshot style images. These images will have padding above
and below the image and will be centered. To apply this to a file path, use this syntax:
<DIV class="image"><IMG src="..." /></DIV>
*/
div.image { margin-top: 20px; margin-bottom: 40px; text-align: center; }
/* /*
P tag code. Most of the help files nest P tags inside of blockquote tags (the was the P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
way it had been done in the beginning). The net effect is that the text is indented. In way it had been done in the beginning). The net effect is that the text is indented. In
@ -34,11 +67,10 @@ h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size
*/ */
p { margin-left: 40px; font-family:times new roman; font-size:14pt; } p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
blockquote p { margin-left: 10px; } blockquote p { margin-left: 10px; }
p.providedbyplugin { color:#CCCCCC; margin-left: 10px; font-size:14pt; margin-top:100px }
p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.relatedtopic { color:#9370DB; margin-left: 10px; font-size:14pt; } p.relatedtopic { color:#9370DB; margin-left: 10px; font-size:14pt; }
p.RelatedTopic { color:#9370DB; margin-left: 10px; font-size:14pt; } p.image { margin-top: 100; margin-bottom: 100; }
/* /*
We wish for a tables to have space between it and the preceding element, so that text We wish for a tables to have space between it and the preceding element, so that text
@ -49,10 +81,11 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; } td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; color: gray;} th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; color: gray;}
/* /*
Code-like formatting for things such as file system paths and proper names of classes, Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax: methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE> <CODE CLASS="path">...</CODE>
*/ */
code { color: #F5F5F5; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; } code { color: gray; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; } code.path { color: #5BA5E3; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -32,7 +32,6 @@
*/ */
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
/* /*
Add some indentation for lists to show their relation to the preceding text. The value is Add some indentation for lists to show their relation to the preceding text. The value is