Merge pull request #3294 from deathbeam/infobox-smaller

Add support for configurable infobox sizes
This commit is contained in:
Adam
2018-06-12 20:04:10 -04:00
committed by GitHub
15 changed files with 279 additions and 164 deletions

View File

@@ -56,6 +56,7 @@ import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.DrawManager;
import net.runelite.client.ui.TitleToolbar; import net.runelite.client.ui.TitleToolbar;
import net.runelite.client.ui.overlay.OverlayRenderer; import net.runelite.client.ui.overlay.OverlayRenderer;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.slf4j.MDC; import org.slf4j.MDC;
@@ -120,6 +121,9 @@ public class RuneLite
@Inject @Inject
private ClanManager clanManager; private ClanManager clanManager;
@Inject
private InfoBoxManager infoBoxManager;
Client client; Client client;
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
@@ -214,6 +218,7 @@ public class RuneLite
eventBus.register(commandManager); eventBus.register(commandManager);
eventBus.register(pluginManager); eventBus.register(pluginManager);
eventBus.register(clanManager); eventBus.register(clanManager);
eventBus.register(infoBoxManager);
if (this.client != null) if (this.client != null)
{ {

View File

@@ -221,4 +221,15 @@ public interface RuneLiteConfig extends Config
{ {
return 4; return 4;
} }
@ConfigItem(
keyName = "infoBoxSize",
name = "Infobox size (px)",
description = "Configures the size of each infobox in pixels",
position = 34
)
default int infoBoxSize()
{
return 35;
}
} }

View File

@@ -24,9 +24,7 @@
*/ */
package net.runelite.client.plugins.prayer; package net.runelite.client.plugins.prayer;
import java.awt.image.BufferedImage;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.Counter; import net.runelite.client.ui.overlay.infobox.Counter;
@@ -35,9 +33,6 @@ public class PrayerCounter extends Counter
@Getter @Getter
private final PrayerType prayerType; private final PrayerType prayerType;
@Setter
private BufferedImage image;
PrayerCounter(Plugin plugin, PrayerType prayerType) PrayerCounter(Plugin plugin, PrayerType prayerType)
{ {
super(null, plugin, ""); super(null, plugin, "");
@@ -55,10 +50,4 @@ public class PrayerCounter extends Counter
{ {
return prayerType.getDescription(); return prayerType.getDescription();
} }
@Override
public BufferedImage getImage()
{
return image;
}
} }

View File

@@ -27,6 +27,7 @@ package net.runelite.client.plugins.screenmarkers;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke; import java.awt.Stroke;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@@ -36,6 +37,10 @@ import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
public class ScreenMarkerRenderable implements LayoutableRenderableEntity public class ScreenMarkerRenderable implements LayoutableRenderableEntity
{ {
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
@Setter
private Point preferredLocation;
@Getter(AccessLevel.PACKAGE)
@Setter
private Dimension preferredSize; private Dimension preferredSize;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE) @Setter(AccessLevel.PACKAGE)
@@ -69,10 +74,4 @@ public class ScreenMarkerRenderable implements LayoutableRenderableEntity
graphics.drawRect(offset, offset, width - thickness, height - thickness); graphics.drawRect(offset, offset, width - thickness, height - thickness);
return preferredSize; return preferredSize;
} }
@Override
public void setPreferredSize(Dimension preferredSize)
{
this.preferredSize = preferredSize;
}
} }

View File

@@ -231,7 +231,7 @@ public class XpGlobesOverlay extends Overlay
String skillCurrentXp = decimalFormat.format(mouseOverSkill.getCurrentXp()); String skillCurrentXp = decimalFormat.format(mouseOverSkill.getCurrentXp());
xpTooltip.getChildren().clear(); xpTooltip.getChildren().clear();
graphics.translate(x, y); xpTooltip.setPreferredLocation(new java.awt.Point(x, y));
xpTooltip.setPreferredSize(new Dimension(TOOLTIP_RECT_SIZE_X, 0)); xpTooltip.setPreferredSize(new Dimension(TOOLTIP_RECT_SIZE_X, 0));
xpTooltip.getChildren().add(LineComponent.builder() xpTooltip.getChildren().add(LineComponent.builder()
@@ -286,6 +286,5 @@ public class XpGlobesOverlay extends Overlay
} }
xpTooltip.render(graphics); xpTooltip.render(graphics);
graphics.translate(-x, -y);
} }
} }

