diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/agent/AgentWindow.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/agent/AgentWindow.java
index 3198ac29c1..5e1c7a995a 100644
--- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/agent/AgentWindow.java
+++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/agent/AgentWindow.java
@@ -28,7 +28,6 @@ import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
-import generic.theme.GThemeDefaults.Colors.Messages;
import ghidra.framework.LoggingInitialization;
import ghidra.util.Msg;
import ghidra.util.Swing;
@@ -74,11 +73,7 @@ public class AgentWindow extends JFrame implements WindowListener, LogListener {
@Override
public void messageLogged(String message, boolean isError) {
-<<<<<<< Upstream, based on origin/master
-=======
- String fMessage =
- isError ? "" + message + "" : message;
->>>>>>> 1e5309a GP-1981 - Theming - Color conversion for Debugger modules
+
Swing.runIfSwingOrRunLater(() -> {
MutableAttributeSet attributes = new SimpleAttributeSet();
if (isError) {
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm b/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm
index 75d88be43f..fda1271536 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm
@@ -165,7 +165,7 @@
with the analyzer.
-
+
Note that multi-user merge does not currently support
merging of Program Options (including Analysis Options). Options stored in shared Program database
following a conflicting checkin may not reflect option settings specified prior to checkin.
@@ -182,9 +182,9 @@
the current program.
-
+
Access to stored configurations is not currently
- aupported across different versions of Ghidra.
+ supported across different versions of Ghidra.
@@ -452,7 +452,7 @@
-
+
When using an external GNU demangler,
please understand the risks associated with using that version of the
software. The demangler_gnu_v2_24 version of the
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm b/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm
index 6c8abbef53..db73da2d09 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/FrontEndPlugin/Ghidra_Front_end.htm
@@ -448,12 +448,11 @@
diff --git a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml
index 584eba039b..233752f8a2 100644
--- a/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml
+++ b/Ghidra/Framework/Docking/src/main/help/help/TOC_Source.xml
@@ -60,8 +60,8 @@
-
-
+
+
diff --git a/Ghidra/Framework/Docking/src/main/help/help/shared/DarkStyle.css b/Ghidra/Framework/Docking/src/main/help/help/shared/DarkStyle.css
new file mode 100644
index 0000000000..6ff0fe6fb8
--- /dev/null
+++ b/Ghidra/Framework/Docking/src/main/help/help/shared/DarkStyle.css
@@ -0,0 +1,58 @@
+/* ###
+ * 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 { 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; }
diff --git a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html
index 4be4a61936..086394618e 100644
--- a/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html
+++ b/Ghidra/Framework/Docking/src/main/help/help/topics/Theming/ThemingDeveloperDocs.html
@@ -5,129 +5,139 @@
- Theming Developer Documentation
-
-
+ Developer's Guide
-
Ghidra Theming Developer Documentation
+
Developer's Guide to Theming
-
This document provides everything an application developer should know when developing
- plugins, scripts, etc., that use colors, fonts, or icons. By following these guidelines,
+
This document provides information an application developer should know when developing
+ plugins, actions, scripts, etc., that use colors, fonts, or icons. By following these guidelines,
developers can easily make use of Ghidra's theming capabilities.
Theme Resource Types
When developing application code for Ghidra such as plugins, actions, etc., developers often
- want to use a color, font, or icon. The key idea to support theming is to never directly
- reference these resources. Instead, the developer should "create" an id string for the resource
- and then in a .theme.properties file provide a default value for that id (and if appropriate,
- also define an alternate default value if the theme is a "dark" theme). The way you
- define and use these ids is a bit different depending on whether the resource is a color, font,
- or icon. Colors and Icons are similar in that references are done using either GColor or GIcon,
- Unfortunately, because of the way Fonts are implemented, there is no GFont, so using fonts is a
- bit more involved.
+ want to use colors, fonts, and icons. The key idea to support theming is to never
+ directly
+ reference those resources. Instead, the developer should create an ID string for the resource
+ and then in a module.theme.properties file, provide a default value for that ID.
+ (Also, you may define an alternate "dark" default value that will be used if the
+ current theme is considered a dark theme). The way you
+ define and use these IDs is a bit different depending on whether the resource is a color, font,
+ or icon. Colors and icons are similar in that developers use these types by creating either
+ GColor or GIcon.
+ Unfortunately, because of the way fonts are implemented, there is no equivalent
+ GFont, so using fonts is a bit more involved.
Colors
-
For colors, developers should use the GColor class. Simply construct a new GColor object
- passing in the color resource id as the argument. GColor is a subclass of Color, so it can be
- used anywhere a Color would be used. The developer then needs to provide a default value for
- that id in the module's theme.properties file. So, for example:
+
For colors, developers should use the GColor class. Simply construct a new
+ GColor object passing in the color resource ID as the argument.
+ GColor is a subclass of Color, so it can be
+ used anywhere a Color would be used. The developer then needs to provide a
+ default value for that ID in the module's module.theme.properties file.
+ So, for example:
- public static final Color MY_COLOR = Color.BLUE;
+ public static final Color MY_COLOR = Color.BLUE;
becomes
- public static final Color MY_COLOR = new
+ public static final Color MY_COLOR = new
GColor("color.fg.xzy");
-
The GColor class uses a delegation model where all method calls to GColor get mapped to
- its delegate. If ever the color associated with a GColor's resource id changes, the GColor is
- refreshed by calling the refresh() method. This is done automatically whenever the
- Gui.setColor(id) is called or a new theme is loaded.
+
The GColor class uses a delegation model where all method calls to
+ GColor get mapped to
+ its delegate color. If ever the color associated with a GColor's resource ID
+ changes, the GColor is automatically updated by calling the
+ refresh() method. This is done whenever the
+ Gui.setColor(id) is called or a new theme is loaded.
+
+
Icons
+
+
Icons work just like colors, so you can just create a GIcon(String id).
+ So, for example,
+
+
+
+ public static final Icon MY_ICON =
+ ResourceManager("images/balloon.png");
+
+
+
becomes
+
+
+ public static final Icon MY_ICON = new
+ GIcon("icon.text.bubble");
+
+
Fonts
-
Unfortunately, fonts able to use the delegation trick that was used for colors. Therefore,
- there is no GFont class. Programming fonts requires a bit more work. If the use of a font is
- in a renderer or in a paint method, imply get the font each time from the Gui class (Font
- font = Gui.getFont(String id)). To set a font on a component, use the "registerFont" method
- on the Gui class. Once the component is registered, the application will automatically update
- the component's font if the font associated with that id changes. So, for example:
+
Unfortunately, fonts are unable to use the delegation model used for colors and icons.
+ Therefore, there is no GFont class. Programming fonts requires a bit more work.
+ If a font used directly, such as in renderer or in a paint method, simply get the
+ font each time
+ from the Gui class, as shown below. To set a font on a component, use
+ Gui.registerFont(Component, String). Once the component is registered, the
+ application will
+ automatically update the component if the font associated with that ID changes. So, for
+ example:
- Font font = new Font("Monospaced", Font.BOLD, 12);
+ Font font = new Font("Monospaced", Font.BOLD, 12);
becomes
- Font font = Gui.getFont("font.xyz");
+ Font font = Gui.getFont("font.xyz");
Icons work just like colors, so you can just create a GIcon(String id). So, for
- example,
-
-
- public static final Icon MY_ICON =
- ResourceManager("images/balloon.png");
-
-
-
becomes
-
-
- public static final Icon MY_ICON = new
- GIcon("icon.text.bubble");
-
-
-
-
-
Resource Id Strings
+
Resource ID Strings
-
Resource Ids are strings used to identify the color, font, or icon. These strings are
- "made up" by the developer and should be chosen in a way that it is as self describing as
+
Resource IDs are strings used to identify a color, font, or icon. These strings are
+ created by the developer and should be chosen in a way that it is as self-describing as
possible. So, for example, if you wanted the text color in some error message in some widget
- "abc", you might create the color id "color.fg.abc.error". To make resource ids as consistent
- as possible, we created a convention for ids as follows:
+ "abc", you might create the color ID "color.fg.abc.error". To help keep resource IDs
+ consistent, we created a convention for IDs as follows:
@@ -145,11 +155,10 @@
category: any value, examples include 'bg'(background), 'fg'(foreground),
'cursor'. There may be multiple dot-separated values.
-
client: the plugin name or feature name; any value usd to represent a more
- specialized use.
+
client: the plugin name or feature name.
specialized uses: any key value here that applies to the client, such as
- "vertex' for a graph client.
+ 'vertex' for a graph client.
@@ -160,6 +169,8 @@
color.bg.listing
+
color.bg.functiongraph.vertex.group
+
font.listing
font.listing.header
@@ -176,11 +187,16 @@
Theme Property Files
-
The default values for resource ids are defined in "theme property" files that created in
- each module's data directory. For small modules there can be just one theme properties, but
- larger modules should probably use multiple files; one for each sub-feature. The application
- will find all theme property files as long as they exist in a module's data directory and end
- with '.theme.properties'.
+
The default values for resource IDs are defined in files that reside
+ a module's data directory (not all modules define this file). These files all
+ are named to end in theme.properties and begin with the module's name. Some
+ modules make use of multiple files in order to better manage the volume of IDs. In this
+ case, the name of each properties file offers a clue as to its contents. Thus, for small
+ modules, those without many resource IDs in use, one theme properties file is sufficient to
+ easily define and manage all required IDs. But, we recommend larger modules use multiple
+ files, one for each sub-feature. The application will find all theme property files as long as
+ they exist in a module's data directory and are named with the
+ .theme.properties suffix.
Theme files uses a very simple format for specifying theme property values. Each line
- specifies a property id (sometimes referfed to as key) and a value, separated by an "=". A
- theme properties file consists of two sections: the standard defaults section and a section
- for specifying defaults for "dark" themes. So a file theme file uses the following
- format:
+ specifies a property ID (sometimes referred to as the key) and a value, separated by an
+ "=". A theme properties file consists of two sections: the standard defaults section and a
+ section for specifying defaults for "dark" themes.
+
NOTE: The [Dark Defaults] section is for overriding values defined in the standard
- [Defaults] section. If a property id is not given a value in the defaults section, it is an
- error. If a value is not defined in the [Dark Defaults] section, then the value defined in
- the [Defaults] section will be used in a dark theme.
+
+
NOTE: The [Dark Defaults] section is for optionally overriding values
+ defined in the standard [Defaults] section. If a property ID is not given a value
+ in the defaults section, it is an error. If a value is not defined in the
+ [Dark Defaults] section, then the value defined in the [Defaults]
+ section will be used in a dark theme.
-
Theme Property Values
+
Theme Property Values
The values specified in the theme properties files can be specified in a variety of ways,
@@ -273,15 +291,15 @@ color.fg.listing.bytes = orange
directly in the theme properties file. A font value can specified as a reference to another
defined font, but with a different size or style.
-
Also, any value can also be a reference to some other id of the same type. So, for
+
Also, any value can also be a reference to some other ID of the same type. So, for
example, a reference color entry might be something like "color.bg.listing = color.bg". This
says that the listing's background color should be whatever "color.bg" is defined to be. Note
that all of the application's defined properties start with either "color.", "font.", or
- "icon.". Properties defined by a Java LookAndFeel don't follow this pattern. To reference a
- property that does not have a standard prefix, an id can be prefixed with "[color]",
+ "icon.". Properties defined by a Java Look and Feel don't follow this pattern. To reference a
+ property that does not have a standard prefix, an ID can be prefixed with "[color]",
"[font]", or "[icon] as appropriate to allow the theme property parser to recognize the
- values as ids to other properties. So to refer to a property named "table.background, it
- would be "color.bg.table = [color]table.background".
+ values as IDs to other properties. So to refer to a Java property named "table.background",
+ you would use the following definition: "color.bg.table = [color]table.background".
size(width,height) - optional modifier to scale the image to the given size.
+
size(width,height): optional modifier to scale the image to the given size.
-
disabled - optional modifier to create a disabled version of the icon.
+
disabled: optional modifier to create a disabled version of the icon.
-
{...} - optional modifier to overlay an icon on the base icon. It is recursively
- defined using the same format.
+
{...}: optional modifier to overlay an icon on the base icon. It is recursively
+ defined using the standard icon format.
-
move(x,y) - optional modifier on overlays to position them relative to the base
+
move(x,y): optional modifier on overlays to position them relative to the base
icon.
@@ -417,22 +439,26 @@ color.fg.listing.bytes = orange
// hammer.icon overlayed in its lower right corner
-
To create an icon suitable for dynamically overlaying other icons, there is special syntax
- for specifying an empty base icon, then overlay another icon in some specific area of the
- empty icon. This icon can then be used to overlay dynamically in the code. For example, to
- create an overlay icon that would add a flag to the bottom, right corner any other iconw:
+
To create stand-alone icon suitable for dynamically overlaying other icons, there is
+ special syntax for specifying an empty base icon. Use the empty icon along with another
+ overlay icon in some specific area of the empty icon to create a final icon that can be used
+ as an overlay for other icons. For example, to
+ create an overlay icon that would add a flag to the bottom-right corner of any other icon:
This document describes the api for initializing and managing themes. A theme (the GTheme
- class) in Ghidra represents a specific LookAndFeel as well the set of values for the color,
- font, and icon resource ids used in the application. The Gui class provides a set of
+
This document describes the API for initializing and managing themes. A theme (the
+ GTheme
+ class) in Ghidra represents a specific Look and Feel as well the set of values for the color,
+ font, and icon resource IDs used in the application. Resource IDs are defined in theme properties
+ files. Application writers refer to these IDs when using colors, fonts and icons.
+ The Gui class provides a set of
static methods that serves as the primary interface for managing all aspects of theming.
-
GTheme class
+
GTheme Class
-
The GTheme class is the implementation of the theme concept. At any giving time, the
- application is using resource values as specified by an active theme. The theme specifies
- the LookAndFeel, whether or not the overall theme is "dark" (which determines which default
+
The GTheme class is the implementation of the theme concept. At any given time,
+ the application is using resource values as specified by the active theme. The theme specifies
+ the Java Look and Feel, whether or not the overall theme is "dark" (which determines which default
values to use) and any resource values which have been overridden specifically by that theme.
- There are two types of of themes; "built-in" themes and file based themes. "Built-in"
- themes are implemented directly as sub-classes of GTheme and simply specify a Java LookAndFeel
+ There are two types of of themes; built-in themes and file-based themes. Built-in
+ themes are implemented directly as sub-classes of GTheme and simply specify a
+ Java Look and Feel
and whether or not the theme is "dark". There is one "built-in" theme for each supported
- LookAndFeel. File based themes read their values from a theme file. Theme files are created by
+ Look and Feel. File-based themes read their values from a theme file. Theme files are created by
editing and saving existing themes.
-
GThemeValueMap / ThemeValue class
+
GThemeValueMap / ThemeValue Classes
-
These are the base classes for storing values for resource ids. A GThemeValueMap
- consists of three hashmaps; one each for colors, fonts, and icons. Each hashmap maps an id to a
- appropriate subclass of ThemeValue, which is the base class for ColorValue, FontValue, and
- IconValue. Resource values are stored in these ThemeValue sub-classes because the value can be
+
These are the base classes for storing values for resource IDs. A GThemeValueMap
+ consists of three maps, one each for colors, fonts, and icons. Each map binds an ID to a
+ appropriate subclass of ThemeValue, which is the base class for
+ ColorValue, FontValue, and
+ IconValue. Resource values are stored in these ThemeValue sub-classes
+ because the value can be
either a concrete value or be a reference to some other resource of the same type. So, for
example, "color.bg.foo" could map directly to an actual color or its value could be reference
- to some other indirect color like "color.bg.bar". In any ThemeValue object, either the
- referenceId or the direct value must be null. To get the ultimate concrete value, there
- is a convenience method called "get" on ThemeValues that takes a GThemeValueMap as an argument.
- This method will recursively resolve referenceIds which is why it needs a value map as an
+ to some other indirect color like "color.bg.bar". In any ThemeValue object, either
+ the referenced ID or the direct value must be null. To get the ultimate concrete value, there
+ is a convenience method called get() on ThemeValues that takes a
+ GThemeValueMap as an argument.
+ This method will recursively resolve reference IDs, which is why it needs a value map as an
argument.
-
GThemeValueMaps have some convenience methods for doing set operations. You can load
- values from other GThemeValueMaps into this map, which adds to the current map, replacing
- values with the same id with values from the other map. Also, there is a method for getting the
- differences from one GThemeValueMap to another.
+
GThemeValueMaps have some convenience methods for performing set operations.
+ You can load
+ values from other GThemeValueMaps into this map, which adds to the current map,
+ replacing values with the same ID with values from the other map. Also, there is a method for
+ getting the differences from one GThemeValueMap to another.
-
Gui class
+
Gui Class
-
The Gui class is a set of static methods that provides the primary API for managing themes.
+
The Gui class is a set of static methods that provides the primary API for
+ managing themes.
It has methods for switching themes, adding themes, deleting themes, saving themes, restoring
- themes, getting/setting values for resource ids, adding theme listeners, and others.
+ themes, getting/setting values for resource IDs, adding theme listeners, and others. This
+ class is meant to be used by application developers, along with GColor for colors
+ and GIcon for icons. Fonts are handled slightly differently by making calls to
+ Gui.registerFont(Component, Id)
+
Application Initialization
-
Applications need to call Gui.initialize() before any uses of color, fonts, or icons occur.
- This will load all resource defaults from the theme.properties files, read the last used theme
- from preferences, and load that theme which includes setting the LookAndFeel.
+
Applications need to call Gui.initialize() before any uses of color, fonts, or
+ icons occur.
+ This will load all resource defaults from all *.theme.properties files, read the
+ last used theme from preferences, and load that theme which includes setting the Look and Feel.
+
Loading a Theme
-
Loading a theme consists of two main operations. Loading the LookAndFeel and building the
- set of values for the resource ids.
+
Loading a theme consists of two main operations: loading the Look and Feel and building the
+ set of values for all defined resource IDs.
-
Loading the LookAndFeel
+
Loading the Look and Feel
-
Because each LookAndFeel present different challenges to the theming feature, there is a
- LookAndFeelManager for each LookAndFeel. The LookAndFeelManager is responsible for installing
- the lookAndFeel (in the case of Nimbus, we had to install a special subclass of the
- NimbusLookAndFeel), extracting the Java resources mappings(Java LookAndFeel objects also
- use a resource id concept), group the java resources into common groups, possibly fix up
- some issues specific to that LookAndFeel, possibly install global properties, and have specific
- update (kicking) techniques to get that LookAndFeel to update its componentUIs when values
- change.
+
Because each Look and Feel presents different challenges to the theming feature, there is a
+ LookandFeelManager for each Look and Feel. The LookandFeelManager is
+ responsible for installing
+ the Look and Feel (in the case of Nimbus, we had to install a special subclass of the
+ NimbusLookandFeel), extracting the Java resources mappings (Java Look and Feel
+ objects also use a resource ID concept), group the Java resources into common groups, possibly
+ fix up some issues specific to that Look and Feel, possibly install global properties, and have
+ specific update techniques to get that Look and Feel to update its component UIs when
+ values change.
Creating the Active Theme Values
-
After the LookAndFeel is loaded and the java values extracted, the final resource mapping is
- created. This is done by loading various resource values sets(each stored in a GThemeValueMap)
- in the correct order into a new GThemeValueMap in GUI called "currentValues" . When
- values are loaded into a GThemeValueMap, they will replace any existing values with the same
- id. The values are loaded in the following order:
+
After the Look and Feel is loaded and the Java values extracted, the final resource mapping is
+ created. This is done by loading various resource values sets (each stored in a GThemeValueMap)
+ in the correct order into a new GThemeValueMap in ThemeManager called
+ "currentValues" . When values are loaded into a GThemeValueMap, they will replace
+ any existing values with the same ID. The values are loaded in the following order:
Whenever the value associated with a resource id changes, the application gets "kicked" in
- various ways to update the display with the new value. The technique used to "kick" the
- application differs depending on the resource type and the LookAndFeel (these differences are
- captured in the LookAndFeelManager sub-classes for each LookAndFeel). It can also vary
- depending on whether the value is an application defined resource or a java defined
+
Whenever the value associated with a resource ID changes, the application gets notified in
+ various ways to update the display with the new value. The technique used to notify the
+ application differs depending on the resource type and the Look and Feel (these differences are
+ captured in the LookandFeelManager sub-classes for each Look and Feel). It can also
+ vary depending on whether the value is an application defined resource or a Java defined
resource.
Updating Colors
-
Updating Colors is the easiest of all the resource. First GColor.refreshAll() is called,
- which causes every GColor to refresh its delegate. Next, repaint() is called on all the top
- level java windows in the application. Also, since color values in the UIDefaults are actually
+
Updating Colors is the easiest of all the resource types. First
+ GColor.refreshAll() is called,
+ which causes every GColor to refresh its internal delegate Color.
+ This is the purpose of using the GColor class, to introduce a level of indirection
+ that allows us to change runtime behavior without having to recompile.
+ Next, repaint() is called on all the top-level Java windows in the application.
+ Also, since color values in the UIDefaults are actually
replaced with GColor objects, this technique works for both application defined resources and
- java defined resources.
-
-
Updating Fonts
-
-
Updating Fonts is a bit more involved. First, if the changed font is java defined, the
- UIDefaults for that font Id (and any that derive from it) are updated. Next, all the components
- that have a registeredFontId are updated, and finally the updateComponentTreeUI method is
- called on all windows in the application.
+ Java defined resources.
Updating Icons
-
Updating Icons is a mixed bag. If the Icon is application defined, GIcon.refreshAll() is
- called which causes every GIcon to refresh its delegate and then call repaint on all the
- windows. If the icon is java defined, then the UIDefaults has to be updated and the
- updateComponentTreeUI method on all windows is called.
+
Updating icons is a mixed bag. If the icon is application defined,
+ GIcon.refreshAll() is
+ called which causes every GIcon to refresh its internal delegate icon and then
+ call repaint() on all the
+ windows. If the icon is Java defined, then the UIDefaults has to be updated and the
+ updateComponentTreeUI() method on all windows is called.
+
+
Updating Fonts
+
+
Updating Fonts is a bit more involved than updating colors and icons, due to the inability
+ to use the indirection model when working with fonts. First, if the changed font is Java
+ defined, the UIDefaults for that font ID (and any that derive from it) are updated.
+ Next, all the components that have called Gui.registeredFont() are updated. (The
+ registration system for fonts is what allows us to notify components of updates, since fonts
+ cannot use the indirection model.)
+ Finally, the updateComponentTreeUI() method is
+ called on all windows in the application.
+
+
Creating/Editing/Saving Themes
-
New themes can be created and saved to files in the theme directory in the users ghidra
- application directory. When the application is started, this directory is scanned and any
- .theme files are loaded and available to be selected as the active theme. The Gui class has
- methods for setting the value of a color, font, or icon for a given resource id. If any values
+
New themes can be created and saved to files in the theme directory in the user's
+ application directory (<home>/.ghidra/.ghidra-<version>/themes).
+ When the application is started, this directory is scanned and any
+ *.theme files are loaded and available to be selected as the active theme.
+ The Gui class has
+ methods for setting the value of a color, font, or icon for a given resource ID. If any values
are currently different from the active theme, the theme can be saved. If the active theme is a
- built-in theme, then the only choice is to save the theme with a new theme name. Saving the
- theme will create a new xxx.theme file where xxx is the name of the theme. Otherwise, the
+ built-in theme, then the only choice is to save using a new theme name. Saving the
+ theme will create a new "xyz.theme" file where "xyz" is the name of the theme. Otherwise, the
existing theme file can be overwritten or a new theme name can be supplied to save to a new
file.
External Icons
-
When settings icons for an icon resource id, the user has the option of using a icon that
- exists on the application classpath or using any supported icon file (.png or .gif) If the user
- chooses to use an icon file, then that icon will be copied into an images directory in their
- application directory (.ghidra). These icons are considered external in that if the theme were
- given to another user, you would also need to give them the icon files.
+
When setting icons for an icon resource ID, the user has the option of using an icon that
+ exists in the application (on the classpath) or using any supported icon file (.png or .gif) on
+ the filesystem. If the user
+ chooses to use a non-application icon file, then that icon will be copied into an images
+ directory in their application directory. These icons are considered external in that if the
+ theme were given to another user, you would also need to give them these icon files, as they
+ will not exist in other application installations.
Importing/Exporting Themes
Themes can be shared with other users by exporting and importing themes. When exporting a
theme that doesn't use any external icons (icons not on the classpath), the theme can be
- exported to a .theme file of the users choosing. If the theme does contain external icons, the
- user has the option to save the theme as a .zip file which would contain both the .theme file
+ exported to a .theme file of the user's choosing. If the theme does contain
+ external icons, the
+ user has the option to save the theme as a .zip file, which would contain both the .theme file
and all the external icon files.
-
LookAndFeel Notes
+
Look and Feel Notes
-
Getting the theming feature to work on all the various Java LookAndFeels is a
- challenge. Java created the concept of UiDefaults, which is a mapping of property names
- to values. The implication is that users can change default values by setting values on the
- UIDefaults. Unfortunately, not all LookAndFeels support this concept. Nimbus and GTK+, in
- particular are problematic. Nimbus sort of honors values in UIDefaults, but only if they are
- installed before Nimbus is loaded. So for out theming purposes, we had to extend the Nimbus
- LookAndFeel in order to override the getDefaults() method (this is the method where
- LookAndFeels populate the UiDefaults) so that we can install any overridden values from the
- selected theme. Also, every time a Java defined property changes, we have to re-install the
- Nimbus LookAndFeel because once it is installed, it no longer pays attention to changes to the
- UIDefaults. The GTK+ LookAndFeel is even more problematic. It gets many of its properties
+
Getting the theming feature to work on all the various Java Look and Feels is a
+ challenge. Java created the concept of UIDefaults, which is a mapping of property
+ names
+ to values. The implication is that users can change Look and Feel settings by changing values
+ in the UIDefaults. Unfortunately, not all Look and Feels support this concept.
+ Nimbus and GTK+, in particular are problematic. Nimbus somewhat honors values in
+ UIDefaults, but only if those values are
+ installed before Nimbus is loaded. So for our theming purposes, we had to extend the Nimbus
+ Look and Feel in order to override the getDefaults() method (this is the method
+ where Look and Feels populate the UIDefaults) so that we can install any overridden
+ values from the selected theme. Also, since Nimbus does not respect changes to these values after
+ they have been created, every time a Java defined property changes, we have to re-install the
+ Nimbus Look and Feel. The GTK+ Look and Feel is even more problematic. It gets many of its
+ properties
from native libraries and there doesn't appear to be anyway of changing them. Therefore, themes
- based on GTK+ doesn't allow for changing java defined values. To compensate for the
- differences among LookAndFeels, we created a LookAndFeelManager base class with sub-classes for
- each LookAndFeel that addresses these differences.
+ based on GTK+ doesn't allow for changing Java defined values. To compensate for the
+ differences among Look and Feels, we created a LookandFeelManager base class with
+ sub-classes for each Look and Feel.
+
+
+
+
+