GP-3000 - Theme Cleanup

This commit is contained in:
dragonmacher 2023-02-09 15:22:54 -05:00
parent f022b9a4d5
commit 1fa08a6002
38 changed files with 324 additions and 177 deletions

View file

@ -26,6 +26,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.Icon;
import javax.swing.JEditorPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
@ -35,6 +36,7 @@ import javax.swing.text.html.HTML.Tag;
import generic.jar.ResourceFile;
import generic.theme.*;
import generic.theme.GThemeDefaults.Colors;
import ghidra.framework.Application;
import ghidra.framework.preferences.Preferences;
import ghidra.util.Msg;
@ -43,11 +45,11 @@ import utilities.util.FileUtilities;
/**
* A class that allows Ghidra to intercept JavaHelp navigation events in order to resolve them
* to Ghidra's help system. Without this class, contribution plugins have no way of
* to Ghidra's help system. Without this class, contribution plugins have no way of
* referencing help documents within Ghidra's default help location.
* <p>
* This class is currently installed by the {@link GHelpSet}.
*
*
* @see GHelpSet
*/
public class GHelpHTMLEditorKit extends HTMLEditorKit {
@ -73,8 +75,7 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
colorsById.put("h3", new GColor("color.fg.help.selector.h3"));
colorsById.put("p.providedbyplugin",
new GColor("color.fg.help.selector.p.provided.by.plugin"));
colorsById.put("p.relatedtopic",
new GColor("color.fg.help.selector.p.related.topic"));
colorsById.put("p.relatedtopic", new GColor("color.fg.help.selector.p.related.topic"));
colorsById.put("th", new GColor("color.fg.help.selector.th"));
colorsById.put("code", new GColor("color.fg.help.selector.code"));
colorsById.put("code.path", new GColor("color.fg.help.selector.code.path"));
@ -176,9 +177,9 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
}
}
/**
/**
* Tests the URL of the given event. If the URL is invalid, a new event may be created if
* a new, valid URL can be created. Creates a new event with a patched URL if
* a new, valid URL can be created. Creates a new event with a patched URL if
* the given event's URL is invalid.
*/
private HyperlinkEvent validateURL(HyperlinkEvent event) {
@ -235,10 +236,10 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
}
//
// The item was not found by the ResourceManager (i.e., it is not in a 'resources'
// The item was not found by the ResourceManager (i.e., it is not in a 'resources'
// directory). See if it may be a relative link to a build's installation root (like
// a file in <install dir>/docs).
//
//
newUrl = findApplicationfile(HREF);
return newUrl;
}
@ -254,7 +255,7 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
}
try {
// put the anchor back into the URL
// put the anchor back into the URL
return new URL(anchorlessURL, anchor);
}
catch (MalformedURLException e) {
@ -438,7 +439,7 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
//==================================================================================================
// Inner Classes
//==================================================================================================
//==================================================================================================
private class GHelpHTMLFactory extends HTMLFactory {
@Override
@ -465,31 +466,36 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
}
/**
* Overridden to allow us to find images that are defined as constants in places like
* Overridden to allow us to find images that are defined as constants in places like
* {@link Icons}
*/
private class GHelpImageView extends ImageView {
private static final String HELP_SHARED_ARROW = "help/shared/arrow.gif";
private static final Icon SHARED_ARROW_ICON = new HelpRightArrowIcon(Colors.FOREGROUND);
private static final IconProvider SHARED_ARROW_ICON_PROVIDER =
new IconProvider(SHARED_ARROW_ICON, null);
/*
* Unusual Code Alert!
* This class exists to enable our help system to find custom icons defined in source
* code. The default behavior herein is to supply a URL to the base class to load. This
* works fine.
*
* works fine.
*
* There is another use case where we wish to have the base class load an image of our
* choosing. Why? Well, we modify, in memory, some icons we use. We do this for things
* like overlays and rotations.
*
*
* In order to have our base class use the image that we want (and not the one
* it loads via a URL), we have to play a small game. We have to allow the base class
* to load the image it wants, which is done asynchronously. If we install our custom
* image during that process, the loading will throw away the image and not render
* anything.
*
* To get the base class to use our image, we override getImage(). However, we should
* anything.
*
* To get the base class to use our image, we override getImage(). However, we should
* only return our image when the base class is finished loading. (See the base class'
* paint() method for why we need to do this.)
*
*
* Note: if we start seeing unusual behavior, like images not rendering, or any size
* issues, then we can revert this code.
*/
@ -541,12 +547,22 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
return null;
}
String srcString = src.toString();
//
// This code is looking for the specific referenced image file and then replacing that
// image file with something that can update its content at runtime, based on theme.
// Alternatively, we could have updated all help files to point to a GIcon, which
// handles updating itself when the theme changes. We chose to replace the icon here
// instead of in the source code to prevent changing many files.
//
String srcString = src.toString().trim();
if (srcString.equals(HELP_SHARED_ARROW)) {
return installImageFromCustomIcon(SHARED_ARROW_ICON_PROVIDER);
}
// check if the srcString is a defined theme icon id
if (Gui.hasIcon(srcString)) {
//
// Wrap the GIcon inside of an IconProvider, as that class can handle a null URL
//
// Wrap the GIcon inside of an IconProvider, as that class can handle a null URL
// returned from GIcon. (This can happen if the GIcon is based on a modified icon.)
//
GIcon gIcon = new GIcon(srcString);
@ -562,6 +578,19 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
return url;
}
private URL installImageFromCustomIcon(IconProvider iconProvider) {
if (iconProvider == null || iconProvider.isInvalid()) {
return null;
}
this.image = iconProvider.getImage();
// note: this icon is not used to load the image; the 'image' we set is used instead
URL url = iconProvider.getOrCreateUrl();
return url;
}
private URL installImageFromJavaCode(String srcString) {
IconProvider iconProvider = getIconFromJavaCode(srcString);
@ -590,7 +619,7 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
// check below
}
// Try the ResourceManager. This will work for images that start with GHelp
// Try the ResourceManager. This will work for images that start with GHelp
// relative link syntax such as 'help/', 'help/topics/' and 'images/'
URL resource = ResourceManager.getResource(srcString);
return resource;

View file

@ -0,0 +1,154 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package help;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.Icon;
/**
* A basic arrow that points to the right, with padding on the sides and above.
*/
public class HelpRightArrowIcon implements Icon {
private static final int ICON_SIZE = 20;
private Color color;
private Shape shape;
public HelpRightArrowIcon(Color color) {
this.color = color;
this.shape = buildShape();
}
private Shape buildShape() {
GeneralPath barPath = new GeneralPath();
//
// Construct the arrow in 2 parts: the line and the angle bracket. The arrow will not fill
// the full area. This allows space before and after the arrow. This space serves as
// padding between text inside of html content. The arrow is also closer to the bottom,
// to aligned vertically with text.
//
double height = 10;
double width = 12;
double thickness = 2;
double arrowthickness = 3;
double top = ICON_SIZE - height;
double cy = top + (height / 2);
double p1x = (ICON_SIZE - width) / 2;
double p1y = cy - (thickness / 2);
barPath.moveTo(p1x, p1y);
double barlength = width - 2;
double p2x = p1x + barlength;
double p2y = p1y;
barPath.lineTo(p2x, p2y);
double p3x = p2x;
double p3y = p2y + thickness;
barPath.lineTo(p3x, p3y);
double p4x = p1x;
double p4y = p3y;
barPath.lineTo(p4x, p4y);
// back to start of arrow line
barPath.lineTo(p1x, p1y);
barPath.closePath();
GeneralPath arrowPath = new GeneralPath();
// trailing arrow bar center
p1x = p1x + barlength + arrowthickness;
p1y = cy;
arrowPath.moveTo(p1x, p1y);
// trailing upper arrow bar point
double trianglewidth = 5;
p2x = p1x - trianglewidth;
p2y = top + 1;
arrowPath.lineTo(p2x, p2y);
// leading upper arrow bar point
p3x = p2x - arrowthickness;
p3y = p2y;
arrowPath.lineTo(p3x, p3y);
// leading arrow bar center
p4x = p1x - arrowthickness;
p4y = cy;
arrowPath.lineTo(p4x, p4y);
// leading lower arrow bar point
double p5x = p3x;
double p5y = ICON_SIZE - 1;
arrowPath.lineTo(p5x, p5y);
// trailing lower arrow bar point
double p6x = p2x;
double p6y = p5y;
arrowPath.lineTo(p6x, p6y);
// back to start
double p7x = p1x;
double p7y = p1y;
arrowPath.lineTo(p7x, p7y);
arrowPath.closePath();
AffineTransform identity = new AffineTransform();
Shape barShape = barPath.createTransformedShape(identity);
Area barArea = new Area(barShape);
Shape arrowShape = arrowPath.createTransformedShape(identity);
Area arrowArea = new Area(arrowShape);
Area fullArea = new Area();
fullArea.add(barArea);
fullArea.add(arrowArea);
return fullArea;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
try {
g2d.translate(x, y);
g2d.setColor(color);
g2d.fill(shape);
}
finally {
g2d.translate(-x, -y);
}
}
@Override
public int getIconWidth() {
return ICON_SIZE;
}
@Override
public int getIconHeight() {
return ICON_SIZE;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 B