View File

@@ -26,15 +26,17 @@ package net.runelite.client.ui.overlay.components;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
@AllArgsConstructor @RequiredArgsConstructor
@Setter @Setter
public class ImageComponent implements LayoutableRenderableEntity public class ImageComponent implements LayoutableRenderableEntity
{ {
private BufferedImage image; private final BufferedImage image;
private Point preferredLocation = new Point();
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
@@ -44,7 +46,7 @@ public class ImageComponent implements LayoutableRenderableEntity
return null; return null;
} }
graphics.drawImage(image, 0, -graphics.getFontMetrics().getHeight(), null); graphics.drawImage(image, preferredLocation.x, preferredLocation.y, null);
return new Dimension(image.getWidth(), image.getHeight()); return new Dimension(image.getWidth(), image.getHeight());
} }

View File

@@ -28,49 +28,80 @@ import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FontMetrics; import java.awt.FontMetrics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.image.BufferedImage; import lombok.Getter;
import java.util.Objects;
import lombok.Setter; import lombok.Setter;
import net.runelite.client.ui.overlay.RenderableEntity; import net.runelite.client.ui.FontManager;
@Setter @Setter
public class InfoBoxComponent implements RenderableEntity public class InfoBoxComponent implements LayoutableRenderableEntity
{ {
private static final int BOX_SIZE = 35; private static final int SEPARATOR = 3;
private static final int SEPARATOR = 2; private static final int DEFAULT_SIZE = 32;
@Getter
private String tooltip;
@Getter
private Point preferredLocation = new Point();
@Setter
private Dimension preferredSize = new Dimension(DEFAULT_SIZE, DEFAULT_SIZE);
private String text; private String text;
private Color color = Color.WHITE; private Color color = Color.WHITE;
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
private Point position = new Point(); private Image image;
private BufferedImage image;
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
if (image == null)
{
return new Dimension();
}
graphics.setFont(getSize() < DEFAULT_SIZE ? FontManager.getRunescapeSmallFont() : FontManager.getRunescapeFont());
graphics.translate(preferredLocation.x, preferredLocation.y);
// Calculate dimensions
final FontMetrics metrics = graphics.getFontMetrics(); final FontMetrics metrics = graphics.getFontMetrics();
final Rectangle bounds = new Rectangle(position.x, position.y, BOX_SIZE, BOX_SIZE); final int size = getSize();
final Rectangle bounds = new Rectangle(size, size);
// Render background
final BackgroundComponent backgroundComponent = new BackgroundComponent(); final BackgroundComponent backgroundComponent = new BackgroundComponent();
backgroundComponent.setBackgroundColor(backgroundColor); backgroundComponent.setBackgroundColor(backgroundColor);
backgroundComponent.setRectangle(bounds); backgroundComponent.setRectangle(bounds);
backgroundComponent.render(graphics); backgroundComponent.render(graphics);
if (Objects.nonNull(image)) // Render image
{ graphics.drawImage(
graphics.drawImage(image, image,
position.x + (BOX_SIZE - image.getWidth()) / 2, (size - image.getWidth(null)) / 2,
position.y + (BOX_SIZE - image.getHeight()) / 2, null); (size - image.getHeight(null)) / 2,
} null);
// Render caption
final TextComponent textComponent = new TextComponent(); final TextComponent textComponent = new TextComponent();
textComponent.setColor(color); textComponent.setColor(color);
textComponent.setText(text); textComponent.setText(text);
textComponent.setPosition(new Point( textComponent.setPosition(new Point(((size - metrics.stringWidth(text)) / 2), size - SEPARATOR));
position.x + ((BOX_SIZE - metrics.stringWidth(text)) / 2),
position.y + BOX_SIZE - SEPARATOR));
textComponent.render(graphics); textComponent.render(graphics);
return new Dimension(BOX_SIZE, BOX_SIZE);
graphics.translate(-preferredLocation.x, -preferredLocation.y);
return bounds.getSize();
}
public Dimension getPreferredSize()
{
return new Dimension(getSize(), getSize());
}
private int getSize()
{
return Math.max(preferredSize.width, preferredSize.height);
} }
} }

