diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml index 78633aa483..80a21011a7 100644 --- a/runelite-client/pom.xml +++ b/runelite-client/pom.xml @@ -78,7 +78,7 @@ org.pushingpixels substance - 7.1.00-rc + 8.0.00-dev org.pushingpixels diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index 7756517b04..8e2f467351 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -30,19 +30,28 @@ import java.awt.AWTException; import java.awt.BorderLayout; import java.awt.Canvas; import java.awt.Cursor; +import java.awt.Desktop; import java.awt.Dimension; import java.awt.Frame; +import java.awt.Image; import java.awt.SystemTray; import java.awt.TrayIcon; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Enumeration; import javax.imageio.ImageIO; import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -59,13 +68,16 @@ import net.runelite.api.Client; import net.runelite.api.GameState; import net.runelite.client.RuneLiteProperties; import org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel; -import org.pushingpixels.substance.internal.ui.SubstanceRootPaneUI; +import org.pushingpixels.substance.internal.SubstanceSynapse; +import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities; +import org.pushingpixels.substance.internal.utils.SubstanceTitlePaneUtilities; @Slf4j public class ClientUI extends JFrame { private static final int PANEL_EXPANDED_WIDTH = PluginPanel.PANEL_WIDTH + PluginPanel.SCROLLBAR_WIDTH; private static final BufferedImage ICON; + private static final String DISCORD_INVITE = "https://discord.gg/R4BQ8tU"; @Getter private TrayIcon trayIcon; @@ -150,7 +162,36 @@ public class ClientUI extends JFrame setLocationRelativeTo(getOwner()); if (customChrome) { - new TitleBarPane(this.getRootPane(), (SubstanceRootPaneUI) this.getRootPane().getUI()).editTitleBar(this); + try + { + BufferedImage discordIcon = ImageIO.read(ClientUI.class.getResourceAsStream("discord.png")); + BufferedImage invertedIcon = ImageIO.read(ClientUI.class.getResourceAsStream("discord_inverted.png")); + + JButton discordButton = new JButton(); + discordButton.setToolTipText("Join Discord"); + discordButton.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + super.mouseClicked(e); + try + { + Desktop.getDesktop().browse(new URL(DISCORD_INVITE).toURI()); + } + catch (IOException | URISyntaxException ex) + { + log.warn("error opening browser", ex); + } + } + }); + + addButtonToTitleBar(discordButton, discordIcon, invertedIcon, 100); + } + catch (IOException ex) + { + log.warn("unable to load discord button", ex); + } } setVisible(true); @@ -172,6 +213,44 @@ public class ClientUI extends JFrame } } + public void addButtonToTitleBar(JButton button, Image iconImage, Image invertedIconImage, int xOffset) + { + JComponent titleBar = SubstanceCoreUtilities.getTitlePaneComponent(this); + + if (titleBar == null) + { + return; + } + + int size = titleBar.getHeight() - 6; + + ImageIcon icon = new ImageIcon(iconImage.getScaledInstance(size, size, Image.SCALE_SMOOTH)); + ImageIcon invertedIcon = new ImageIcon(invertedIconImage.getScaledInstance(size, size, Image.SCALE_SMOOTH)); + + button.setIcon(icon); + button.setRolloverIcon(invertedIcon); + button.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE); + button.putClientProperty(SubstanceTitlePaneUtilities.EXTRA_COMPONENT_KIND, SubstanceTitlePaneUtilities.ExtraComponentKind.TRAILING); + button.setFocusable(false); + button.setBounds(titleBar.getWidth() - xOffset, 2, + icon.getIconWidth() + 4, icon.getIconHeight() + 2); + + titleBar.addComponentListener(new ComponentAdapter() + { + @Override + public void componentResized(ComponentEvent e) + { + super.componentResized(e); + button.setBounds(titleBar.getWidth() - xOffset, 1, button.getWidth(), button.getHeight()); + } + }); + + titleBar.add(button); + + revalidate(); + repaint(); + } + private static void setUIFont(FontUIResource f) { final Enumeration keys = UIManager.getDefaults().keys(); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/TitleBarPane.java b/runelite-client/src/main/java/net/runelite/client/ui/TitleBarPane.java deleted file mode 100644 index c4002f9a20..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/ui/TitleBarPane.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017. l2- - * - * 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; - -import java.awt.Desktop; -import java.awt.Image; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import javax.imageio.ImageIO; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JFrame; -import javax.swing.JRootPane; -import lombok.extern.slf4j.Slf4j; -import org.pushingpixels.substance.api.SubstanceLookAndFeel; -import org.pushingpixels.substance.internal.ui.SubstanceRootPaneUI; -import org.pushingpixels.substance.internal.utils.SubstanceTitlePane; - -@Slf4j -public class TitleBarPane extends SubstanceTitlePane -{ - private static final String DISCORD_INVITE = "https://discord.gg/R4BQ8tU"; - - private BufferedImage discordIcon; - private BufferedImage invertedIcon; - - public TitleBarPane(JRootPane root, SubstanceRootPaneUI ui) - { - super(root, ui); - - try - { - discordIcon = ImageIO.read(ClientUI.class.getResourceAsStream("discord.png")); - invertedIcon = ImageIO.read(ClientUI.class.getResourceAsStream("discord_inverted.png")); - } - catch (IOException ex) - { - log.warn("unable to load discord icons", ex); - } - } - - public void editTitleBar(JFrame frame) - { - if (discordIcon == null || invertedIcon == null) - { - return; - } - - JComponent titleBar = SubstanceLookAndFeel.getTitlePaneComponent(frame); - - JButton discordButton = new JButton(); - int heigth = titleBar.getHeight() - 3; - int width = heigth; - int x = titleBar.getWidth() - 100; - int y = 1; - ImageIcon icon = new ImageIcon(discordIcon.getScaledInstance(width - 3, heigth - 3, Image.SCALE_SMOOTH)); - ImageIcon invIcon = new ImageIcon(invertedIcon.getScaledInstance(width - 3, heigth - 3, Image.SCALE_SMOOTH)); - - discordButton.setIcon(icon); - discordButton.setRolloverIcon(invIcon); - discordButton.putClientProperty("substancelaf.componentFlat", Boolean.TRUE); - discordButton.putClientProperty("substancelaf.internal.titlePane.extraComponentKind", ExtraComponentKind.TRAILING); - discordButton.setFocusable(false); - discordButton.setBounds(x, y, icon.getIconWidth() + 4, icon.getIconHeight() + 2); - discordButton.setToolTipText("Join Discord"); - - discordButton.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - super.mouseClicked(e); - try - { - Desktop.getDesktop().browse(new URL(DISCORD_INVITE).toURI()); - } - catch (IOException | URISyntaxException ex) - { - log.warn("error opening browser", ex); - } - } - }); - - titleBar.addComponentListener(new ComponentAdapter() - { - @Override - public void componentResized(ComponentEvent e) - { - super.componentResized(e); - discordButton.setBounds(titleBar.getWidth() - 100, y, discordButton.getWidth(), discordButton.getHeight()); - } - }); - - titleBar.add(discordButton); - } -}