Allow titlebar buttons to be moved out of the titlebar
This commit is contained in:
@@ -40,6 +40,7 @@ public class RuneLiteProperties
|
||||
private static final String RUNELITE_VERSION = "runelite.version";
|
||||
private static final String RUNESCAPE_VERSION = "runescape.version";
|
||||
private static final String DISCORD_APP_ID = "runelite.discord.appid";
|
||||
private static final String DISCORD_INVITE = "runelite.discord.invite";
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
@@ -76,4 +77,9 @@ public class RuneLiteProperties
|
||||
{
|
||||
return properties.getProperty(DISCORD_APP_ID);
|
||||
}
|
||||
|
||||
public String getDiscordInvite()
|
||||
{
|
||||
return properties.getProperty(DISCORD_INVITE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,15 @@ import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.awt.Font;
|
||||
import com.google.inject.Inject;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.LayoutStyle;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
@@ -40,6 +44,9 @@ import net.runelite.api.events.SessionClose;
|
||||
import net.runelite.api.events.SessionOpen;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import net.runelite.client.account.SessionManager;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.events.ClientUILoaded;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import net.runelite.client.util.RunnableExceptionLogger;
|
||||
@@ -53,6 +60,12 @@ public class InfoPanel extends PluginPanel
|
||||
@Nullable
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientUI clientUI;
|
||||
|
||||
@Inject
|
||||
private RuneLiteConfig runeliteConfig;
|
||||
|
||||
@Inject
|
||||
private RuneLiteProperties runeLiteProperties;
|
||||
|
||||
@@ -67,6 +80,8 @@ public class InfoPanel extends PluginPanel
|
||||
|
||||
private final GroupLayout layout = new GroupLayout(this);
|
||||
|
||||
private final JPanel toolbarPanelPlaceholder = new JPanel();
|
||||
|
||||
private final JLabel usernameHeader = new JLabel();
|
||||
private final JRichTextPane username = new JRichTextPane();
|
||||
|
||||
@@ -76,6 +91,8 @@ public class InfoPanel extends PluginPanel
|
||||
|
||||
final Font smallFont = FontManager.getRunescapeSmallFont();
|
||||
|
||||
toolbarPanelPlaceholder.setVisible(false);
|
||||
|
||||
final JLabel runeliteVersionHeader = new JLabel("RuneLite version");
|
||||
runeliteVersionHeader.setFont(smallFont);
|
||||
final JLabel runeliteVersion = new JLabel(runeLiteProperties.getVersion());
|
||||
@@ -112,7 +129,11 @@ public class InfoPanel extends PluginPanel
|
||||
+ "</a>"
|
||||
);
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 6, 6, 6));
|
||||
|
||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
||||
.addComponent(toolbarPanelPlaceholder)
|
||||
.addGap(3)
|
||||
.addGroup(layout.createParallelGroup()
|
||||
.addComponent(runeliteVersionHeader)
|
||||
.addComponent(runescapeVersionHeader)
|
||||
@@ -130,6 +151,9 @@ public class InfoPanel extends PluginPanel
|
||||
|
||||
layout.setHorizontalGroup(layout.createParallelGroup()
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(toolbarPanelPlaceholder)
|
||||
).addGroup(layout.createSequentialGroup()
|
||||
.addComponent(runeliteVersionHeader)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(runescapeVersionHeader)
|
||||
@@ -154,7 +178,29 @@ public class InfoPanel extends PluginPanel
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onSessionOpen(SessionOpen sessionOpen)
|
||||
private void onClientUILoaded(ClientUILoaded e)
|
||||
{
|
||||
// Add the title toolbar to the infopanel if the custom chrome is disabled
|
||||
if (!runeliteConfig.enableCustomChrome())
|
||||
{
|
||||
try
|
||||
{
|
||||
SwingUtilities.invokeAndWait(() ->
|
||||
{
|
||||
JPanel toolbar = clientUI.getTitleToolbar();
|
||||
layout.replace(toolbarPanelPlaceholder, toolbar);
|
||||
toolbar.revalidate();
|
||||
});
|
||||
}
|
||||
catch (InterruptedException | InvocationTargetException ex)
|
||||
{
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionOpen(SessionOpen sessionOpen)
|
||||
{
|
||||
String name = sessionManager.getAccountSession().getUsername();
|
||||
if (name != null)
|
||||
|
||||
@@ -51,7 +51,6 @@ import java.util.regex.Pattern;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
@@ -69,7 +68,6 @@ import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.events.ClientUILoaded;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.screenshot.imgur.ImageUploadRequest;
|
||||
@@ -85,7 +83,6 @@ import okhttp3.MediaType;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Screenshot plugin"
|
||||
@@ -133,7 +130,6 @@ public class ScreenshotPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
// prior to UI loading this does nothing
|
||||
addButtonToTitleBar();
|
||||
}
|
||||
|
||||
@@ -143,12 +139,6 @@ public class ScreenshotPlugin extends Plugin
|
||||
removeButtonFromTitlebar();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void clientUiLoaded(ClientUILoaded e)
|
||||
{
|
||||
addButtonToTitleBar();
|
||||
}
|
||||
|
||||
private void addButtonToTitleBar()
|
||||
{
|
||||
try
|
||||
@@ -170,7 +160,7 @@ public class ScreenshotPlugin extends Plugin
|
||||
}
|
||||
});
|
||||
|
||||
clientUi.addButtonToTitleBar(titleBarButton, iconImage, invertedIconImage, 130);
|
||||
clientUi.getTitleToolbar().addButton(titleBarButton, iconImage, invertedIconImage);
|
||||
});
|
||||
}
|
||||
catch (IOException ex)
|
||||
@@ -183,14 +173,7 @@ public class ScreenshotPlugin extends Plugin
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
JComponent titleBar = SubstanceCoreUtilities.getTitlePaneComponent(clientUi);
|
||||
|
||||
if (titleBar != null)
|
||||
{
|
||||
titleBar.remove(titleBarButton);
|
||||
clientUi.revalidate();
|
||||
clientUi.repaint();
|
||||
}
|
||||
clientUi.getTitleToolbar().remove(titleBarButton);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@ 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;
|
||||
@@ -43,13 +41,9 @@ 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;
|
||||
@@ -69,7 +63,6 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel;
|
||||
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
||||
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
||||
import org.pushingpixels.substance.internal.utils.SubstanceTitlePaneUtilities;
|
||||
|
||||
@@ -78,7 +71,6 @@ 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;
|
||||
@@ -89,6 +81,9 @@ public class ClientUI extends JFrame
|
||||
private PluginToolbar pluginToolbar;
|
||||
private PluginPanel pluginPanel;
|
||||
|
||||
@Getter
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
static
|
||||
{
|
||||
BufferedImage icon = null;
|
||||
@@ -158,46 +153,29 @@ public class ClientUI extends JFrame
|
||||
if (customChrome)
|
||||
{
|
||||
getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
|
||||
|
||||
JComponent titleBar = SubstanceCoreUtilities.getTitlePaneComponent(this);
|
||||
titleToolbar.putClientProperty(SubstanceTitlePaneUtilities.EXTRA_COMPONENT_KIND, SubstanceTitlePaneUtilities.ExtraComponentKind.TRAILING);
|
||||
titleBar.add(titleToolbar);
|
||||
|
||||
// The title bar doesn't have a real layout manager, so we have to do it manually
|
||||
titleBar.addComponentListener(new ComponentAdapter()
|
||||
{
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e)
|
||||
{
|
||||
super.componentResized(e);
|
||||
final int width = titleToolbar.getPreferredSize().width;
|
||||
titleToolbar.setBounds(titleBar.getWidth() - 75 - width, 0, width, titleBar.getHeight());
|
||||
titleToolbar.revalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pack();
|
||||
revalidateMinimumSize();
|
||||
setLocationRelativeTo(getOwner());
|
||||
|
||||
if (customChrome)
|
||||
{
|
||||
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);
|
||||
toFront();
|
||||
requestFocus();
|
||||
@@ -217,44 +195,6 @@ 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();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
@@ -382,6 +322,8 @@ public class ClientUI extends JFrame
|
||||
pluginToolbar = new PluginToolbar(this);
|
||||
container.add(pluginToolbar);
|
||||
|
||||
titleToolbar = new TitleToolbar(properties);
|
||||
|
||||
add(container);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.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.BorderFactory;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
||||
|
||||
@Slf4j
|
||||
public class TitleToolbar extends JPanel
|
||||
{
|
||||
private static final int TITLEBAR_SIZE = 23;
|
||||
|
||||
@Getter
|
||||
private final GroupLayout.SequentialGroup horizontal;
|
||||
|
||||
@Getter
|
||||
private final GroupLayout.ParallelGroup vertical;
|
||||
|
||||
public TitleToolbar(RuneLiteProperties properties)
|
||||
{
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
|
||||
|
||||
horizontal = layout.createSequentialGroup();
|
||||
layout.setHorizontalGroup(horizontal);
|
||||
|
||||
vertical = layout.createParallelGroup();
|
||||
layout.setVerticalGroup(vertical);
|
||||
|
||||
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(properties.getDiscordInvite()).toURI());
|
||||
}
|
||||
catch (IOException | URISyntaxException ex)
|
||||
{
|
||||
log.warn("error opening browser", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addButton(discordButton, discordIcon, invertedIcon);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("unable to load discord button", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void addButton(JButton button, Image iconImage, Image invertedIconImage)
|
||||
{
|
||||
final int iconSize = TITLEBAR_SIZE - 6;
|
||||
ImageIcon icon = new ImageIcon(iconImage.getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH));
|
||||
ImageIcon invertedIcon = new ImageIcon(invertedIconImage.getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH));
|
||||
|
||||
button.setIcon(icon);
|
||||
button.setRolloverIcon(invertedIcon);
|
||||
button.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE);
|
||||
button.setFocusable(false);
|
||||
|
||||
horizontal.addGap(6);
|
||||
horizontal.addComponent(button, 0, TITLEBAR_SIZE, TITLEBAR_SIZE);
|
||||
vertical.addComponent(button, 0, TITLEBAR_SIZE, TITLEBAR_SIZE);
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
@@ -2,3 +2,4 @@ runelite.title=RuneLite
|
||||
runelite.version=${project.version}
|
||||
runescape.version=${rs.version}
|
||||
runelite.discord.appid=409416265891971072
|
||||
runelite.discord.invite=https://discord.gg/R4BQ8tU
|
||||
Reference in New Issue
Block a user