View File

@@ -25,9 +25,11 @@
package net.runelite.client.ui.overlay.components; package net.runelite.client.ui.overlay.components;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Point;
import net.runelite.client.ui.overlay.RenderableEntity; import net.runelite.client.ui.overlay.RenderableEntity;
public interface LayoutableRenderableEntity extends RenderableEntity public interface LayoutableRenderableEntity extends RenderableEntity
{ {
void setPreferredLocation(Point position);
void setPreferredSize(Dimension dimension); void setPreferredSize(Dimension dimension);
} }

View File

@@ -47,19 +47,23 @@ public class LineComponent implements LayoutableRenderableEntity
@Builder.Default @Builder.Default
private Color rightColor = Color.WHITE; private Color rightColor = Color.WHITE;
@Builder.Default
private Point preferredLocation = new Point();
@Builder.Default @Builder.Default
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0);
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
graphics.translate(preferredLocation.x, preferredLocation.y);
// Prevent NPEs // Prevent NPEs
final String left = MoreObjects.firstNonNull(this.left, ""); final String left = MoreObjects.firstNonNull(this.left, "");
final String right = MoreObjects.firstNonNull(this.right, ""); final String right = MoreObjects.firstNonNull(this.right, "");
final FontMetrics metrics = graphics.getFontMetrics(); final FontMetrics metrics = graphics.getFontMetrics();
int x = 0; int x = 0;
int y = 0; int y = metrics.getHeight();
final int leftFullWidth = getLineWidth(left, metrics); final int leftFullWidth = getLineWidth(left, metrics);
final int rightFullWidth = getLineWidth(right, metrics); final int rightFullWidth = getLineWidth(right, metrics);
@@ -108,7 +112,8 @@ public class LineComponent implements LayoutableRenderableEntity
y += metrics.getHeight(); y += metrics.getHeight();
} }
return new Dimension(preferredSize.width, y); graphics.translate(-preferredLocation.x, -preferredLocation.y);
return new Dimension(preferredSize.width, y - metrics.getHeight());
} }
final TextComponent leftLineComponent = new TextComponent(); final TextComponent leftLineComponent = new TextComponent();
@@ -124,7 +129,8 @@ public class LineComponent implements LayoutableRenderableEntity
rightLineComponent.render(graphics); rightLineComponent.render(graphics);
y += metrics.getHeight(); y += metrics.getHeight();
return new Dimension(preferredSize.width, y); graphics.translate(-preferredLocation.x, -preferredLocation.y);
return new Dimension(preferredSize.width, y - metrics.getHeight());
} }
private static int getLineWidth(final String line, final FontMetrics metrics) private static int getLineWidth(final String line, final FontMetrics metrics)

View File

