From fa9e05f0a680a9abc8100a410f2c162945f9da8f Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Sun, 6 May 2018 19:56:47 +0200 Subject: [PATCH] Merge ImagePanelComponent with PanelComponent - Remove ImagePanelComponent - Add LayoutableRenderableEntity that is RenderableEntity with preferred size - Add support to PanelComponent for rendering list of LayoutableRenderableEntity - Add support for aligning PanelComponent horizontally or vertically - Add ImageComponent to be used in PanelComponent - Make other components support new design Signed-off-by: Tomas Slusny --- .../ui/overlay/components/ImageComponent.java | 56 +++++ .../components/ImagePanelComponent.java | 127 ---------- .../LayoutableRenderableEntity.java | 33 +++ .../ui/overlay/components/LineComponent.java | 170 +++++++++++++ .../ui/overlay/components/PanelComponent.java | 237 +++++------------- .../components/ProgressBarComponent.java | 16 +- .../ui/overlay/components/TextComponent.java | 11 +- 7 files changed, 333 insertions(+), 317 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java delete mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImagePanelComponent.java create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java new file mode 100644 index 0000000000..4eef508b39 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImageComponent.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.components; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import lombok.AllArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@Setter +public class ImageComponent implements LayoutableRenderableEntity +{ + private BufferedImage image; + + @Override + public Dimension render(Graphics2D graphics) + { + if (image == null) + { + return null; + } + + graphics.drawImage(image, 0, -graphics.getFontMetrics().getHeight(), null); + return new Dimension(image.getWidth(), image.getHeight()); + } + + @Override + public void setPreferredSize(Dimension dimension) + { + // Just use image dimensions for now + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImagePanelComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImagePanelComponent.java deleted file mode 100644 index cc81463875..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ImagePanelComponent.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2017, Devin French - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.components; - -import com.google.common.base.Strings; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import javax.annotation.Nullable; -import lombok.Getter; -import lombok.Setter; -import net.runelite.client.ui.overlay.RenderableEntity; - -public class ImagePanelComponent implements RenderableEntity -{ - private static final int TOP_BORDER = 4; - private static final int SIDE_BORDER = 4; - private static final int BOTTOM_BORDER = 4; - private static final int SEPARATOR = 1; - - @Setter - @Nullable - private String title; - - @Setter - private Color titleColor = Color.WHITE; - - @Setter - private Color backgroundColor = BackgroundComponent.DEFAULT_BACKGROUND_COLOR; - - @Getter - private final List images = new ArrayList<>(); - - @Setter - private Point position = new Point(); - - @Override - public Dimension render(Graphics2D graphics) - { - final Dimension dimension = new Dimension(); - final FontMetrics metrics = graphics.getFontMetrics(); - - //Determine max height and width of images - int maxImageHeight = 0; - int imageWidth = 0; - for (final BufferedImage image : images) - { - if (image.getHeight() > maxImageHeight) - { - maxImageHeight = image.getHeight(); - } - imageWidth += image.getWidth() + SEPARATOR; - } - - int height = TOP_BORDER + (Strings.isNullOrEmpty(title) ? 0 : metrics.getHeight() + SEPARATOR) - + maxImageHeight + BOTTOM_BORDER; - int width = Math.max(Strings.isNullOrEmpty(title) ? 0 : metrics.stringWidth(title), imageWidth) + SIDE_BORDER * 2; - dimension.setSize(width, height); - - if (dimension.height == TOP_BORDER + BOTTOM_BORDER) - { - return null; - } - - int y = position.y + TOP_BORDER; - if (!Strings.isNullOrEmpty(title)) - { - // Calculate panel dimensions - y += metrics.getHeight(); - } - - // Render background - final BackgroundComponent backgroundComponent = new BackgroundComponent(); - backgroundComponent.setBackgroundColor(backgroundColor); - backgroundComponent.setRectangle(new Rectangle(position.x, position.y, dimension.width, dimension.height)); - backgroundComponent.render(graphics); - - // Render title - if (!Strings.isNullOrEmpty(title)) - { - final TextComponent titleComponent = new TextComponent(); - titleComponent.setText(title); - titleComponent.setColor(titleColor); - titleComponent.setPosition(new Point(position.x + (width - metrics.stringWidth(title)) / 2, y)); - titleComponent.render(graphics); - y += SEPARATOR; - } - - // Render all images - int imageOffsetX = ((width - imageWidth) / 2); - for (final BufferedImage image : images) - { - graphics.drawImage(image, imageOffsetX + ((imageWidth / images.size()) - image.getWidth()) / 2, y, null); - imageOffsetX += image.getWidth() + SEPARATOR; - } - - return dimension; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java new file mode 100644 index 0000000000..b717f58706 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LayoutableRenderableEntity.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.components; + +import java.awt.Dimension; +import net.runelite.client.ui.overlay.RenderableEntity; + +public interface LayoutableRenderableEntity extends RenderableEntity +{ + void setPreferredSize(Dimension dimension); +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java new file mode 100644 index 0000000000..1cdcf68df6 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/LineComponent.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018, Tomas Slusny + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.ui.overlay.components; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import lombok.Builder; +import lombok.Setter; + +@Setter +@Builder +public class LineComponent implements LayoutableRenderableEntity +{ + private static final int SEPARATOR = 1; + + private String left; + private String right; + + @Builder.Default + private Color leftColor = Color.WHITE; + + @Builder.Default + private Color rightColor = Color.WHITE; + + @Builder.Default + private Dimension preferredSize = new Dimension(); + + @Override + public Dimension render(Graphics2D graphics) + { + // Prevent NPEs + final String left = MoreObjects.firstNonNull(this.left, ""); + final String right = MoreObjects.firstNonNull(this.right, ""); + + final FontMetrics metrics = graphics.getFontMetrics(); + int x = 0; + int y = 0; + final int leftFullWidth = getLineWidth(left, metrics); + final int rightFullWidth = getLineWidth(right, metrics); + + if (preferredSize.width < leftFullWidth + rightFullWidth) + { + int leftSmallWidth = preferredSize.width; + int rightSmallWidth = 0; + + if (!Strings.isNullOrEmpty(right)) + { + rightSmallWidth = (preferredSize.width / 3); + leftSmallWidth -= rightSmallWidth; + } + + final String[] leftSplitLines = lineBreakText(left, leftSmallWidth, metrics); + final String[] rightSplitLines = lineBreakText(right, rightSmallWidth, metrics); + + int lineCount = Math.max(leftSplitLines.length, rightSplitLines.length); + + for (int i = 0; i < lineCount; i++) + { + String leftText = ""; + String rightText = ""; + + if (i < leftSplitLines.length) + { + leftText = leftSplitLines[i]; + } + + if (i < rightSplitLines.length) + { + rightText = rightSplitLines[i]; + } + + final TextComponent leftLineComponent = new TextComponent(); + leftLineComponent.setPosition(new Point(x, y)); + leftLineComponent.setText(leftText); + leftLineComponent.setColor(leftColor); + leftLineComponent.render(graphics); + + final TextComponent rightLineComponent = new TextComponent(); + rightLineComponent.setPosition(new Point(x + leftSmallWidth + rightFullWidth - getLineWidth(rightText, metrics), y)); + rightLineComponent.setText(rightText); + rightLineComponent.setColor(rightColor); + rightLineComponent.render(graphics); + y += metrics.getHeight() + SEPARATOR; + } + + return new Dimension(preferredSize.width, y); + } + + final TextComponent leftLineComponent = new TextComponent(); + leftLineComponent.setPosition(new Point(x, y)); + leftLineComponent.setText(left); + leftLineComponent.setColor(leftColor); + leftLineComponent.render(graphics); + + final TextComponent rightLineComponent = new TextComponent(); + rightLineComponent.setPosition(new Point(x + preferredSize.width - getLineWidth(right, metrics), y)); + rightLineComponent.setText(right); + rightLineComponent.setColor(rightColor); + rightLineComponent.render(graphics); + y += metrics.getHeight() + SEPARATOR; + + return new Dimension(preferredSize.width, y); + } + + private static int getLineWidth(final String line, final FontMetrics metrics) + { + return metrics.stringWidth(TextComponent.textWithoutColTags(line)); + } + + private static String[] lineBreakText(String text, int maxWidth, FontMetrics metrics) + { + final String[] words = text.split(" "); + + if (words.length == 0) + { + return new String[0]; + } + + final StringBuilder wrapped = new StringBuilder(words[0]); + int spaceLeft = maxWidth - metrics.stringWidth(wrapped.toString()); + + for (int i = 1; i < words.length; i++) + { + final String word = words[i]; + final int wordLen = metrics.stringWidth(word); + final int spaceWidth = metrics.stringWidth(" "); + + if (wordLen + spaceWidth > spaceLeft) + { + wrapped.append("\n").append(word); + spaceLeft = maxWidth - wordLen; + } + else + { + wrapped.append(" ").append(word); + spaceLeft -= spaceWidth + wordLen; + } + } + + return wrapped.toString().split("\n"); + } +} + diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java index 600c01287d..0bf95c128d 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/PanelComponent.java @@ -33,78 +33,23 @@ import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; import java.util.List; -import java.util.ListIterator; -import java.util.Objects; -import lombok.AllArgsConstructor; -import lombok.Data; import lombok.Getter; import lombok.Setter; -import net.runelite.client.ui.overlay.RenderableEntity; -public class PanelComponent implements RenderableEntity +public class PanelComponent implements LayoutableRenderableEntity { + public enum Orientation + { + HORIZONTAL, + VERTICAL; + } + private static final int TOP_BORDER = 4; private static final int LEFT_BORDER = 4; private static final int RIGHT_BORDER = 4; private static final int BOTTOM_BORDER = 4; private static final int SEPARATOR = 1; - @Data - @AllArgsConstructor - public static class Line - { - private boolean wrapWords; - private String left; - private Color leftColor = Color.WHITE; - private String right = ""; - private Color rightColor = Color.WHITE; - - public Line(String left) - { - this.left = left; - } - - public Line(boolean wrapWords, String left) - { - this.wrapWords = wrapWords; - this.left = left; - } - - public Line(String left, Color leftColor) - { - this.left = left; - this.leftColor = leftColor; - } - - public Line(boolean wrapWords, String left, Color leftColor) - { - this.wrapWords = wrapWords; - this.left = left; - this.leftColor = leftColor; - } - - public Line(String left, String right) - { - this.left = left; - this.right = right; - } - - public Line(boolean wrapWords, String left, String right) - { - this.wrapWords = wrapWords; - this.left = left; - this.right = right; - } - - public Line(String left, Color leftColor, String right, Color rightColor) - { - this.left = left; - this.leftColor = leftColor; - this.right = right; - this.rightColor = rightColor; - } - } - @Setter private String title; @@ -117,152 +62,92 @@ public class PanelComponent implements RenderableEntity @Setter private Point position = new Point(); + @Setter + private Dimension preferredSize = new Dimension(129, 0); + @Getter - private List lines = new ArrayList<>(); + private List children = new ArrayList<>(); @Setter - private ProgressBarComponent progressBar; + private Orientation orientation = Orientation.VERTICAL; - @Setter - private int width = 129; + private final Dimension savedChildrenSize = new Dimension(); @Override public Dimension render(Graphics2D graphics) { - final FontMetrics metrics = graphics.getFontMetrics(); - - // Do word wrapping - ListIterator iterator = lines.listIterator(); - while (iterator.hasNext()) - { - Line line = iterator.next(); - - if (line.wrapWords) - { - iterator.remove(); - - int maxWidth = width; - if (line.right.length() > 0) - { - maxWidth /= 2; - } - maxWidth -= LEFT_BORDER + RIGHT_BORDER; - - List leftSplitLines = lineBreakText(line.getLeft(), maxWidth, metrics); - List rightSplitLines = lineBreakText(line.getRight(), maxWidth, metrics); - - int lineCount = Math.max(leftSplitLines.size(), rightSplitLines.size()); - - for (int i = 0; i < lineCount; i++) - { - String left = ""; - String right = ""; - - if (i < leftSplitLines.size()) - { - left = leftSplitLines.get(i); - } - - if (i < rightSplitLines.size()) - { - right = rightSplitLines.get(i); - } - - iterator.add(new Line(false, left, line.getLeftColor(), right, line.getRightColor())); - } - } - } - - final Dimension dimension = new Dimension(); - final int elementNumber = (Strings.isNullOrEmpty(title) ? 0 : 1) + lines.size() + (Objects.isNull(progressBar) ? 0 : 1); - int height = elementNumber == 0 ? 0 : - TOP_BORDER + (graphics.getFontMetrics().getHeight() * elementNumber) - + SEPARATOR * elementNumber + (Objects.isNull(progressBar) ? 0 : progressBar.getHeight() / 2) - + BOTTOM_BORDER; - dimension.setSize(width, height); - - if (dimension.height == 0) + if (Strings.isNullOrEmpty(title) && children.isEmpty()) { return null; } + final FontMetrics metrics = graphics.getFontMetrics(); + // Calculate panel dimensions - int y = position.y + TOP_BORDER + metrics.getHeight(); + int width = preferredSize.width; + int height = preferredSize.height; + int x = LEFT_BORDER; + int y = TOP_BORDER + metrics.getHeight(); + + // Set graphics offset at correct position + graphics.translate(position.x, position.y); // Render background + final Dimension dimension = new Dimension( + savedChildrenSize.width + RIGHT_BORDER, + savedChildrenSize.height + BOTTOM_BORDER); + final BackgroundComponent backgroundComponent = new BackgroundComponent(); + backgroundComponent.setRectangle(new Rectangle(dimension)); backgroundComponent.setBackgroundColor(backgroundColor); - backgroundComponent.setRectangle(new Rectangle(position.x, position.y, dimension.width, dimension.height)); backgroundComponent.render(graphics); - // Render title if (!Strings.isNullOrEmpty(title)) { + // Render title final TextComponent titleComponent = new TextComponent(); titleComponent.setText(title); titleComponent.setColor(titleColor); - titleComponent.setPosition(new Point(position.x + (width - metrics.stringWidth(title)) / 2, y)); + titleComponent.setPosition(new Point((dimension.width - metrics.stringWidth(title)) / 2, y)); titleComponent.render(graphics); - y += metrics.getHeight() + SEPARATOR; + + // Move children a bit + height = y += metrics.getHeight() + SEPARATOR; } - // Render all lines - for (final Line line : lines) + // Render all children + final Dimension childPreferredSize = new Dimension( + preferredSize.width - RIGHT_BORDER, + preferredSize.height - BOTTOM_BORDER); + + for (final LayoutableRenderableEntity child : children) { - final TextComponent leftLineComponent = new TextComponent(); - leftLineComponent.setPosition(new Point(position.x + LEFT_BORDER, y)); - leftLineComponent.setText(line.getLeft()); - leftLineComponent.setColor(line.getLeftColor()); - leftLineComponent.render(graphics); + child.setPreferredSize(childPreferredSize); + graphics.translate(x, y); + final Dimension childDimension = child.render(graphics); + graphics.translate(-x, -y); - final TextComponent rightLineComponent = new TextComponent(); - rightLineComponent.setPosition(new Point(position.x + width - RIGHT_BORDER - metrics.stringWidth(TextComponent.textWithoutColTags(line.getRight())), y)); - rightLineComponent.setText(line.getRight()); - rightLineComponent.setColor(line.getRightColor()); - rightLineComponent.render(graphics); - y += metrics.getHeight() + SEPARATOR; + switch (orientation) + { + case VERTICAL: + height = y += childDimension.height + SEPARATOR; + width = Math.max(width, x + childDimension.width); + break; + case HORIZONTAL: + width = x += childDimension.width + SEPARATOR; + height = Math.max(height, y + childDimension.height); + break; + } } - //Render progress bar - if (!Objects.isNull(progressBar)) - { - progressBar.setWidth(width - LEFT_BORDER - RIGHT_BORDER); - progressBar.setPosition(new Point(position.x + LEFT_BORDER, y - (metrics.getHeight() / 2))); - progressBar.render(graphics); - } + // Reset the padding + height -= metrics.getHeight(); + // Save children size + savedChildrenSize.setSize(width, height); + + // Reset graphics position + graphics.translate(-position.x, -position.y); return dimension; } - - private List lineBreakText(String text, int maxWidth, FontMetrics metrics) - { - List lines = new ArrayList<>(); - - int pos = 0; - String[] words = text.split(" "); - String line = ""; - - while (pos < words.length) - { - String newLine = pos > 0 && !line.isEmpty() - ? line + " " + words[pos] - : words[pos]; - int width = metrics.stringWidth(newLine); - - if (width >= maxWidth) - { - lines.add(line); - line = ""; - } - else - { - line = newLine; - pos++; - } - } - - lines.add(line); - - return lines; - } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java index 00b8f624f5..6fbbaa5bb4 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/ProgressBarComponent.java @@ -31,10 +31,9 @@ import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Point; import java.text.DecimalFormat; -import lombok.Getter; import lombok.Setter; -public class ProgressBarComponent +public class ProgressBarComponent implements LayoutableRenderableEntity { @Setter private String text; @@ -54,20 +53,16 @@ public class ProgressBarComponent @Setter private Color fontColor = Color.WHITE; - @Getter @Setter - private int width = 140; - - @Getter - @Setter - private int height = 16; + private Dimension preferredSize = new Dimension(129, 16); + @Override public Dimension render(Graphics2D graphics) { FontMetrics metrics = graphics.getFontMetrics(); int barX = position.x; - int barY = position.y; + int barY = position.y - metrics.getHeight(); String textToWrite; if (Strings.isNullOrEmpty(text)) @@ -80,6 +75,9 @@ public class ProgressBarComponent textToWrite = text; } + int width = preferredSize.width; + int height = Math.max(preferredSize.height, 16); + int progressTextX = barX + (width - metrics.stringWidth(textToWrite)) / 2; int progressTextY = barY + ((height - metrics.getHeight()) / 2) + metrics.getAscent(); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java index 11f3615feb..b0656614c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/TextComponent.java @@ -60,13 +60,13 @@ public class TextComponent implements RenderableEntity if (COL_TAG_PATTERN.matcher(text).find()) { - String[] parts = COL_TAG_PATTERN_W_LOOKAHEAD.split(text); + final String[] parts = COL_TAG_PATTERN_W_LOOKAHEAD.split(text); int x = position.x; - for (int i = 0; i < parts.length; i++) + + for (String textSplitOnCol : parts) { - String textSplitOnCol = parts[i]; - String textWithoutCol = textWithoutColTags(textSplitOnCol); - String colColor = textSplitOnCol.substring(textSplitOnCol.indexOf("=") + 1, textSplitOnCol.indexOf(">")); + final String textWithoutCol = textWithoutColTags(textSplitOnCol); + final String colColor = textSplitOnCol.substring(textSplitOnCol.indexOf("=") + 1, textSplitOnCol.indexOf(">")); // shadow graphics.setColor(Color.BLACK); @@ -89,6 +89,7 @@ public class TextComponent implements RenderableEntity graphics.setColor(color); graphics.drawString(text, position.x, position.y); } + return new Dimension(fontMetrics.stringWidth(text), fontMetrics.getHeight()); } }