diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java index d3eb52044d..6372ea82c6 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/grandexchange/GrandExchangeSearchPanel.java @@ -35,7 +35,6 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; import javax.imageio.ImageIO; -import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; @@ -46,7 +45,7 @@ import net.runelite.api.Client; import net.runelite.api.ItemComposition; import net.runelite.client.game.AsyncBufferedImage; import net.runelite.client.game.ItemManager; -import net.runelite.client.plugins.hiscore.IconTextField; +import net.runelite.client.ui.components.IconTextField; import net.runelite.http.api.item.Item; import net.runelite.http.api.item.ItemPrice; import net.runelite.http.api.item.SearchResult; @@ -60,7 +59,7 @@ class GrandExchangeSearchPanel extends JPanel private final ItemManager itemManager; private final ScheduledExecutorService executor; - private Icon search; + private ImageIcon search; private IconTextField searchBox = new IconTextField(); private JPanel container = new JPanel(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java index 948b2dd8ee..3bf64d811c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/HiscorePanel.java @@ -49,7 +49,6 @@ import javax.imageio.ImageIO; import javax.inject.Inject; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; -import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; @@ -64,6 +63,7 @@ import net.runelite.api.Client; import net.runelite.api.Experience; import net.runelite.api.Player; import net.runelite.client.ui.PluginPanel; +import net.runelite.client.ui.components.IconTextField; import net.runelite.client.util.StackFormatter; import net.runelite.http.api.hiscore.HiscoreClient; import net.runelite.http.api.hiscore.HiscoreEndpoint; @@ -165,7 +165,7 @@ public class HiscorePanel extends PluginPanel inputPanel.setLayout(new BorderLayout(7, 7)); inputPanel.setBorder(subPanelBorder); - Icon search; + ImageIcon search; try { BufferedImage icon; @@ -417,14 +417,14 @@ public class HiscorePanel extends PluginPanel { String rank = (result.getBountyHunterHunter().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getBountyHunterHunter().getRank()); text = "Bounty Hunter - Hunter Kills" + System.lineSeparator() - + "Rank: " + rank; + + "Rank: " + rank; break; } case "Last Man Standing": { String rank = (result.getLastManStanding().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getLastManStanding().getRank()); text = "Last Man Standing" + System.lineSeparator() - + "Rank: " + rank; + + "Rank: " + rank; break; } case "Overall": @@ -586,13 +586,13 @@ public class HiscorePanel extends PluginPanel if (result.getPlayer() != null) { int combatLevel = Experience.getCombatLevel( - result.getAttack().getLevel(), - result.getStrength().getLevel(), - result.getDefence().getLevel(), - result.getHitpoints().getLevel(), - result.getMagic().getLevel(), - result.getRanged().getLevel(), - result.getPrayer().getLevel() + result.getAttack().getLevel(), + result.getStrength().getLevel(), + result.getDefence().getLevel(), + result.getHitpoints().getLevel(), + result.getMagic().getLevel(), + result.getRanged().getLevel(), + result.getPrayer().getLevel() ); label.setText(Integer.toString(combatLevel)); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UIActionSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UIActionSlot.java index 74c3bfe16f..dcc6cba345 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UIActionSlot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UIActionSlot.java @@ -34,7 +34,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry; import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.JShadowedLabel; +import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; class UIActionSlot extends JPanel { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICombinedActionSlot.java b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICombinedActionSlot.java index acdd05b7de..d981e9d97f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICombinedActionSlot.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/skillcalculator/UICombinedActionSlot.java @@ -33,7 +33,7 @@ import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JPanel; import net.runelite.client.ui.FontManager; -import net.runelite.client.ui.JShadowedLabel; +import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; class UICombinedActionSlot extends JPanel { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java index 01bcdcc0bd..4ece97d152 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/xptracker/XpInfoBox.java @@ -53,7 +53,7 @@ import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; import net.runelite.api.Skill; import net.runelite.client.game.SkillIconManager; -import net.runelite.client.ui.JShadowedLabel; +import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; import net.runelite.client.util.LinkBrowser; import org.pushingpixels.substance.internal.SubstanceSynapse; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java b/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java index 1f5f9d7878..bec0c4f052 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java @@ -34,6 +34,9 @@ public class ColorScheme /* The orange color used for the branding's accents */ public static final Color BRAND_ORANGE = new Color(220, 138, 0); + /* The orange color used for the branding's accents, with lowered opacity */ + public static final Color BRAND_ORANGE_TRANSPARENT = new Color(220, 138, 0, 120); + public static final Color DARKER_GRAY_COLOR = new Color(30, 30, 30); public static final Color DARK_GRAY_COLOR = new Color(40, 40, 40); public static final Color MEDIUM_GRAY_COLOR = new Color(77, 77, 77); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/PluginPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/PluginPanel.java index ca93c74fe0..44835b771e 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/PluginPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/PluginPanel.java @@ -68,7 +68,6 @@ public abstract class PluginPanel extends JPanel northPanel.setBackground(ColorScheme.DARK_GRAY_COLOR); scrollPane = new JScrollPane(northPanel); - scrollPane.getVerticalScrollBar().setUnitIncrement(16); //Otherwise scrollspeed is really slow scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); wrappedPanel = new JPanel(); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/CustomScrollBarUI.java b/runelite-client/src/main/java/net/runelite/client/ui/components/CustomScrollBarUI.java new file mode 100644 index 0000000000..7714042049 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/CustomScrollBarUI.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018, Psikoi + * 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.components; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollBarUI; +import net.runelite.client.ui.ColorScheme; + +/** + * This scroll bar UI is to be used for the "RuneLite Obsidian" client theme. + * It is a part of the client's redesign as detailed on issue #1342 + */ +public class CustomScrollBarUI extends BasicScrollBarUI +{ + /** + * Overrides the painting of the bar's track (the darker part underneath that extends + * the full page length). + */ + @Override + protected void paintTrack(Graphics graphics, JComponent jComponent, Rectangle rectangle) + { + graphics.setColor(ColorScheme.SCROLL_TRACK_COLOR); + graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } + + /** + * Overrides the painting of the bar's thumb (the lighter part on top that users + * use to slide up and down the page). + */ + @Override + protected void paintThumb(Graphics graphics, JComponent jComponent, Rectangle rectangle) + { + graphics.setColor(ColorScheme.MEDIUM_GRAY_COLOR); + graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } + + /** + * Creates an empty JButton to be used as the scroll bar's arrows (to disable the arrows). + */ + protected JButton createEmptyButton() + { + JButton button = new JButton(); + Dimension zeroDim = new Dimension(0, 0); + button.setPreferredSize(zeroDim); + button.setMinimumSize(zeroDim); + button.setMaximumSize(zeroDim); + return button; + } + + public static ComponentUI createUI(JComponent c) + { + JScrollBar bar = (JScrollBar) c; + bar.setUnitIncrement(16); + bar.setPreferredSize(new Dimension(7, 0)); + return new CustomScrollBarUI(); + } + + /** + * Applies an empty button to the decrease (down arrow) button. + */ + @Override + protected JButton createDecreaseButton(int orientation) + { + return createEmptyButton(); + } + + /** + * Applies an empty button to the increase (up arrow) button. + */ + @Override + protected JButton createIncreaseButton(int orientation) + { + return createEmptyButton(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java new file mode 100644 index 0000000000..fde8d673cb --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/IconTextField.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017, Adam + * Copyright (c) 2018, Psikoi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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 HOLDER 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.components; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import net.runelite.client.ui.ColorScheme; + +/** + * This component is a JTextField with an icon on its left side. + */ +public class IconTextField extends JPanel +{ + private final JTextField textField; + + //to support gifs, the icon needs to be wrapped in a JLabel + private final JLabel iconWrapperLabel; + + //the default background color, this needs to be stored for hover effects + private Color backgroundColor = ColorScheme.DARKER_GRAY_COLOR; + //the default hover background color, this needs to be stored for hover effects + private Color hoverBackgroundColor; + + // the input can be blocked (no clicking, no editing, no hover effects) + private boolean blocked; + + public IconTextField() + { + setLayout(new BorderLayout()); + + this.iconWrapperLabel = new JLabel(); + this.iconWrapperLabel.setPreferredSize(new Dimension(30, 0)); + this.iconWrapperLabel.setVerticalAlignment(JLabel.CENTER); + this.iconWrapperLabel.setHorizontalAlignment(JLabel.CENTER); + + this.textField = new JTextField(); + this.textField.setBorder(null); + this.textField.setOpaque(false); + this.textField.setSelectedTextColor(Color.WHITE); + this.textField.setSelectionColor(ColorScheme.BRAND_ORANGE_TRANSPARENT); + + add(iconWrapperLabel, BorderLayout.WEST); + add(textField, BorderLayout.CENTER); + + textField.addMouseListener(new MouseAdapter() + { + @Override + public void mouseEntered(MouseEvent mouseEvent) + { + if (blocked) + { + return; + } + + if (hoverBackgroundColor != null) + { + IconTextField.super.setBackground(hoverBackgroundColor); + } + } + + @Override + public void mouseExited(MouseEvent mouseEvent) + { + IconTextField.super.setBackground(backgroundColor); + } + }); + } + + public void addActionListener(ActionListener actionListener) + { + textField.addActionListener(actionListener); + } + + public void setIcon(ImageIcon icon) + { + iconWrapperLabel.setIcon(icon); + } + + public String getText() + { + return textField.getText(); + } + + public void setText(String text) + { + textField.setText(text); + } + + @Override + public void setBackground(Color color) + { + if (color == null) + { + return; + } + super.setBackground(color); + this.backgroundColor = color; + } + + public void setHoverBackgroundColor(Color hoverBackgroundColor) + { + if (hoverBackgroundColor == null) + { + return; + } + this.hoverBackgroundColor = hoverBackgroundColor; + } + + public void setEditable(boolean editable) + { + this.blocked = !editable; + textField.setEditable(editable); + textField.setFocusable(editable); + if (!editable) + { + super.setBackground(backgroundColor); + } + } + +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/PluginErrorPanel.java b/runelite-client/src/main/java/net/runelite/client/ui/components/PluginErrorPanel.java new file mode 100644 index 0000000000..779253cff0 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/PluginErrorPanel.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, Psikoi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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 HOLDER 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.components; + +import java.awt.BorderLayout; +import java.awt.Color; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.components.shadowlabel.JShadowedLabel; + +/** + * A component to display an error/info message (to be used on a plugin panel) + * Example uses are: no ge search results found, no ge offers found. + */ +public class PluginErrorPanel extends JPanel +{ + private final JLabel noResultsTitle = new JShadowedLabel(); + private final JLabel noResultsDescription = new JShadowedLabel(); + + public PluginErrorPanel() + { + setOpaque(false); + setBorder(new EmptyBorder(50, 0, 0, 0)); + setLayout(new BorderLayout()); + + noResultsTitle.setForeground(Color.WHITE); + noResultsTitle.setHorizontalAlignment(SwingConstants.CENTER); + + noResultsDescription.setFont(FontManager.getRunescapeSmallFont()); + noResultsDescription.setForeground(Color.GRAY); + noResultsDescription.setHorizontalAlignment(SwingConstants.CENTER); + + add(noResultsTitle, BorderLayout.NORTH); + add(noResultsDescription, BorderLayout.CENTER); + + setVisible(false); + } + + /** + * Changes the content of the panel to the given parameters. + * The description has to be wrapped in html so that its text can be wrapped. + */ + public void setContent(String title, String description) + { + noResultsTitle.setText(title); + noResultsDescription.setText("" + description + ""); + setVisible(true); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/IconTextField.java b/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java similarity index 52% rename from runelite-client/src/main/java/net/runelite/client/plugins/hiscore/IconTextField.java rename to runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java index 055640de17..424e4ebebb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/hiscore/IconTextField.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/ThinProgressBar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Adam + * Copyright (c) 2018, Psikoi * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,54 +23,71 @@ * 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.plugins.hiscore; +package net.runelite.client.ui.components; -import java.awt.Graphics; -import java.awt.Insets; -import javax.swing.BorderFactory; -import javax.swing.Icon; -import javax.swing.JTextField; -import javax.swing.border.Border; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import javax.swing.JPanel; +import lombok.Setter; +import net.runelite.client.ui.ColorScheme; -public class IconTextField extends JTextField +/** + * A progress bar to be displayed underneath the GE offer item panels + */ +public class ThinProgressBar extends JPanel { - private Border border; - private Icon icon; + @Setter + private int maximumValue; - @Override - public void setBorder(Border border) + @Setter + private int value; + + private final JPanel topBar = new JPanel(); + + public ThinProgressBar() { - this.border = border; + setLayout(new BorderLayout()); + setBackground(Color.GREEN.darker()); - if (icon == null) + topBar.setPreferredSize(new Dimension(100, 4)); + topBar.setBackground(ColorScheme.PROGRESS_COMPLETE_COLOR); + + add(topBar, BorderLayout.WEST); + } + + /** + * Updates the UI based on the percentage progress + */ + public void update() + { + double percentage = getPercentage(); + int topWidth = (int) (getSize().width * (percentage / 100)); + + topBar.setPreferredSize(new Dimension(topWidth, 4)); + topBar.repaint(); + + revalidate(); + repaint(); + } + + public double getPercentage() + { + if (value == 0) { - super.setBorder(border); - } - else - { - Border margin = BorderFactory.createEmptyBorder(0, icon.getIconWidth() + 4, 0, 0); - Border compound = BorderFactory.createCompoundBorder(border, margin); - super.setBorder(compound); + return 0; } + + return (value * 100) / maximumValue; } @Override - public void paintComponent(Graphics graphics) + public void setForeground(Color color) { - super.paintComponent(graphics); - - Insets iconInsets = border.getBorderInsets(this); - icon.paintIcon(this, graphics, iconInsets.left, iconInsets.top); + if (topBar != null) + { + topBar.setBackground(color); + } + setBackground(color.darker()); } - - public void setIcon(Icon icon) - { - this.icon = icon; - resetBorder(); - } - - private void resetBorder() - { - setBorder(border); - } -} +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/materialtabs/MaterialTab.java b/runelite-client/src/main/java/net/runelite/client/ui/components/materialtabs/MaterialTab.java new file mode 100644 index 0000000000..692b9891bc --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/materialtabs/MaterialTab.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, Psikoi + * 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.components.materialtabs; + +import java.awt.Color; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import lombok.Getter; +import net.runelite.client.ui.ColorScheme; + +/** + * This class represents a Material Design inspired tab. + *

+ * Each tab will communicate with it's containing group when it's clicked + * and that group will display the tab's content on it's own display. + * + * @author Psikoi + */ +public class MaterialTab extends JLabel +{ + private static final Border SELECTED_BORDER = new CompoundBorder( + BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.BRAND_ORANGE), + BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + private static final Border UNSELECTED_BORDER = BorderFactory + .createEmptyBorder(5, 10, 5, 10); + + /* The tab's containing group */ + private final MaterialTabGroup group; + + /* The tab's associated content display */ + @Getter + private final JComponent content; + + @Getter + private boolean selected; + + public MaterialTab(String string, MaterialTabGroup group, JComponent content) + { + super(string); + + this.group = group; + this.content = content; + + if (selected) + { + select(); + } + else + { + unselect(); + } + + addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + group.select(MaterialTab.this); + } + }); + } + + public void select() + { + setBorder(SELECTED_BORDER); + setForeground(Color.WHITE); + selected = true; + } + + public void unselect() + { + setBorder(UNSELECTED_BORDER); + setForeground(Color.GRAY); + selected = false; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/materialtabs/MaterialTabGroup.java b/runelite-client/src/main/java/net/runelite/client/ui/components/materialtabs/MaterialTabGroup.java new file mode 100644 index 0000000000..5e50953523 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/materialtabs/MaterialTabGroup.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018, Psikoi + * 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.components.materialtabs; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; + +/** + * This class will be a container (group) for the new Material Tabs. It will + * contain a list of tabs and a display (JPanel). When a tab is selected, the + * JPanel "display" will display the content associated with that tab. + *

+ * How to use these tabs: + *

    + *
  1. 1 - Create displays (JPanels) for each tab
  2. + *
  3. 2 - Create an empty JPanel to serve as the group's display
  4. + *
  5. 3 - Create a new MaterialGroup, passing the panel in step 2 as a param
  6. + *
  7. 4 - Create new tabs, passing the group in step 3 and one of the panels in + * step 1 as params
  8. + *
  9. 5 - Add the tabs to the group using the MaterialTabGroup#addTab method
  10. + *
  11. 6 - Select one of the tabs using the MaterialTab#select method
  12. + *
+ * + * @author Psikoi + */ +public class MaterialTabGroup extends JPanel +{ + /* The panel on which the content tab's content will be displayed on. */ + private final JPanel display; + /* A list of all the tabs contained in this group. */ + private final List tabs = new ArrayList<>(); + + public MaterialTabGroup(JPanel display) + { + this.display = display; + this.display.setLayout(new BorderLayout()); + setLayout(new FlowLayout()); + setOpaque(false); + } + + public void addTab(MaterialTab tab) + { + tabs.add(tab); + add(tab, BorderLayout.NORTH); + } + + /*** + * Selects a tab from the group, and sets the display's content to the + * tab's associated content. + * @param selectedTab - The tab to select + */ + public boolean select(MaterialTab selectedTab) + { + if (!tabs.contains(selectedTab)) + { + return false; + } + + display.removeAll(); + + for (MaterialTab tab : tabs) + { + if (tab.equals(selectedTab)) + { + tab.select(); + display.add(tab.getContent()); + display.repaint(); + } + else + { + tab.unselect(); + } + } + + return true; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/ui/JShadowedLabel.java b/runelite-client/src/main/java/net/runelite/client/ui/components/shadowlabel/JShadowedLabel.java similarity index 97% rename from runelite-client/src/main/java/net/runelite/client/ui/JShadowedLabel.java rename to runelite-client/src/main/java/net/runelite/client/ui/components/shadowlabel/JShadowedLabel.java index 37182fb762..35ccf12374 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/JShadowedLabel.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/shadowlabel/JShadowedLabel.java @@ -22,7 +22,7 @@ * (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; +package net.runelite.client.ui.components.shadowlabel; import java.awt.Color; import java.awt.Point; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/JShadowedLabelUI.java b/runelite-client/src/main/java/net/runelite/client/ui/components/shadowlabel/JShadowedLabelUI.java similarity index 97% rename from runelite-client/src/main/java/net/runelite/client/ui/JShadowedLabelUI.java rename to runelite-client/src/main/java/net/runelite/client/ui/components/shadowlabel/JShadowedLabelUI.java index 0494b66d1f..32e59f4993 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/JShadowedLabelUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/components/shadowlabel/JShadowedLabelUI.java @@ -22,7 +22,7 @@ * (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; +package net.runelite.client.ui.components.shadowlabel; import java.awt.Graphics; import javax.swing.JLabel; diff --git a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java index b6a66a35d6..a83cd7e24e 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java @@ -60,6 +60,7 @@ import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE; import javax.swing.plaf.FontUIResource; import lombok.extern.slf4j.Slf4j; import net.runelite.client.ui.NavigationButton; +import net.runelite.client.ui.components.CustomScrollBarUI; import org.pushingpixels.substance.internal.SubstanceSynapse; import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities; @@ -82,6 +83,7 @@ public class SwingUtil UIManager.put("Button.foreground", Color.WHITE); UIManager.put("MenuItem.foreground", Color.WHITE); + UIManager.put("ScrollBarUI", CustomScrollBarUI.class.getName()); // Do not render shadows under popups/tooltips. // Fixes black boxes under popups that are above the game applet. diff --git a/runelite-client/src/main/resources/net/runelite/client/ui/components/error.png b/runelite-client/src/main/resources/net/runelite/client/ui/components/error.png new file mode 100644 index 0000000000..11048a6501 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/ui/components/error.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/ui/components/loading_spinner.gif b/runelite-client/src/main/resources/net/runelite/client/ui/components/loading_spinner.gif new file mode 100644 index 0000000000..81e7c2845d Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/ui/components/loading_spinner.gif differ diff --git a/runelite-client/src/main/resources/net/runelite/client/ui/components/loading_spinner_darker.gif b/runelite-client/src/main/resources/net/runelite/client/ui/components/loading_spinner_darker.gif new file mode 100644 index 0000000000..e44fcdab65 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/ui/components/loading_spinner_darker.gif differ diff --git a/runelite-client/src/main/resources/net/runelite/client/ui/components/search.png b/runelite-client/src/main/resources/net/runelite/client/ui/components/search.png new file mode 100644 index 0000000000..e68566fe4d Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/ui/components/search.png differ diff --git a/runelite-client/src/main/resources/net/runelite/client/ui/components/search_darker.png b/runelite-client/src/main/resources/net/runelite/client/ui/components/search_darker.png new file mode 100644 index 0000000000..0d5d4608a6 Binary files /dev/null and b/runelite-client/src/main/resources/net/runelite/client/ui/components/search_darker.png differ