@@ -26,12 +26,12 @@ package net.runelite.client.ui.overlay.components;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -44,8 +44,12 @@ public class PanelComponent implements LayoutableRenderableEntity
} }
@Setter @Setter
@Nullable
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR; private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
@Setter
private Point preferredLocation = new Point();
@Setter @Setter
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0);
@@ -55,6 +59,9 @@ public class PanelComponent implements LayoutableRenderableEntity
@Setter @Setter
private Orientation orientation = Orientation.VERTICAL; private Orientation orientation = Orientation.VERTICAL;
@Setter
private int wrapping = -1;
@Setter @Setter
private Rectangle border = new Rectangle( private Rectangle border = new Rectangle(
ComponentConstants.STANDARD_BORDER, ComponentConstants.STANDARD_BORDER,
@@ -75,21 +82,25 @@ public class PanelComponent implements LayoutableRenderableEntity
return null; return null;
} }
final FontMetrics metrics = graphics.getFontMetrics(); graphics.translate(preferredLocation.x, preferredLocation.y);
// Render background // Calculate panel dimension
final Dimension dimension = new Dimension( final Dimension dimension = new Dimension(
border.x + childDimensions.width + border.width, border.x + childDimensions.width + border.width,
border.y + childDimensions.height + border.height); border.y + childDimensions.height + border.height);
final BackgroundComponent backgroundComponent = new BackgroundComponent(); // Render background
backgroundComponent.setRectangle(new Rectangle(dimension)); if (backgroundColor != null)
backgroundComponent.setBackgroundColor(backgroundColor); {
backgroundComponent.render(graphics); final BackgroundComponent backgroundComponent = new BackgroundComponent();
backgroundComponent.setRectangle(new Rectangle(dimension));
backgroundComponent.setBackgroundColor(backgroundColor);
backgroundComponent.render(graphics);
}
// Offset children // Offset children
final int baseX = border.x; final int baseX = border.x;
final int baseY = border.y + metrics.getHeight(); final int baseY = border.y;
int width = 0; int width = 0;
int height = 0; int height = 0;
int x = baseX; int x = baseX;
@@ -100,13 +111,17 @@ public class PanelComponent implements LayoutableRenderableEntity
preferredSize.width - border.x - border.width, preferredSize.width - border.x - border.width,
preferredSize.height - border.y - border.height); preferredSize.height - border.y - border.height);
// Calculate max width/height for infoboxes
int totalHeight = 0;
int totalWidth = 0;
// Render all children // Render all children
for (final LayoutableRenderableEntity child : children) for (int i = 0; i < children.size(); i ++)
{ {
final LayoutableRenderableEntity child = children.get(i);
child.setPreferredLocation(new Point(x, y));
child.setPreferredSize(childPreferredSize); child.setPreferredSize(childPreferredSize);
graphics.translate(x, y);
final Dimension childDimension = child.render(graphics); final Dimension childDimension = child.render(graphics);
graphics.translate(-x, -y);
switch (orientation) switch (orientation)
{ {
@@ -121,15 +136,45 @@ public class PanelComponent implements LayoutableRenderableEntity
height = Math.max(height, childDimension.height); height = Math.max(height, childDimension.height);
break; break;
} }
// Calculate total size
totalWidth = Math.max(totalWidth, width);
totalHeight = Math.max(totalHeight, height);
if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0)
{
switch (orientation)
{
case VERTICAL:
{
height = 0;
y = baseY;
int diff = childDimension.width + gap.x;
x += diff;
width += diff;
break;
}
case HORIZONTAL:
{
width = 0;
x = baseX;
int diff = childDimension.height + gap.y;
y += diff;
height += diff;
break;
}
}
}
} }
// Remove last child gap // Remove last child gap
width -= gap.x; totalWidth -= gap.x;
height -= gap.y; totalHeight -= gap.y;
// Cache children bounds // Cache children bounds
childDimensions.setSize(width, height); childDimensions.setSize(totalWidth, totalHeight);
graphics.translate(-preferredLocation.x, -preferredLocation.y);
return dimension; return dimension;
} }
} }

View File

@@ -50,15 +50,17 @@ public class ProgressBarComponent implements LayoutableRenderableEntity
private Color foregroundColor = new Color(82, 161, 82); private Color foregroundColor = new Color(82, 161, 82);
private Color backgroundColor = new Color(255, 255, 255, 127); private Color backgroundColor = new Color(255, 255, 255, 127);
private Color fontColor = Color.WHITE; private Color fontColor = Color.WHITE;
private Point preferredLocation = new Point();
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 16); private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 16);
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
graphics.translate(preferredLocation.x, preferredLocation.y);
final FontMetrics metrics = graphics.getFontMetrics(); final FontMetrics metrics = graphics.getFontMetrics();
final int barX = 0; final int barX = 0;
final int barY = -metrics.getHeight(); final int barY = 0;
final long span = maximum - minimum; final long span = maximum - minimum;
final double currentValue = value - minimum; final double currentValue = value - minimum;
@@ -92,6 +94,7 @@ public class ProgressBarComponent implements LayoutableRenderableEntity
textComponent.setText(textToWrite); textComponent.setText(textToWrite);
textComponent.render(graphics); textComponent.render(graphics);
graphics.translate(-preferredLocation.x, -preferredLocation.y);
return new Dimension(width, height); return new Dimension(width, height);
} }
} }

