Merge remote-tracking branch 'origin/GP-41_dev747368_multiiconbuilder'

This commit is contained in:
ghidravore 2020-08-05 12:42:26 -04:00
commit 2c3ceb59d1
3 changed files with 224 additions and 19 deletions

View file

@ -15,6 +15,10 @@
*/
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 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
* other icons overlayed. The {@link #build()} method returns an {@link ImageIcon}, as this
* allows Java's buttons to create analogue disabled icons correctly.
* other icons overlaid. The {@link #build()} method returns an {@link ImageIcon}, as this
* 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.
*/
public class MultiIconBuilder {
private MultiIcon multiIcon;
private String description;
@ -38,6 +41,28 @@ public class MultiIconBuilder {
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
*
@ -45,7 +70,7 @@ public class MultiIconBuilder {
* @return this builder
*/
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
*/
public MultiIconBuilder addLowerRightIcon(Icon icon, int w, int h) {
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;
return addIcon(icon, w, h, QUADRANT.LR);
}
/**
@ -75,7 +93,7 @@ public class MultiIconBuilder {
* @return this builder
*/
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
*/
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;
int y = multiIcon.getIconHeight() - scaled.getIconHeight();
TranslateIcon txIcon = new TranslateIcon(scaled, x, y);
multiIcon.addIcon(txIcon);
return this;
FontRenderContext frc = new FontRenderContext(null, true, true);
TextLayout tl = new TextLayout(text, font, frc);
BufferedImage bi = new BufferedImage((int) Math.ceil(tl.getAdvance()),
(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);
}
/**

View file

@ -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;
}
}

View file

@ -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();
}
}
}