mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch 'origin/GP-41_dev747368_multiiconbuilder'
This commit is contained in:
@@ -15,6 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package resources;
|
package resources;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.font.FontRenderContext;
|
||||||
|
import java.awt.font.TextLayout;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
@@ -24,13 +28,12 @@ import resources.icons.TranslateIcon;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder to allow for easier creation of an icon that is composed of a base icon, with
|
* A builder to allow for easier creation of an icon that is composed of a base icon, with
|
||||||
* other icons overlayed. The {@link #build()} method returns an {@link ImageIcon}, as this
|
* other icons overlaid. The {@link #build()} method returns an {@link ImageIcon}, as this
|
||||||
* allows Java's buttons to create analogue disabled icons correctly.
|
* allows Java's buttons to automatically create disabled icons correctly.
|
||||||
*
|
*
|
||||||
* <P>Note: this class is a work-in-progress. Add more methods for locating overlays as needed.
|
* <P>Note: this class is a work-in-progress. Add more methods for locating overlays as needed.
|
||||||
*/
|
*/
|
||||||
public class MultiIconBuilder {
|
public class MultiIconBuilder {
|
||||||
|
|
||||||
private MultiIcon multiIcon;
|
private MultiIcon multiIcon;
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@@ -38,6 +41,28 @@ public class MultiIconBuilder {
|
|||||||
this.multiIcon = new MultiIcon(Objects.requireNonNull(baseIcon));
|
this.multiIcon = new MultiIcon(Objects.requireNonNull(baseIcon));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified icon as an overlay to the base icon, possibly scaled according
|
||||||
|
* to the specified width and height, in the specified quadrant corner.
|
||||||
|
*
|
||||||
|
* @param icon the icon to overlay
|
||||||
|
* @param w width of the overlaid icon
|
||||||
|
* @param h height of the overlaid icon
|
||||||
|
* @param quandrant corner to place the overlay on
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public MultiIconBuilder addIcon(Icon icon, int w, int h, QUADRANT quandrant) {
|
||||||
|
ImageIcon scaled = ResourceManager.getScaledIcon(icon, w, h);
|
||||||
|
|
||||||
|
int x = (multiIcon.getIconWidth() - scaled.getIconWidth()) * quandrant.x;
|
||||||
|
int y = (multiIcon.getIconHeight() - scaled.getIconHeight()) * quandrant.y;
|
||||||
|
|
||||||
|
TranslateIcon txIcon = new TranslateIcon(scaled, x, y);
|
||||||
|
multiIcon.addIcon(txIcon);
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given icon as an overlay to the base icon, to the lower-right
|
* Adds the given icon as an overlay to the base icon, to the lower-right
|
||||||
*
|
*
|
||||||
@@ -45,7 +70,7 @@ public class MultiIconBuilder {
|
|||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
public MultiIconBuilder addLowerRightIcon(Icon icon) {
|
public MultiIconBuilder addLowerRightIcon(Icon icon) {
|
||||||
return addLowerRightIcon(icon, icon.getIconWidth(), icon.getIconHeight());
|
return addIcon(icon, icon.getIconWidth(), icon.getIconHeight(), QUADRANT.LR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,14 +83,7 @@ public class MultiIconBuilder {
|
|||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
public MultiIconBuilder addLowerRightIcon(Icon icon, int w, int h) {
|
public MultiIconBuilder addLowerRightIcon(Icon icon, int w, int h) {
|
||||||
|
return addIcon(icon, w, h, QUADRANT.LR);
|
||||||
ImageIcon scaled = ResourceManager.getScaledIcon(icon, w, h);
|
|
||||||
|
|
||||||
int x = multiIcon.getIconWidth() - scaled.getIconWidth();
|
|
||||||
int y = multiIcon.getIconHeight() - scaled.getIconHeight();
|
|
||||||
TranslateIcon txIcon = new TranslateIcon(scaled, x, y);
|
|
||||||
multiIcon.addIcon(txIcon);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,7 +93,7 @@ public class MultiIconBuilder {
|
|||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
public MultiIconBuilder addLowerLeftIcon(Icon icon) {
|
public MultiIconBuilder addLowerLeftIcon(Icon icon) {
|
||||||
return addLowerLeftIcon(icon, icon.getIconWidth(), icon.getIconHeight());
|
return addIcon(icon, icon.getIconWidth(), icon.getIconHeight(), QUADRANT.LL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,14 +106,34 @@ public class MultiIconBuilder {
|
|||||||
* @return this builder
|
* @return this builder
|
||||||
*/
|
*/
|
||||||
public MultiIconBuilder addLowerLeftIcon(Icon icon, int w, int h) {
|
public MultiIconBuilder addLowerLeftIcon(Icon icon, int w, int h) {
|
||||||
|
return addIcon(icon, w, h, QUADRANT.LL);
|
||||||
|
}
|
||||||
|
|
||||||
ImageIcon scaled = ResourceManager.getScaledIcon(icon, w, h);
|
/**
|
||||||
|
* Add text overlaid on the base icon, aligned to the specified quadrant.
|
||||||
|
*
|
||||||
|
* @param text Text string to write onto the icon. Probably can only fit a letter or two
|
||||||
|
* @param font The font to use to render the text. You know the size of the base icon, so
|
||||||
|
* you should be able to figure out the size of the font to use for the text
|
||||||
|
* @param color The color to use when rendering the text
|
||||||
|
* @param quandrant The {@link QUADRANT} to align the text to different parts of the icon
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public MultiIconBuilder addText(String text, Font font, Color color, QUADRANT quandrant) {
|
||||||
|
|
||||||
int x = 0;
|
FontRenderContext frc = new FontRenderContext(null, true, true);
|
||||||
int y = multiIcon.getIconHeight() - scaled.getIconHeight();
|
TextLayout tl = new TextLayout(text, font, frc);
|
||||||
TranslateIcon txIcon = new TranslateIcon(scaled, x, y);
|
|
||||||
multiIcon.addIcon(txIcon);
|
BufferedImage bi = new BufferedImage((int) Math.ceil(tl.getAdvance()),
|
||||||
return this;
|
(int) Math.ceil(tl.getAscent() + tl.getDescent()), BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
|
Graphics2D g2d = (Graphics2D) bi.getGraphics();
|
||||||
|
g2d.setFont(font);
|
||||||
|
g2d.setColor(color);
|
||||||
|
tl.draw(g2d, 0, tl.getAscent());
|
||||||
|
g2d.dispose();
|
||||||
|
|
||||||
|
return addIcon(new ImageIcon(bi), bi.getWidth(), bi.getHeight(), quandrant);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/* ###
|
||||||
|
* 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 resources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum specifying the quadrant of an overlay, either upper left, upper right, lower left, lower right.
|
||||||
|
*/
|
||||||
|
public enum QUADRANT {
|
||||||
|
UL(0, 0), UR(1, 0), LL(0, 1), LR(1, 1);
|
||||||
|
|
||||||
|
QUADRANT(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String to enum.
|
||||||
|
*
|
||||||
|
* @param s string of either "UL", "UR", "LL", "LR"
|
||||||
|
* @param defaultValue value to return if string is invalid
|
||||||
|
* @return QUADRANT enum
|
||||||
|
*/
|
||||||
|
public static QUADRANT valueOf(String s, QUADRANT defaultValue) {
|
||||||
|
if (s != null) {
|
||||||
|
try {
|
||||||
|
return QUADRANT.valueOf(s.toUpperCase());
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException iae) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/* ###
|
||||||
|
* 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 resources.icons;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import resources.MultiIconBuilder;
|
||||||
|
import resources.QUADRANT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal tests for MultiIconBuilder. Doesn't test the produced images, just that it didn't cause an exception.
|
||||||
|
* <p>
|
||||||
|
* The showXYZ() methods are present so a human can run them as a test and see the output
|
||||||
|
*/
|
||||||
|
public class MultiIconBuilderTest {
|
||||||
|
|
||||||
|
private ImageIcon makeEmptyIcon(int w, int h, Color color) {
|
||||||
|
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
if (color != null) {
|
||||||
|
Graphics g = bi.getGraphics();
|
||||||
|
g.setColor(color);
|
||||||
|
g.fillRect(0, 0, w, h);
|
||||||
|
g.dispose();
|
||||||
|
}
|
||||||
|
return new ImageIcon(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageIcon makeQuandrantIcon(int w, int h, Color bgColor, Color lineColor) {
|
||||||
|
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
Graphics g = bi.getGraphics();
|
||||||
|
g.setColor(bgColor);
|
||||||
|
g.fillRect(0, 0, w, h);
|
||||||
|
g.setColor(lineColor);
|
||||||
|
g.drawLine(w / 2, 0, w / 2, h);
|
||||||
|
g.drawLine(0, h / 2, w, h / 2);
|
||||||
|
g.dispose();
|
||||||
|
return new ImageIcon(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Font font = new Font("Monospaced", Font.PLAIN, 12);
|
||||||
|
|
||||||
|
//@Test
|
||||||
|
public void showIconText() {
|
||||||
|
for (QUADRANT quad : QUADRANT.values()) {
|
||||||
|
ImageIcon icon =
|
||||||
|
new MultiIconBuilder(makeQuandrantIcon(32, 32, Color.gray, Color.white))
|
||||||
|
.addText("Abcfg", font, Color.red, quad)
|
||||||
|
.build();
|
||||||
|
JOptionPane.showMessageDialog(null, "" + quad + " aligned", "Icon text overlay test",
|
||||||
|
JOptionPane.OK_OPTION, icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Test
|
||||||
|
public void showIconOverlay() {
|
||||||
|
for (QUADRANT quad : QUADRANT.values()) {
|
||||||
|
ImageIcon icon = new MultiIconBuilder(makeEmptyIcon(32, 32, Color.gray))
|
||||||
|
.addIcon(makeEmptyIcon(8, 8, Color.red), 8, 8, quad)
|
||||||
|
.build();
|
||||||
|
JOptionPane.showMessageDialog(null, "" + quad + " aligned", "Icon_icon overlay test",
|
||||||
|
JOptionPane.OK_OPTION, icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Test
|
||||||
|
public void showScaledIconOverlay() {
|
||||||
|
for (QUADRANT quad : QUADRANT.values()) {
|
||||||
|
ImageIcon icon = new MultiIconBuilder(makeEmptyIcon(32, 32, Color.gray))
|
||||||
|
.addIcon(makeQuandrantIcon(32, 32, Color.red, Color.black), 14, 14, quad)
|
||||||
|
.build();
|
||||||
|
JOptionPane.showMessageDialog(null, "" + quad + " aligned",
|
||||||
|
"Scaled icon_icon overlay test",
|
||||||
|
JOptionPane.OK_OPTION, icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIconOverlay() {
|
||||||
|
// doesn't verify anything other than it doesn't fall down go boom
|
||||||
|
for (QUADRANT quad : QUADRANT.values()) {
|
||||||
|
ImageIcon icon = new MultiIconBuilder(makeEmptyIcon(32, 32, Color.gray))
|
||||||
|
.addIcon(makeQuandrantIcon(32, 32, Color.red, Color.black), 14, 14, quad)
|
||||||
|
.build();
|
||||||
|
icon.getDescription();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIconText() {
|
||||||
|
// doesn't verify anything other than it doesn't fall down go boom
|
||||||
|
for (QUADRANT quad : QUADRANT.values()) {
|
||||||
|
ImageIcon icon =
|
||||||
|
new MultiIconBuilder(makeQuandrantIcon(32, 32, Color.gray, Color.white))
|
||||||
|
.addText("Abcfg", font, Color.red, quad)
|
||||||
|
.build();
|
||||||
|
icon.getDescription();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user