View File

@@ -41,18 +41,23 @@ public class TitleComponent implements LayoutableRenderableEntity
@Builder.Default @Builder.Default
private Color color = Color.WHITE; private Color color = Color.WHITE;
@Builder.Default
private Point preferredLocation = new Point();
@Builder.Default @Builder.Default
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0); private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0);
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
graphics.translate(preferredLocation.x, preferredLocation.y);
final FontMetrics metrics = graphics.getFontMetrics(); final FontMetrics metrics = graphics.getFontMetrics();
final TextComponent titleComponent = new TextComponent(); final TextComponent titleComponent = new TextComponent();
titleComponent.setText(text); titleComponent.setText(text);
titleComponent.setColor(color); titleComponent.setColor(color);
titleComponent.setPosition(new Point((preferredSize.width - metrics.stringWidth(text)) / 2, 0)); titleComponent.setPosition(new Point((preferredSize.width - metrics.stringWidth(text)) / 2, metrics.getHeight()));
final Dimension dimension = titleComponent.render(graphics); final Dimension dimension = titleComponent.render(graphics);
graphics.translate(-preferredLocation.x, -preferredLocation.y);
return new Dimension(Math.min(preferredSize.width, dimension.width), dimension.height); return new Dimension(Math.min(preferredSize.width, dimension.width), dimension.height);
} }
} }

View File

@@ -25,36 +25,39 @@
package net.runelite.client.ui.overlay.infobox; package net.runelite.client.ui.overlay.infobox;
import java.awt.Color; import java.awt.Color;
import java.awt.image.BufferedImage; import java.awt.Image;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
public abstract class InfoBox public abstract class InfoBox
{ {
private final BufferedImage image;
@Getter @Getter
private final Plugin plugin; private final Plugin plugin;
@Getter
@Setter
private Image image;
@Getter
@Setter
private Image scaledImage;
@Getter @Getter
@Setter @Setter
private InfoBoxPriority priority; private InfoBoxPriority priority;
@Getter
@Setter
private String tooltip; private String tooltip;
public InfoBox(BufferedImage image, Plugin plugin) public InfoBox(Image image, Plugin plugin)
{ {
this.image = image;
this.plugin = plugin; this.plugin = plugin;
setImage(image);
setPriority(InfoBoxPriority.NONE); setPriority(InfoBoxPriority.NONE);
} }
public BufferedImage getImage()
{
return image;
}
public abstract String getText(); public abstract String getText();
public abstract Color getTextColor(); public abstract Color getTextColor();
@@ -68,14 +71,4 @@ public abstract class InfoBox
{ {
return false; return false;
} }
public String getTooltip()
{
return tooltip;
}
public void setTooltip(String tooltip)
{
this.tooltip = tooltip;
}
} }

View File

@@ -26,13 +26,20 @@ package net.runelite.client.ui.overlay.infobox;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain; import com.google.common.collect.ComparisonChain;
import com.google.common.eventbus.Subscribe;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.ConfigChanged;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
@Singleton @Singleton
@@ -40,13 +47,30 @@ import net.runelite.client.plugins.PluginDescriptor;
public class InfoBoxManager public class InfoBoxManager
{ {
private final List<InfoBox> infoBoxes = new ArrayList<>(); private final List<InfoBox> infoBoxes = new ArrayList<>();
private final RuneLiteConfig runeLiteConfig;
@Inject
private InfoBoxManager(final RuneLiteConfig runeLiteConfig)
{
this.runeLiteConfig = runeLiteConfig;
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getGroup().equals("runelite") && event.getKey().equals("infoBoxSize"))
{
infoBoxes.forEach(this::updateInfoBoxImage);
}
}
public void addInfoBox(InfoBox infoBox) public void addInfoBox(InfoBox infoBox)
{ {
Preconditions.checkNotNull(infoBox); Preconditions.checkNotNull(infoBox);
log.debug("Adding InfoBox {}", infoBox); log.debug("Adding InfoBox {}", infoBox);
infoBoxes.add(infoBox);
updateInfoBoxImage(infoBox);
infoBoxes.add(infoBox);
refreshInfoBoxes(); refreshInfoBoxes();
} }
@@ -92,6 +116,43 @@ public class InfoBoxManager
} }
} }
private void updateInfoBoxImage(final InfoBox infoBox)
{
if (infoBox.getImage() == null)
{
return;
}
// Set scaled InfoBox image
final Image image = infoBox.getImage();
Image resultImage = image;
final double width = image.getWidth(null);
final double height = image.getHeight(null);
final double size = Math.max(2, runeLiteConfig.infoBoxSize()); // Limit size to 2 as that is minimum size not causing breakage
if (size < width || size < height)
{
final double scalex = size / width;
final double scaley = size / height;
if (scalex == 1 && scaley == 1)
{
return;
}
final double scale = Math.min(scalex, scaley);
final int newWidth = (int) (width * scale);
final int newHeight = (int) (height * scale);
final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
final Graphics g = scaledImage.createGraphics();
g.drawImage(image, 0, 0, newWidth, newHeight, null);
g.dispose();
resultImage = scaledImage;
}
infoBox.setScaledImage(resultImage);
}
private void refreshInfoBoxes() private void refreshInfoBoxes()
{ {
Collections.sort(infoBoxes, (b1, b2) -> ComparisonChain Collections.sort(infoBoxes, (b1, b2) -> ComparisonChain

View File

@@ -39,15 +39,14 @@ import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil; import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.components.InfoBoxComponent; import net.runelite.client.ui.overlay.components.InfoBoxComponent;
import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.tooltip.Tooltip; import net.runelite.client.ui.overlay.tooltip.Tooltip;
import net.runelite.client.ui.overlay.tooltip.TooltipManager; import net.runelite.client.ui.overlay.tooltip.TooltipManager;
public class InfoBoxOverlay extends Overlay public class InfoBoxOverlay extends Overlay
{ {
private static final int BOXSIZE = 35; private final PanelComponent panelComponent = new PanelComponent();
private static final int SEPARATOR = 2;
private static final int TOTAL_BOXSIZE = BOXSIZE + SEPARATOR;
private final InfoBoxManager infoboxManager; private final InfoBoxManager infoboxManager;
private final TooltipManager tooltipManager; private final TooltipManager tooltipManager;
private final Provider<Client> clientProvider; private final Provider<Client> clientProvider;
@@ -65,108 +64,73 @@ public class InfoBoxOverlay extends Overlay
this.clientProvider = clientProvider; this.clientProvider = clientProvider;
this.config = config; this.config = config;
setPosition(OverlayPosition.TOP_LEFT); setPosition(OverlayPosition.TOP_LEFT);
panelComponent.setBackgroundColor(null);
panelComponent.setBorder(new Rectangle());
panelComponent.setGap(new Point(1, 1));
} }
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
List<InfoBox> infoBoxes = infoboxManager.getInfoBoxes(); final List<InfoBox> infoBoxes = infoboxManager.getInfoBoxes();
if (infoBoxes.isEmpty()) if (infoBoxes.isEmpty())
{ {
return null; return null;
} }
int wrap = config.infoBoxWrap(); panelComponent.getChildren().clear();
int infoBoxCount = infoBoxes.size(); panelComponent.setWrapping(config.infoBoxWrap());
boolean vertical = config.infoBoxVertical(); panelComponent.setOrientation(config.infoBoxVertical()
? PanelComponent.Orientation.VERTICAL
: PanelComponent.Orientation.HORIZONTAL);
panelComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
int width, height; infoBoxes.forEach(box ->
if (!vertical)
{ {
width = getWidth(infoBoxCount, wrap);
height = getHeight(infoBoxCount, wrap);
}
else
{
width = getHeight(infoBoxCount, wrap);
height = getWidth(infoBoxCount, wrap);
}
int x = 0;
int y = 0;
for (InfoBox box : infoBoxes)
{
if (!box.render())
{
continue;
}
final InfoBoxComponent infoBoxComponent = new InfoBoxComponent(); final InfoBoxComponent infoBoxComponent = new InfoBoxComponent();
infoBoxComponent.setColor(box.getTextColor()); infoBoxComponent.setColor(box.getTextColor());
infoBoxComponent.setImage(box.getImage()); infoBoxComponent.setImage(box.getScaledImage());
infoBoxComponent.setText(box.getText()); infoBoxComponent.setText(box.getText());
infoBoxComponent.setPosition(new Point(x, y)); infoBoxComponent.setTooltip(box.getTooltip());
final Dimension infoBoxBounds = infoBoxComponent.render(graphics); panelComponent.getChildren().add(infoBoxComponent);
});
if (!Strings.isNullOrEmpty(box.getTooltip())) final Dimension dimension = panelComponent.render(graphics);
final Client client = clientProvider.get();
// Handle tooltips
if (client != null)
{
final Point mouse = new Point(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY());
for (final LayoutableRenderableEntity child : panelComponent.getChildren())
{ {
final Rectangle intersectionRectangle = new Rectangle(infoBoxBounds); if (child instanceof InfoBoxComponent)
intersectionRectangle.setLocation(getBounds().getLocation()); {
intersectionRectangle.translate(x, y); final InfoBoxComponent component = (InfoBoxComponent) child;
final Point transformed = OverlayUtil.transformPosition(getPosition(), intersectionRectangle.getSize());
intersectionRectangle.translate(transformed.x, transformed.y);
final Client client = clientProvider.get(); if (!Strings.isNullOrEmpty(component.getTooltip()))
{
final Rectangle intersectionRectangle = new Rectangle(component.getPreferredLocation(), component.getPreferredSize());
if (client != null && intersectionRectangle.contains(new Point(client.getMouseCanvasPosition().getX(), // Move the intersection based on overlay position
client.getMouseCanvasPosition().getY()))) intersectionRectangle.translate(getBounds().x, getBounds().y);
{
tooltipManager.add(new Tooltip(box.getTooltip()));
}
}
// Determine which axis to reset/increase // Move the intersection based on overlay "orientation"
if (vertical) final Point transformed = OverlayUtil.transformPosition(getPosition(), intersectionRectangle.getSize());
{ intersectionRectangle.translate(transformed.x, transformed.y);
// Reset y if newbox reaches height limit
if (y + TOTAL_BOXSIZE < height) if (intersectionRectangle.contains(mouse))
{ {
y += TOTAL_BOXSIZE; tooltipManager.add(new Tooltip(component.getTooltip()));
} }
else }
{
y = 0;
x += TOTAL_BOXSIZE;
}
}
else
{
// Reset x if newbox reaches width limit
if (x + TOTAL_BOXSIZE < width)
{
x += TOTAL_BOXSIZE;
}
else
{
x = 0;
y += TOTAL_BOXSIZE;
} }
} }
} }
return new Dimension(width, height); return dimension;
}
private static int getHeight(int infoBoxCount, int maxRow)
{
return maxRow == 0 ? TOTAL_BOXSIZE : (int) Math.ceil((double)infoBoxCount / maxRow) * TOTAL_BOXSIZE;
}
private static int getWidth(int infoBoxCount, int maxRow)
{
return maxRow == 0 ? infoBoxCount * TOTAL_BOXSIZE : (maxRow > infoBoxCount ? infoBoxCount : maxRow) * TOTAL_BOXSIZE;
} }
} }