Merge pull request #880 from deathbeam/cleanup-clientui
Cleanup ClientUI
This commit is contained in:
@@ -35,7 +35,6 @@ import java.applet.Applet;
|
||||
import java.io.File;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.SwingUtilities;
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -43,12 +42,11 @@ import net.runelite.api.Client;
|
||||
import net.runelite.client.account.SessionManager;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.discord.DiscordService;
|
||||
import net.runelite.client.events.ClientUILoaded;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.TitleToolbar;
|
||||
import net.runelite.client.ui.overlay.OverlayRenderer;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
@@ -66,9 +64,6 @@ public class RuneLite
|
||||
private static Injector injector;
|
||||
private static OptionSet options;
|
||||
|
||||
@Inject
|
||||
private RuneLiteProperties properties;
|
||||
|
||||
@Inject
|
||||
private PluginManager pluginManager;
|
||||
|
||||
@@ -90,17 +85,19 @@ public class RuneLite
|
||||
@Inject
|
||||
private SessionManager sessionManager;
|
||||
|
||||
@Inject
|
||||
private RuneLiteConfig runeliteConfig;
|
||||
|
||||
@Inject
|
||||
private DiscordService discordService;
|
||||
|
||||
@Inject
|
||||
private ClientSessionManager clientSessionManager;
|
||||
|
||||
@Inject
|
||||
private ClientUI clientUI;
|
||||
|
||||
@Inject
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
Client client;
|
||||
ClientUI gui;
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
@@ -147,8 +144,8 @@ public class RuneLite
|
||||
this.client = (Client) client;
|
||||
}
|
||||
|
||||
// Load swing UI
|
||||
SwingUtilities.invokeAndWait(() -> setGui(ClientUI.create(this, properties, client)));
|
||||
// Initialize UI
|
||||
clientUI.init(client);
|
||||
|
||||
// Initialize Discord service
|
||||
discordService.init();
|
||||
@@ -157,10 +154,10 @@ public class RuneLite
|
||||
configManager.load();
|
||||
|
||||
// Register event listeners
|
||||
eventBus.register(clientUI);
|
||||
eventBus.register(overlayRenderer);
|
||||
eventBus.register(menuManager);
|
||||
eventBus.register(chatMessageManager);
|
||||
eventBus.register(gui);
|
||||
eventBus.register(pluginManager);
|
||||
|
||||
// Tell the plugin manager if client is outdated or not
|
||||
@@ -183,28 +180,11 @@ public class RuneLite
|
||||
// Load the session, including saved configuration
|
||||
sessionManager.loadSession();
|
||||
|
||||
SwingUtilities.invokeAndWait(() ->
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
client.setSize(runeliteConfig.gameSize());
|
||||
client.setPreferredSize(runeliteConfig.gameSize());
|
||||
// Refresh title toolbar
|
||||
titleToolbar.refresh();
|
||||
|
||||
client.getParent().setPreferredSize(runeliteConfig.gameSize());
|
||||
client.getParent().setSize(runeliteConfig.gameSize());
|
||||
}
|
||||
|
||||
gui.showWithChrome(runeliteConfig.enableCustomChrome());
|
||||
|
||||
if (gui.isAlwaysOnTopSupported())
|
||||
{
|
||||
gui.setAlwaysOnTop(runeliteConfig.gameAlwaysOnTop());
|
||||
}
|
||||
|
||||
gui.setResizable(!runeliteConfig.lockWindowSize());
|
||||
});
|
||||
|
||||
eventBus.post(new ClientUILoaded());
|
||||
// Show UI after all plugins are loaded
|
||||
clientUI.show();
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
@@ -213,11 +193,6 @@ public class RuneLite
|
||||
discordService.close();
|
||||
}
|
||||
|
||||
public void setGui(ClientUI gui)
|
||||
{
|
||||
this.gui = gui;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setClient(Client client)
|
||||
{
|
||||
|
||||
@@ -41,7 +41,6 @@ import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.task.Scheduler;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.util.QueryRunner;
|
||||
|
||||
@Slf4j
|
||||
@@ -67,12 +66,6 @@ public class RuneLiteModule extends AbstractModule
|
||||
return runeLite.client;
|
||||
}
|
||||
|
||||
@Provides
|
||||
ClientUI provideClientUi(RuneLite runelite)
|
||||
{
|
||||
return runelite.gui;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RuneLiteConfig provideConfig(ConfigManager configManager)
|
||||
|
||||
@@ -60,16 +60,14 @@ public class SessionManager
|
||||
private final EventBus eventBus;
|
||||
private ConfigManager configManager;
|
||||
private ScheduledExecutorService executor;
|
||||
private final LinkBrowser browser;
|
||||
private final AccountClient loginClient = new AccountClient();
|
||||
|
||||
@Inject
|
||||
public SessionManager(ConfigManager configManager, EventBus eventBus, ScheduledExecutorService executor, LinkBrowser browser)
|
||||
public SessionManager(ConfigManager configManager, EventBus eventBus, ScheduledExecutorService executor)
|
||||
{
|
||||
this.configManager = configManager;
|
||||
this.eventBus = eventBus;
|
||||
this.executor = executor;
|
||||
this.browser = browser;
|
||||
eventBus.register(this);
|
||||
}
|
||||
|
||||
@@ -213,7 +211,7 @@ public class SessionManager
|
||||
openSession(new AccountSession(login.getUid(), Instant.now()));
|
||||
|
||||
// Navigate to login link
|
||||
browser.browse(login.getOauthUrl());
|
||||
LinkBrowser.browse(login.getOauthUrl());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
|
||||
@Value
|
||||
public class PluginToolbarButtonAdded
|
||||
{
|
||||
private NavigationButton button;
|
||||
private int index;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
|
||||
@Value
|
||||
public class PluginToolbarButtonRemoved
|
||||
{
|
||||
private NavigationButton button;
|
||||
private int index;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
|
||||
@Value
|
||||
public class TitleToolbarButtonAdded
|
||||
{
|
||||
private NavigationButton button;
|
||||
private int index;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.events;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
|
||||
@Value
|
||||
public class TitleToolbarButtonRemoved
|
||||
{
|
||||
private NavigationButton button;
|
||||
private int index;
|
||||
}
|
||||
@@ -25,22 +25,20 @@
|
||||
package net.runelite.client.plugins.account;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JOptionPane;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.SessionClose;
|
||||
import net.runelite.api.events.SessionOpen;
|
||||
import net.runelite.client.account.AccountSession;
|
||||
import net.runelite.client.account.SessionManager;
|
||||
import net.runelite.api.events.SessionOpen;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.TitleToolbar;
|
||||
import net.runelite.client.util.RunnableExceptionLogger;
|
||||
|
||||
@@ -55,13 +53,13 @@ public class AccountPlugin extends Plugin
|
||||
private SessionManager sessionManager;
|
||||
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
@Inject
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
private JButton loginButton;
|
||||
private JButton logoutButton;
|
||||
private NavigationButton loginButton;
|
||||
private NavigationButton logoutButton;
|
||||
|
||||
private static final BufferedImage LOGIN_IMAGE, LOGOUT_IMAGE;
|
||||
|
||||
@@ -84,47 +82,45 @@ public class AccountPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
loginButton = new JButton();
|
||||
loginButton.setToolTipText("Login");
|
||||
loginButton.addActionListener(this::loginClick);
|
||||
loginButton = NavigationButton.builder()
|
||||
.icon(LOGIN_IMAGE)
|
||||
.tooltip("Login")
|
||||
.onClick(this::loginClick)
|
||||
.build();
|
||||
|
||||
logoutButton = new JButton();
|
||||
logoutButton.setToolTipText("Logout");
|
||||
logoutButton.addActionListener(this::logoutClick);
|
||||
logoutButton = NavigationButton.builder()
|
||||
.icon(LOGOUT_IMAGE)
|
||||
.tooltip("Logout")
|
||||
.onClick(this::logoutClick)
|
||||
.build();
|
||||
|
||||
addAndRemoveButtons();
|
||||
}
|
||||
|
||||
private void addAndRemoveButtons()
|
||||
{
|
||||
TitleToolbar tb = ui.getTitleToolbar();
|
||||
tb.remove(loginButton);
|
||||
tb.remove(logoutButton);
|
||||
if (sessionManager.getAccountSession() == null)
|
||||
{
|
||||
tb.addButton(loginButton, LOGIN_IMAGE, LOGIN_IMAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
tb.addButton(logoutButton, LOGOUT_IMAGE, LOGOUT_IMAGE);
|
||||
}
|
||||
titleToolbar.removeNavigation(loginButton);
|
||||
titleToolbar.removeNavigation(logoutButton);
|
||||
titleToolbar.addNavigation(sessionManager.getAccountSession() == null
|
||||
? loginButton
|
||||
: logoutButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
ui.getTitleToolbar().remove(loginButton);
|
||||
ui.getTitleToolbar().remove(logoutButton);
|
||||
titleToolbar.removeNavigation(loginButton);
|
||||
titleToolbar.removeNavigation(logoutButton);
|
||||
}
|
||||
|
||||
private void loginClick(ActionEvent ae)
|
||||
private void loginClick()
|
||||
{
|
||||
executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
|
||||
}
|
||||
|
||||
private void logoutClick(ActionEvent ae)
|
||||
private void logoutClick()
|
||||
{
|
||||
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(ui,
|
||||
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null,
|
||||
"Are you sure you want to logout?", "Logout Confirmation",
|
||||
JOptionPane.YES_NO_OPTION))
|
||||
{
|
||||
|
||||
@@ -36,8 +36,8 @@ import net.runelite.client.events.PluginChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Configuration",
|
||||
@@ -47,7 +47,7 @@ import net.runelite.client.ui.NavigationButton;
|
||||
public class ConfigPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
@@ -75,18 +75,19 @@ public class ConfigPlugin extends Plugin
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("config_icon.png"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Configuration",
|
||||
icon,
|
||||
() -> configPanel);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("Configuration")
|
||||
.icon(icon)
|
||||
.panel(configPanel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
@@ -35,9 +35,9 @@ import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
|
||||
@PluginDescriptor(
|
||||
@@ -47,7 +47,7 @@ import net.runelite.client.ui.overlay.Overlay;
|
||||
public class DevToolsPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private DevToolsOverlay overlay;
|
||||
@@ -89,12 +89,13 @@ public class DevToolsPlugin extends Plugin
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("devtools_icon.png"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Developer Tools",
|
||||
icon,
|
||||
() -> panel);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("Developer Tools")
|
||||
.icon(icon)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
|
||||
font = FontManager.getRunescapeFont()
|
||||
.deriveFont(Font.BOLD, 16);
|
||||
@@ -103,7 +104,7 @@ public class DevToolsPlugin extends Plugin
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,19 +27,25 @@ package net.runelite.client.plugins.discord;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.imageio.ImageIO;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.discord.DiscordService;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.TitleToolbar;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Discord"
|
||||
@@ -55,9 +61,16 @@ public class DiscordPlugin extends Plugin
|
||||
@Inject
|
||||
private DiscordService discordService;
|
||||
|
||||
@Inject
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
@Inject
|
||||
private RuneLiteProperties properties;
|
||||
|
||||
private final DiscordState discordState = new DiscordState();
|
||||
private Map<Skill, Integer> skillExp = new HashMap<>();
|
||||
private boolean loggedIn = false;
|
||||
private NavigationButton discordButton;
|
||||
|
||||
@Provides
|
||||
private DiscordConfig provideConfig(ConfigManager configManager)
|
||||
@@ -68,12 +81,26 @@ public class DiscordPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
BufferedImage icon;
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("discord.png"));
|
||||
}
|
||||
|
||||
discordButton = NavigationButton.builder()
|
||||
.tooltip("Join Discord")
|
||||
.icon(icon)
|
||||
.onClick(() -> LinkBrowser.browse(properties.getDiscordInvite()))
|
||||
.build();
|
||||
|
||||
titleToolbar.addNavigation(discordButton);
|
||||
updateGameStatus(client.getGameState(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
titleToolbar.removeNavigation(discordButton);
|
||||
discordService.clearPresence();
|
||||
discordState.reset();
|
||||
}
|
||||
|
||||
@@ -120,13 +120,11 @@ class FeedPanel extends PluginPanel
|
||||
|
||||
private final FeedConfig config;
|
||||
private final Supplier<FeedResult> feedSupplier;
|
||||
private final LinkBrowser linkBrowser;
|
||||
|
||||
FeedPanel(FeedConfig config, Supplier<FeedResult> feedSupplier, LinkBrowser linkBrowser)
|
||||
FeedPanel(FeedConfig config, Supplier<FeedResult> feedSupplier)
|
||||
{
|
||||
this.config = config;
|
||||
this.feedSupplier = feedSupplier;
|
||||
this.linkBrowser = linkBrowser;
|
||||
}
|
||||
|
||||
void rebuildFeed()
|
||||
@@ -294,7 +292,7 @@ class FeedPanel extends PluginPanel
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
avatarAndRight.setBackground(hoverColor);
|
||||
linkBrowser.browse(item.getUrl());
|
||||
LinkBrowser.browse(item.getUrl());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -41,9 +41,8 @@ import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
import net.runelite.http.api.feed.FeedClient;
|
||||
import net.runelite.http.api.feed.FeedResult;
|
||||
|
||||
@@ -55,7 +54,7 @@ import net.runelite.http.api.feed.FeedResult;
|
||||
public class FeedPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private FeedConfig config;
|
||||
@@ -63,9 +62,6 @@ public class FeedPlugin extends Plugin
|
||||
@Inject
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
@Inject
|
||||
private LinkBrowser linkBrowser;
|
||||
|
||||
private FeedPanel feedPanel;
|
||||
private NavigationButton navButton;
|
||||
|
||||
@@ -86,7 +82,7 @@ public class FeedPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
feedPanel = new FeedPanel(config, feedSupplier, linkBrowser);
|
||||
feedPanel = new FeedPanel(config, feedSupplier);
|
||||
|
||||
BufferedImage icon;
|
||||
synchronized (ImageIO.class)
|
||||
@@ -94,20 +90,20 @@ public class FeedPlugin extends Plugin
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("icon.png"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"News Feed",
|
||||
icon,
|
||||
() -> feedPanel);
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("News Feed")
|
||||
.icon(icon)
|
||||
.panel(feedPanel)
|
||||
.build();
|
||||
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
executorService.submit(this::updateFeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
private void updateFeed()
|
||||
|
||||
@@ -45,10 +45,9 @@ import net.runelite.client.util.LinkBrowser;
|
||||
class GrandExchangeItemPanel extends JPanel
|
||||
{
|
||||
private static final NumberFormat NUMBER_FORMATTER = NumberFormat.getInstance();
|
||||
|
||||
private static final Dimension ICON_SIZE = new Dimension(32, 32);
|
||||
|
||||
GrandExchangeItemPanel(LinkBrowser linkBrowser, BufferedImage icon, String name, int itemID, int gePrice, Double
|
||||
GrandExchangeItemPanel(BufferedImage icon, String name, int itemID, int gePrice, Double
|
||||
haPrice)
|
||||
{
|
||||
BorderLayout layout = new BorderLayout();
|
||||
@@ -75,7 +74,7 @@ class GrandExchangeItemPanel extends JPanel
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
geLink(linkBrowser, name, itemID);
|
||||
geLink(name, itemID);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -125,13 +124,13 @@ class GrandExchangeItemPanel extends JPanel
|
||||
add(rightPanel, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private void geLink(LinkBrowser linkBrowser, String name, int itemID)
|
||||
private void geLink(String name, int itemID)
|
||||
{
|
||||
final String url = "http://services.runescape.com/m=itemdb_oldschool/"
|
||||
+ name.replaceAll(" ", "_")
|
||||
+ "/viewitem?obj="
|
||||
+ itemID;
|
||||
|
||||
linkBrowser.browse(url);
|
||||
LinkBrowser.browse(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.GrandExchangeOffer;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
|
||||
@Slf4j
|
||||
class GrandExchangePanel extends PluginPanel
|
||||
@@ -54,7 +53,7 @@ class GrandExchangePanel extends PluginPanel
|
||||
private JTabbedPane tabbedPane = new JTabbedPane();
|
||||
|
||||
@Inject
|
||||
GrandExchangePanel(Client client, ItemManager itemManager, ScheduledExecutorService executor, LinkBrowser linkBrowser)
|
||||
GrandExchangePanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
||||
{
|
||||
setLayout(new BorderLayout());
|
||||
add(tabbedPane, BorderLayout.NORTH);
|
||||
@@ -68,7 +67,7 @@ class GrandExchangePanel extends PluginPanel
|
||||
}
|
||||
|
||||
// Search Panel
|
||||
searchPanel = new GrandExchangeSearchPanel(client, itemManager, executor, linkBrowser);
|
||||
searchPanel = new GrandExchangeSearchPanel(client, itemManager, executor);
|
||||
|
||||
tabbedPane.addTab("Offers", offerPanel);
|
||||
tabbedPane.addTab("Search", searchPanel);
|
||||
|
||||
@@ -48,8 +48,8 @@ import net.runelite.client.input.MouseListener;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Grand Exchange"
|
||||
@@ -69,7 +69,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private GrandExchangeConfig config;
|
||||
@@ -84,13 +84,20 @@ public class GrandExchangePlugin extends Plugin
|
||||
protected void startUp() throws IOException
|
||||
{
|
||||
panel = injector.getInstance(GrandExchangePanel.class);
|
||||
|
||||
BufferedImage icon;
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("ge_icon.png"));
|
||||
}
|
||||
button = new NavigationButton("GE Offers", icon, () -> panel);
|
||||
ui.getPluginToolbar().addNavigation(button);
|
||||
|
||||
button = NavigationButton.builder()
|
||||
.name("GE Offers")
|
||||
.icon(icon)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
pluginToolbar.addNavigation(button);
|
||||
|
||||
itemClick = new MouseListener()
|
||||
{
|
||||
@@ -119,7 +126,8 @@ public class GrandExchangePlugin extends Plugin
|
||||
|
||||
if (!button.isSelected())
|
||||
{
|
||||
button.doClick();
|
||||
button.setSelected(true);
|
||||
button.getOnSelect().run();
|
||||
}
|
||||
|
||||
panel.getSearchPanel().priceLookup(itemComp.getName());
|
||||
@@ -145,8 +153,7 @@ public class GrandExchangePlugin extends Plugin
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(button);
|
||||
|
||||
pluginToolbar.removeNavigation(button);
|
||||
mouseManager.unregisterMouseListener(itemClick);
|
||||
}
|
||||
|
||||
@@ -172,10 +179,6 @@ public class GrandExchangePlugin extends Plugin
|
||||
@Subscribe
|
||||
public void onGrandExchangeOfferChanged(GrandExchangeOfferChanged offerEvent)
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
panel.updateOffer(offerEvent.getOffer(), offerEvent.getSlot());
|
||||
});
|
||||
SwingUtilities.invokeLater(() -> panel.updateOffer(offerEvent.getOffer(), offerEvent.getSlot()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.hiscore.IconTextField;
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
import net.runelite.http.api.item.Item;
|
||||
import net.runelite.http.api.item.ItemClient;
|
||||
import net.runelite.http.api.item.ItemPrice;
|
||||
@@ -60,7 +59,6 @@ class GrandExchangeSearchPanel extends JPanel
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
private final ScheduledExecutorService executor;
|
||||
private final LinkBrowser linkBrowser;
|
||||
|
||||
private ItemClient itemClient;
|
||||
|
||||
@@ -71,12 +69,11 @@ class GrandExchangeSearchPanel extends JPanel
|
||||
private JPanel searchItemsPanel = new JPanel();
|
||||
private JLabel searchingLabel = new JLabel();
|
||||
|
||||
GrandExchangeSearchPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor, LinkBrowser linkBrowser)
|
||||
GrandExchangeSearchPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
||||
{
|
||||
this.client = client;
|
||||
this.itemManager = itemManager;
|
||||
this.executor = executor;
|
||||
this.linkBrowser = linkBrowser;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -203,7 +200,7 @@ class GrandExchangeSearchPanel extends JPanel
|
||||
{
|
||||
for (GrandExchangeItems item : ITEMS_LIST)
|
||||
{
|
||||
GrandExchangeItemPanel panel = new GrandExchangeItemPanel(linkBrowser, item.getIcon(), item.getName(),
|
||||
GrandExchangeItemPanel panel = new GrandExchangeItemPanel(item.getIcon(), item.getName(),
|
||||
item.getItemId(), item.getGePrice(), item.getHaPrice());
|
||||
|
||||
searchItemsPanel.add(panel);
|
||||
|
||||
@@ -38,8 +38,8 @@ import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "HiScore",
|
||||
@@ -50,7 +50,7 @@ public class HiscorePlugin extends Plugin
|
||||
private static final String LOOKUP = "Lookup";
|
||||
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private MenuManager menuManager;
|
||||
@@ -81,12 +81,13 @@ public class HiscorePlugin extends Plugin
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("hiscore.gif"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Hiscore",
|
||||
icon,
|
||||
() -> hiscorePanel);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("Hiscore")
|
||||
.icon(icon)
|
||||
.panel(hiscorePanel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
|
||||
if (config.playerOption())
|
||||
{
|
||||
@@ -97,8 +98,7 @@ public class HiscorePlugin extends Plugin
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
menuManager.removePlayerMenuItem(LOOKUP);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,8 @@ public class HiscorePlugin extends Plugin
|
||||
{
|
||||
if (!navButton.isSelected())
|
||||
{
|
||||
navButton.doClick();
|
||||
navButton.setSelected(true);
|
||||
navButton.getOnSelect().run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,15 +26,15 @@ package net.runelite.client.plugins.info;
|
||||
|
||||
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.awt.Font;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.LayoutStyle;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
@@ -46,23 +46,25 @@ 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.events.TitleToolbarButtonAdded;
|
||||
import net.runelite.client.events.TitleToolbarButtonRemoved;
|
||||
import net.runelite.client.ui.ClientTitleToolbar;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import net.runelite.client.util.RunnableExceptionLogger;
|
||||
import net.runelite.client.util.SwingUtil;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class InfoPanel extends PluginPanel
|
||||
{
|
||||
private final static String RUNELITE_LOGIN = "https://runelite_login/";
|
||||
private static final int TITLEBAR_SIZE = 23;
|
||||
private static final String RUNELITE_LOGIN = "https://runelite_login/";
|
||||
|
||||
@Inject
|
||||
@Nullable
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientUI clientUI;
|
||||
|
||||
@Inject
|
||||
private RuneLiteConfig runeliteConfig;
|
||||
|
||||
@@ -79,9 +81,7 @@ public class InfoPanel extends PluginPanel
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
private final GroupLayout layout = new GroupLayout(this);
|
||||
|
||||
private final JPanel toolbarPanelPlaceholder = new JPanel();
|
||||
|
||||
private final ClientTitleToolbar titleBar = new ClientTitleToolbar();
|
||||
private final JLabel usernameHeader = new JLabel();
|
||||
private final JRichTextPane username = new JRichTextPane();
|
||||
|
||||
@@ -90,8 +90,7 @@ public class InfoPanel extends PluginPanel
|
||||
setLayout(layout);
|
||||
|
||||
final Font smallFont = FontManager.getRunescapeSmallFont();
|
||||
|
||||
toolbarPanelPlaceholder.setVisible(false);
|
||||
updateTitleBar();
|
||||
|
||||
final JLabel runeliteVersionHeader = new JLabel("RuneLite version");
|
||||
runeliteVersionHeader.setFont(smallFont);
|
||||
@@ -119,7 +118,8 @@ public class InfoPanel extends PluginPanel
|
||||
}
|
||||
}
|
||||
});
|
||||
setNotLoggedIn();
|
||||
|
||||
updateLoggedIn();
|
||||
|
||||
final JRichTextPane issueLink = new JRichTextPane("text/html",
|
||||
"RuneLite is open source!<br>"
|
||||
@@ -132,7 +132,7 @@ public class InfoPanel extends PluginPanel
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 6, 6, 6));
|
||||
|
||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
||||
.addComponent(toolbarPanelPlaceholder)
|
||||
.addComponent(titleBar)
|
||||
.addGap(3)
|
||||
.addGroup(layout.createParallelGroup()
|
||||
.addComponent(runeliteVersionHeader)
|
||||
@@ -152,16 +152,15 @@ 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(titleBar))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(runeliteVersionHeader)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(runescapeVersionHeader)
|
||||
).addGroup(layout.createSequentialGroup()
|
||||
.addComponent(runescapeVersionHeader))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(runeliteVersion)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(runescapeVersion)
|
||||
)
|
||||
.addComponent(runescapeVersion))
|
||||
.addComponent(usernameHeader)
|
||||
.addComponent(username)
|
||||
.addComponent(issueLink)
|
||||
@@ -170,50 +169,81 @@ public class InfoPanel extends PluginPanel
|
||||
eventBus.register(this);
|
||||
}
|
||||
|
||||
private void setNotLoggedIn()
|
||||
private void updateLoggedIn()
|
||||
{
|
||||
username.setContentType("text/html");
|
||||
username.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud.");
|
||||
usernameHeader.setText("Not logged in");
|
||||
}
|
||||
final String name = sessionManager.getAccountSession() != null
|
||||
? sessionManager.getAccountSession().getUsername()
|
||||
: null;
|
||||
|
||||
@Subscribe
|
||||
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)
|
||||
{
|
||||
username.setContentType("text/plain");
|
||||
username.setText(name);
|
||||
usernameHeader.setText("Logged in as");
|
||||
}
|
||||
else
|
||||
{
|
||||
username.setContentType("text/html");
|
||||
username.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud.");
|
||||
usernameHeader.setText("Not logged in");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTitleBar()
|
||||
{
|
||||
titleBar.setVisible(!runeliteConfig.enableCustomChrome());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onSessionClose(SessionClose e)
|
||||
public void onClientUILoaded(ClientUILoaded e)
|
||||
{
|
||||
setNotLoggedIn();
|
||||
// Add the title toolbar to the infopanel if the custom chrome is disabled
|
||||
updateTitleBar();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionOpen(SessionOpen sessionOpen)
|
||||
{
|
||||
updateLoggedIn();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSessionClose(SessionClose e)
|
||||
{
|
||||
updateLoggedIn();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onTitleToolbarButtonAdded(TitleToolbarButtonAdded event)
|
||||
{
|
||||
if (runeliteConfig.enableCustomChrome())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
final int iconSize = TITLEBAR_SIZE - 6;
|
||||
final JButton button = SwingUtil.createSwingButton(event.getButton(), iconSize, null);
|
||||
titleBar.addComponent(event.getButton(), button);
|
||||
titleBar.revalidate();
|
||||
titleBar.repaint();
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onTitleToolbarButtonRemoved(TitleToolbarButtonRemoved event)
|
||||
{
|
||||
if (runeliteConfig.enableCustomChrome())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
titleBar.removeComponent(event.getButton());
|
||||
titleBar.revalidate();
|
||||
titleBar.repaint();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,12 @@ package net.runelite.client.plugins.info;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
import net.runelite.client.ui.TitleToolbar;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Info Panel",
|
||||
@@ -39,7 +41,13 @@ import net.runelite.client.ui.NavigationButton;
|
||||
public class InfoPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
@Inject
|
||||
private RuneLiteConfig runeLiteConfig;
|
||||
|
||||
private NavigationButton navButton;
|
||||
|
||||
@@ -55,18 +63,23 @@ public class InfoPlugin extends Plugin
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("info_icon.png"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Info",
|
||||
icon,
|
||||
() -> panel
|
||||
);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("Info")
|
||||
.icon(icon)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
|
||||
if (!runeLiteConfig.enableCustomChrome())
|
||||
{
|
||||
titleToolbar.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
|
||||
@PluginDescriptor(
|
||||
@@ -57,7 +57,7 @@ public class KourendLibraryPlugin extends Plugin
|
||||
final static boolean debug = false;
|
||||
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@@ -86,19 +86,19 @@ public class KourendLibraryPlugin extends Plugin
|
||||
icon = ImageIO.read(Book.class.getResourceAsStream("panel_icon.png"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Kourend Library",
|
||||
icon,
|
||||
() -> panel
|
||||
);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("Kourend Library")
|
||||
.icon(icon)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,19 +24,18 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.notes;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.SessionOpen;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Notes",
|
||||
@@ -46,7 +45,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class NotesPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private NotesConfig config;
|
||||
@@ -72,19 +71,19 @@ public class NotesPlugin extends Plugin
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("notes_icon.png"));
|
||||
}
|
||||
|
||||
navButton = new NavigationButton(
|
||||
"Notes",
|
||||
icon,
|
||||
() -> panel
|
||||
);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("Notes")
|
||||
.icon(icon)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
@@ -25,19 +25,17 @@
|
||||
package net.runelite.client.plugins.screenshot;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -52,10 +50,6 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
@@ -80,6 +74,8 @@ import net.runelite.client.plugins.screenshot.imgur.ImageUploadRequest;
|
||||
import net.runelite.client.plugins.screenshot.imgur.ImageUploadResponse;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.TitleToolbar;
|
||||
import net.runelite.client.ui.overlay.OverlayRenderer;
|
||||
import net.runelite.client.util.Text;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
@@ -125,13 +121,16 @@ public class ScreenshotPlugin extends Plugin
|
||||
@Inject
|
||||
private ClientUI clientUi;
|
||||
|
||||
@Inject
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
@Inject
|
||||
private OverlayRenderer overlayRenderer;
|
||||
|
||||
@Inject
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
private JButton titleBarButton;
|
||||
private NavigationButton titleBarButton;
|
||||
|
||||
@Provides
|
||||
ScreenshotConfig getConfig(ConfigManager configManager)
|
||||
@@ -141,66 +140,39 @@ public class ScreenshotPlugin extends Plugin
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
addButtonToTitleBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
removeButtonFromTitlebar();
|
||||
}
|
||||
|
||||
private void addButtonToTitleBar()
|
||||
{
|
||||
try
|
||||
{
|
||||
BufferedImage iconImage;
|
||||
BufferedImage invertedIconImage;
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
iconImage = ImageIO.read(ScreenshotPlugin.class.getResourceAsStream("screenshot.png"));
|
||||
invertedIconImage = ImageIO.read(ScreenshotPlugin.class.getResourceAsStream("screenshot_inverted.png"));
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
titleBarButton = new JButton();
|
||||
titleBarButton.setToolTipText("Take screenshot");
|
||||
titleBarButton.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
titleBarButton = NavigationButton.builder()
|
||||
.tooltip("Take screenshot")
|
||||
.icon(iconImage)
|
||||
.onClick(() -> takeScreenshot(
|
||||
TIME_FORMAT.format(new Date()),
|
||||
client.getLocalPlayer() != null))
|
||||
.popup(ImmutableMap
|
||||
.<String, Runnable>builder()
|
||||
.put("Open screenshot folder...", () ->
|
||||
{
|
||||
super.mouseClicked(e);
|
||||
|
||||
if (SwingUtilities.isLeftMouseButton(e))
|
||||
try
|
||||
{
|
||||
takeScreenshot(TIME_FORMAT.format(new Date()), client.getLocalPlayer() != null);
|
||||
Desktop.getDesktop().open(RuneLite.SCREENSHOT_DIR);
|
||||
}
|
||||
}
|
||||
});
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("Error opening screenshot dir", ex);
|
||||
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
}
|
||||
})
|
||||
.build())
|
||||
.build();
|
||||
|
||||
JMenuItem folderItem = new JMenuItem("Open screenshot folder...");
|
||||
folderItem.addActionListener(e ->
|
||||
{
|
||||
try
|
||||
{
|
||||
Desktop.getDesktop().open(RuneLite.SCREENSHOT_DIR);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("Error opening screenshot directory", ex);
|
||||
}
|
||||
});
|
||||
popupMenu.add(folderItem);
|
||||
|
||||
titleBarButton.setComponentPopupMenu(popupMenu);
|
||||
|
||||
clientUi.getTitleToolbar().addButton(titleBarButton, iconImage, invertedIconImage);
|
||||
});
|
||||
titleToolbar.addNavigation(titleBarButton);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
@@ -208,12 +180,10 @@ public class ScreenshotPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private void removeButtonFromTitlebar()
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
clientUi.getTitleToolbar().remove(titleBarButton);
|
||||
});
|
||||
titleToolbar.removeNavigation(titleBarButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -410,9 +380,8 @@ public class ScreenshotPlugin extends Plugin
|
||||
clientUi.paint(graphics);
|
||||
|
||||
// Evaluate the position of the game inside the frame
|
||||
Point gamePoint = SwingUtilities.convertPoint(client.getCanvas(), 0, 0, clientUi);
|
||||
gameOffsetX = gamePoint.x;
|
||||
gameOffsetY = gamePoint.y;
|
||||
gameOffsetX = 6;
|
||||
gameOffsetY = 0;
|
||||
}
|
||||
|
||||
// Draw the game onto the screenshot
|
||||
|
||||
@@ -47,8 +47,8 @@ import net.runelite.client.game.SkillIconManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import static net.runelite.client.plugins.xptracker.XpWorldType.NORMAL;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.PluginToolbar;
|
||||
import net.runelite.http.api.worlds.World;
|
||||
import net.runelite.http.api.worlds.WorldClient;
|
||||
import net.runelite.http.api.worlds.WorldResult;
|
||||
@@ -62,7 +62,7 @@ import net.runelite.http.api.xp.XpClient;
|
||||
public class XpTrackerPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private ClientUI ui;
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@@ -104,25 +104,27 @@ public class XpTrackerPlugin extends Plugin
|
||||
log.warn("Error looking up worlds list", e);
|
||||
}
|
||||
|
||||
xpPanel = new XpPanel(this, client, skillIconManager);
|
||||
|
||||
BufferedImage icon;
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
icon = ImageIO.read(getClass().getResourceAsStream("xp.png"));
|
||||
}
|
||||
|
||||
xpPanel = new XpPanel(this, client, skillIconManager);
|
||||
navButton = new NavigationButton(
|
||||
"XP Tracker",
|
||||
icon,
|
||||
() -> xpPanel);
|
||||
navButton = NavigationButton.builder()
|
||||
.name("XP Tracker")
|
||||
.icon(icon)
|
||||
.panel(xpPanel)
|
||||
.build();
|
||||
|
||||
ui.getPluginToolbar().addNavigation(navButton);
|
||||
pluginToolbar.addNavigation(navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
ui.getPluginToolbar().removeNavigation(navButton);
|
||||
pluginToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.swing.JToolBar;
|
||||
|
||||
/**
|
||||
* Client plugin toolbar.
|
||||
*/
|
||||
public class ClientPluginToolbar extends JToolBar
|
||||
{
|
||||
private static final int TOOLBAR_WIDTH = 36, TOOLBAR_HEIGHT = 503;
|
||||
private final Map<NavigationButton, Component> componentMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Instantiates a new Client plugin toolbar.
|
||||
*/
|
||||
ClientPluginToolbar()
|
||||
{
|
||||
super(JToolBar.VERTICAL);
|
||||
setFloatable(false);
|
||||
setSize(new Dimension(TOOLBAR_WIDTH, TOOLBAR_HEIGHT));
|
||||
setMinimumSize(new Dimension(TOOLBAR_WIDTH, TOOLBAR_HEIGHT));
|
||||
setPreferredSize(new Dimension(TOOLBAR_WIDTH, TOOLBAR_HEIGHT));
|
||||
setMaximumSize(new Dimension(TOOLBAR_WIDTH, Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
public void addComponent(final int index, final NavigationButton button, final Component component)
|
||||
{
|
||||
if (componentMap.put(button, component) == null)
|
||||
{
|
||||
add(component, index);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeComponent(final NavigationButton button)
|
||||
{
|
||||
final Component component = componentMap.remove(button);
|
||||
|
||||
if (component != null)
|
||||
{
|
||||
remove(component);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.LayoutManager2;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/**
|
||||
* Client title toolbar component.
|
||||
*/
|
||||
public class ClientTitleToolbar extends JPanel
|
||||
{
|
||||
public static final int TITLEBAR_SIZE = 23;
|
||||
private static final int ITEM_PADDING = 4;
|
||||
|
||||
private final Map<NavigationButton, Component> componentMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Instantiates a new Client title toolbar.
|
||||
*/
|
||||
public ClientTitleToolbar()
|
||||
{
|
||||
// The only other layout manager that would manage it's preferred size without padding
|
||||
// was the GroupLayout manager, which doesn't work with dynamic layouts like this one.
|
||||
// Primarily, it would not remove components unless it was immediately repainted.
|
||||
setLayout(new LayoutManager2()
|
||||
{
|
||||
@Override
|
||||
public void addLayoutComponent(String name, Component comp)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLayoutComponent(Component comp, Object constraints)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLayoutComponent(Component comp)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent)
|
||||
{
|
||||
int width = parent.getComponentCount() * (TITLEBAR_SIZE + ITEM_PADDING);
|
||||
return new Dimension(width, TITLEBAR_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize(Container parent)
|
||||
{
|
||||
return preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension maximumLayoutSize(Container parent)
|
||||
{
|
||||
return preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLayoutAlignmentX(Container target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLayoutAlignmentY(Container target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateLayout(Container target)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent)
|
||||
{
|
||||
int x = 0;
|
||||
for (Component c : parent.getComponents())
|
||||
{
|
||||
x += ITEM_PADDING;
|
||||
int height = c.getPreferredSize().height;
|
||||
if (height > TITLEBAR_SIZE)
|
||||
{
|
||||
height = TITLEBAR_SIZE;
|
||||
}
|
||||
c.setBounds(x, (TITLEBAR_SIZE - height) / 2, TITLEBAR_SIZE, height);
|
||||
x += TITLEBAR_SIZE;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addComponent(NavigationButton button, Component c)
|
||||
{
|
||||
if (componentMap.put(button, c) == null)
|
||||
{
|
||||
add(c);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeComponent(NavigationButton button)
|
||||
{
|
||||
final Component component = componentMap.remove(button);
|
||||
if (component != null)
|
||||
{
|
||||
remove(component);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,40 +24,32 @@
|
||||
*/
|
||||
package net.runelite.client.ui;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.applet.Applet;
|
||||
import java.awt.AWTException;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
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.util.Enumeration;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.plaf.FontUIResource;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
@@ -65,31 +57,29 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.events.ClientUILoaded;
|
||||
import net.runelite.client.events.PluginToolbarButtonAdded;
|
||||
import net.runelite.client.events.PluginToolbarButtonRemoved;
|
||||
import net.runelite.client.events.TitleToolbarButtonAdded;
|
||||
import net.runelite.client.events.TitleToolbarButtonRemoved;
|
||||
import net.runelite.client.util.OSType;
|
||||
import net.runelite.client.util.OSXUtil;
|
||||
import net.runelite.client.util.SwingUtil;
|
||||
import org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel;
|
||||
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
||||
import org.pushingpixels.substance.internal.utils.SubstanceTitlePaneUtilities;
|
||||
|
||||
/**
|
||||
* Client UI.
|
||||
*/
|
||||
@Slf4j
|
||||
public class ClientUI extends JFrame
|
||||
@Singleton
|
||||
public class ClientUI
|
||||
{
|
||||
private static final int PANEL_EXPANDED_WIDTH = PluginPanel.PANEL_WIDTH + PluginPanel.SCROLLBAR_WIDTH;
|
||||
public static final BufferedImage ICON;
|
||||
|
||||
@Getter
|
||||
private TrayIcon trayIcon;
|
||||
|
||||
private final RuneLite runelite;
|
||||
private final Applet client;
|
||||
private final RuneLiteProperties properties;
|
||||
private JPanel navContainer;
|
||||
private PluginToolbar pluginToolbar;
|
||||
private PluginPanel pluginPanel;
|
||||
|
||||
@Getter
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
static
|
||||
{
|
||||
BufferedImage icon = null;
|
||||
@@ -109,129 +99,39 @@ public class ClientUI extends JFrame
|
||||
ICON = icon;
|
||||
}
|
||||
|
||||
public static ClientUI create(RuneLite runelite, RuneLiteProperties properties, Applet client)
|
||||
{
|
||||
// Force heavy-weight popups/tooltips.
|
||||
// Prevents them from being obscured by the game applet.
|
||||
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
|
||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||
@Getter
|
||||
private TrayIcon trayIcon;
|
||||
|
||||
// Do not render shadows under popups/tooltips.
|
||||
// Fixes black boxes under popups that are above the game applet.
|
||||
System.setProperty("jgoodies.popupDropShadowEnabled", "false");
|
||||
private final RuneLite runelite;
|
||||
private final RuneLiteProperties properties;
|
||||
private final RuneLiteConfig config;
|
||||
private final EventBus eventBus;
|
||||
private Applet client;
|
||||
private JFrame frame;
|
||||
private JPanel navContainer;
|
||||
private PluginPanel pluginPanel;
|
||||
private ClientPluginToolbar pluginToolbar;
|
||||
private ClientTitleToolbar titleToolbar;
|
||||
private JButton currentButton;
|
||||
|
||||
// Do not fill in background on repaint. Reduces flickering when
|
||||
// the applet is resized.
|
||||
System.setProperty("sun.awt.noerasebackground", "true");
|
||||
|
||||
// Use substance look and feel
|
||||
try
|
||||
{
|
||||
UIManager.setLookAndFeel(new SubstanceGraphiteLookAndFeel());
|
||||
}
|
||||
catch (UnsupportedLookAndFeelException ex)
|
||||
{
|
||||
log.warn("unable to set look and feel", ex);
|
||||
}
|
||||
|
||||
// Use custom UI font
|
||||
setUIFont(new FontUIResource(FontManager.getRunescapeFont()));
|
||||
|
||||
ClientUI gui = new ClientUI(runelite, properties, client);
|
||||
OSXUtil.tryEnableFullscreen(gui);
|
||||
return gui;
|
||||
}
|
||||
|
||||
private ClientUI(RuneLite runelite, RuneLiteProperties properties, Applet client)
|
||||
@Inject
|
||||
private ClientUI(
|
||||
RuneLite runelite,
|
||||
RuneLiteProperties properties,
|
||||
RuneLiteConfig config,
|
||||
EventBus eventBus)
|
||||
{
|
||||
this.runelite = runelite;
|
||||
this.properties = properties;
|
||||
this.client = client;
|
||||
this.trayIcon = setupTrayIcon();
|
||||
|
||||
init();
|
||||
setTitle(properties.getTitle());
|
||||
setIconImage(ICON);
|
||||
// Prevent substance from using a resize cursor for pointing
|
||||
getLayeredPane().setCursor(Cursor.getDefaultCursor());
|
||||
setLocationRelativeTo(getOwner());
|
||||
setResizable(true);
|
||||
}
|
||||
|
||||
public void showWithChrome(boolean customChrome)
|
||||
{
|
||||
setUndecorated(customChrome);
|
||||
|
||||
if (customChrome)
|
||||
{
|
||||
getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
|
||||
|
||||
JComponent titleBar = SubstanceCoreUtilities.getTitlePaneComponent(this);
|
||||
titleToolbar.putClientProperty(SubstanceTitlePaneUtilities.EXTRA_COMPONENT_KIND, SubstanceTitlePaneUtilities.ExtraComponentKind.TRAILING);
|
||||
titleBar.add(titleToolbar);
|
||||
|
||||
// Substance's default layout manager for the title bar only lays out substance's components
|
||||
// This wraps the default manager and lays out the TitleToolbar as well.
|
||||
LayoutManager delegate = titleBar.getLayout();
|
||||
titleBar.setLayout(new LayoutManager()
|
||||
{
|
||||
@Override
|
||||
public void addLayoutComponent(String name, Component comp)
|
||||
{
|
||||
delegate.addLayoutComponent(name, comp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLayoutComponent(Component comp)
|
||||
{
|
||||
delegate.removeLayoutComponent(comp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent)
|
||||
{
|
||||
return delegate.preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize(Container parent)
|
||||
{
|
||||
return delegate.minimumLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent)
|
||||
{
|
||||
delegate.layoutContainer(parent);
|
||||
final int width = titleToolbar.getPreferredSize().width;
|
||||
titleToolbar.setBounds(titleBar.getWidth() - 75 - width, 0, width, titleBar.getHeight());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pack();
|
||||
revalidateMinimumSize();
|
||||
setLocationRelativeTo(getOwner());
|
||||
|
||||
setVisible(true);
|
||||
toFront();
|
||||
requestFocus();
|
||||
giveClientFocus();
|
||||
}
|
||||
|
||||
private void giveClientFocus()
|
||||
{
|
||||
if (client instanceof Client)
|
||||
{
|
||||
final Canvas c = ((Client) client).getCanvas();
|
||||
c.requestFocusInWindow();
|
||||
}
|
||||
else if (client != null)
|
||||
{
|
||||
client.requestFocusInWindow();
|
||||
}
|
||||
this.config = config;
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* On config changed.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
@@ -240,147 +140,303 @@ public class ClientUI extends JFrame
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getKey().equals("gameAlwaysOnTop"))
|
||||
{
|
||||
if (this.isAlwaysOnTopSupported())
|
||||
{
|
||||
this.setAlwaysOnTop(Boolean.valueOf(event.getNewValue()));
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getKey().equals("lockWindowSize"))
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> setResizable(!Boolean.valueOf(event.getNewValue())));
|
||||
}
|
||||
|
||||
if (!event.getKey().equals("gameSize"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String[] splitStr = event.getNewValue().split("x");
|
||||
int width = Integer.parseInt(splitStr[0]);
|
||||
int height = Integer.parseInt(splitStr[1]);
|
||||
|
||||
// The upper bounds are defined by the applet's max size
|
||||
// The lower bounds are taken care of by ClientPanel's setMinimumSize
|
||||
|
||||
if (width > 7680)
|
||||
{
|
||||
width = 7680;
|
||||
}
|
||||
|
||||
if (height > 2160)
|
||||
{
|
||||
height = 2160;
|
||||
}
|
||||
|
||||
Dimension size = new Dimension(width, height);
|
||||
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
if (event.getKey().equals("gameAlwaysOnTop"))
|
||||
{
|
||||
if (frame.isAlwaysOnTopSupported())
|
||||
{
|
||||
frame.setAlwaysOnTop(config.gameAlwaysOnTop());
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getKey().equals("lockWindowSize"))
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> frame.setResizable(!config.lockWindowSize()));
|
||||
}
|
||||
|
||||
if (!event.getKey().equals("gameSize"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int width = config.gameSize().width;
|
||||
int height = config.gameSize().height;
|
||||
|
||||
// The upper bounds are defined by the applet's max size
|
||||
// The lower bounds are taken care of by ClientPanel's setMinimumSize
|
||||
|
||||
if (width > 7680)
|
||||
{
|
||||
width = 7680;
|
||||
}
|
||||
|
||||
if (height > 2160)
|
||||
{
|
||||
height = 2160;
|
||||
}
|
||||
|
||||
final Dimension size = new Dimension(width, height);
|
||||
|
||||
client.setSize(size);
|
||||
client.setPreferredSize(size);
|
||||
|
||||
client.getParent().setPreferredSize(size);
|
||||
client.getParent().setSize(size);
|
||||
|
||||
if (isVisible())
|
||||
if (frame.isVisible())
|
||||
{
|
||||
pack();
|
||||
frame.pack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void setUIFont(FontUIResource f)
|
||||
@Subscribe
|
||||
public void onPluginToolbarButtonAdded(final PluginToolbarButtonAdded event)
|
||||
{
|
||||
final Enumeration keys = UIManager.getDefaults().keys();
|
||||
|
||||
while (keys.hasMoreElements())
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
final Object key = keys.nextElement();
|
||||
final Object value = UIManager.get(key);
|
||||
|
||||
if (value instanceof FontUIResource)
|
||||
final JButton button = SwingUtil.createSwingButton(event.getButton(), 0, (jButton) ->
|
||||
{
|
||||
UIManager.put(key, f);
|
||||
}
|
||||
}
|
||||
final PluginPanel panel = event.getButton().getPanel();
|
||||
|
||||
if (panel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentButton != null)
|
||||
{
|
||||
currentButton.setSelected(false);
|
||||
}
|
||||
|
||||
if (currentButton == jButton)
|
||||
{
|
||||
contract();
|
||||
currentButton = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentButton = jButton;
|
||||
currentButton.setSelected(true);
|
||||
expand(panel);
|
||||
}
|
||||
});
|
||||
|
||||
pluginToolbar.addComponent(event.getIndex(), event.getButton(), button);
|
||||
});
|
||||
}
|
||||
|
||||
private TrayIcon setupTrayIcon()
|
||||
@Subscribe
|
||||
public void onPluginToolbarButtonRemoved(final PluginToolbarButtonRemoved event)
|
||||
{
|
||||
if (!SystemTray.isSupported())
|
||||
SwingUtilities.invokeLater(() -> pluginToolbar.removeComponent(event.getButton()));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onTitleToolbarButtonAdded(final TitleToolbarButtonAdded event)
|
||||
{
|
||||
if (!config.enableCustomChrome() && !SwingUtil.isCustomTitlePanePresent(frame))
|
||||
{
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
SystemTray systemTray = SystemTray.getSystemTray();
|
||||
TrayIcon trayIcon = new TrayIcon(ICON, properties.getTitle());
|
||||
trayIcon.setImageAutoSize(true);
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
final int iconSize = ClientTitleToolbar.TITLEBAR_SIZE - 6;
|
||||
final JButton button = SwingUtil.createSwingButton(event.getButton(), iconSize, null);
|
||||
titleToolbar.addComponent(event.getButton(), button);
|
||||
});
|
||||
}
|
||||
|
||||
try
|
||||
@Subscribe
|
||||
public void onTitleToolbarButtonRemoved(final TitleToolbarButtonRemoved event)
|
||||
{
|
||||
if (!config.enableCustomChrome() && !SwingUtil.isCustomTitlePanePresent(frame))
|
||||
{
|
||||
systemTray.add(trayIcon);
|
||||
}
|
||||
catch (AWTException ex)
|
||||
{
|
||||
log.debug("Unable to add system tray icon", ex);
|
||||
return trayIcon;
|
||||
return;
|
||||
}
|
||||
|
||||
// bring to front when tray icon is clicked
|
||||
trayIcon.addMouseListener(new MouseAdapter()
|
||||
SwingUtilities.invokeLater(() -> titleToolbar.removeComponent(event.getButton()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize UI.
|
||||
*
|
||||
* @param client the client
|
||||
* @throws Exception exception that can occur during creation of the UI
|
||||
*/
|
||||
public void init(@Nullable final Applet client) throws Exception
|
||||
{
|
||||
this.client = client;
|
||||
|
||||
SwingUtilities.invokeAndWait(() ->
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
// Set some sensible swing defaults
|
||||
SwingUtil.setupDefaults();
|
||||
|
||||
// Use substance look and feel
|
||||
SwingUtil.setTheme(new SubstanceGraphiteLookAndFeel());
|
||||
|
||||
// Use custom UI font
|
||||
SwingUtil.setFont(FontManager.getRunescapeFont());
|
||||
|
||||
// Create main window
|
||||
frame = new JFrame();
|
||||
|
||||
// Try to enable fullscreen on OSX
|
||||
OSXUtil.tryEnableFullscreen(frame);
|
||||
|
||||
trayIcon = SwingUtil.createTrayIcon(ICON, properties.getTitle(), frame);
|
||||
|
||||
frame.setTitle(properties.getTitle());
|
||||
frame.setIconImage(ICON);
|
||||
frame.getLayeredPane().setCursor(Cursor.getDefaultCursor()); // Prevent substance from using a resize cursor for pointing
|
||||
frame.setLocationRelativeTo(frame.getOwner());
|
||||
frame.setResizable(true);
|
||||
|
||||
SwingUtil.addGracefulExitCallback(frame, runelite::shutdown,
|
||||
() -> client != null
|
||||
&& client instanceof Client
|
||||
&& ((Client) client).getGameState() != GameState.LOGIN_SCREEN);
|
||||
|
||||
final JPanel container = new JPanel();
|
||||
container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
|
||||
container.add(new ClientPanel(client));
|
||||
|
||||
navContainer = new JPanel();
|
||||
navContainer.setLayout(new BorderLayout(0, 0));
|
||||
navContainer.setMinimumSize(new Dimension(0, 0));
|
||||
navContainer.setMaximumSize(new Dimension(0, Integer.MAX_VALUE));
|
||||
container.add(navContainer);
|
||||
|
||||
pluginToolbar = new ClientPluginToolbar();
|
||||
container.add(pluginToolbar);
|
||||
|
||||
titleToolbar = new ClientTitleToolbar();
|
||||
frame.add(container);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show client UI after everything else is done.
|
||||
*
|
||||
* @throws Exception exception that can occur during modification of the UI
|
||||
*/
|
||||
public void show() throws Exception
|
||||
{
|
||||
final boolean withTitleBar = config.enableCustomChrome();
|
||||
|
||||
SwingUtilities.invokeAndWait(() ->
|
||||
{
|
||||
frame.setUndecorated(withTitleBar);
|
||||
|
||||
if (withTitleBar)
|
||||
{
|
||||
setVisible(true);
|
||||
setState(Frame.NORMAL); // unminimize
|
||||
frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
|
||||
|
||||
final JComponent titleBar = SubstanceCoreUtilities.getTitlePaneComponent(frame);
|
||||
titleToolbar.putClientProperty(SubstanceTitlePaneUtilities.EXTRA_COMPONENT_KIND, SubstanceTitlePaneUtilities.ExtraComponentKind.TRAILING);
|
||||
titleBar.add(titleToolbar);
|
||||
|
||||
// Substance's default layout manager for the title bar only lays out substance's components
|
||||
// This wraps the default manager and lays out the TitleToolbar as well.
|
||||
LayoutManager delegate = titleBar.getLayout();
|
||||
titleBar.setLayout(new LayoutManager()
|
||||
{
|
||||
@Override
|
||||
public void addLayoutComponent(String name, Component comp)
|
||||
{
|
||||
delegate.addLayoutComponent(name, comp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLayoutComponent(Component comp)
|
||||
{
|
||||
delegate.removeLayoutComponent(comp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent)
|
||||
{
|
||||
return delegate.preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize(Container parent)
|
||||
{
|
||||
return delegate.minimumLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent)
|
||||
{
|
||||
delegate.layoutContainer(parent);
|
||||
final int width = titleToolbar.getPreferredSize().width;
|
||||
titleToolbar.setBounds(titleBar.getWidth() - 75 - width, 0, width, titleBar.getHeight());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
frame.pack();
|
||||
SwingUtil.revalidateMinimumSize(frame);
|
||||
frame.setLocationRelativeTo(frame.getOwner());
|
||||
frame.setVisible(true);
|
||||
frame.toFront();
|
||||
requestFocus();
|
||||
giveClientFocus();
|
||||
});
|
||||
|
||||
return trayIcon;
|
||||
eventBus.post(new ClientUILoaded());
|
||||
}
|
||||
|
||||
private void init()
|
||||
/**
|
||||
* Paint this component to target graphics
|
||||
*
|
||||
* @param graphics the graphics
|
||||
*/
|
||||
public void paint(final Graphics graphics)
|
||||
{
|
||||
assert SwingUtilities.isEventDispatchThread();
|
||||
|
||||
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
checkExit();
|
||||
}
|
||||
});
|
||||
|
||||
final JPanel container = new JPanel();
|
||||
container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
|
||||
container.add(new ClientPanel(client));
|
||||
|
||||
navContainer = new JPanel();
|
||||
navContainer.setLayout(new BorderLayout(0, 0));
|
||||
navContainer.setMinimumSize(new Dimension(0, 0));
|
||||
navContainer.setMaximumSize(new Dimension(0, Integer.MAX_VALUE));
|
||||
container.add(navContainer);
|
||||
|
||||
pluginToolbar = new PluginToolbar(this);
|
||||
container.add(pluginToolbar);
|
||||
|
||||
titleToolbar = new TitleToolbar(properties);
|
||||
|
||||
add(container);
|
||||
frame.paint(graphics);
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Gets component width.
|
||||
*
|
||||
* @return the width
|
||||
*/
|
||||
public int getWidth()
|
||||
{
|
||||
return frame.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets component height.
|
||||
*
|
||||
* @return the height
|
||||
*/
|
||||
public int getHeight()
|
||||
{
|
||||
return frame.getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this component has focus.
|
||||
*
|
||||
* @return true if component has focus
|
||||
*/
|
||||
public boolean isFocused()
|
||||
{
|
||||
return frame.isFocused();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request focus on this component and then on client component
|
||||
*/
|
||||
public void requestFocus()
|
||||
{
|
||||
if (OSType.getOSType() == OSType.MacOS)
|
||||
@@ -388,17 +444,11 @@ public class ClientUI extends JFrame
|
||||
OSXUtil.requestFocus();
|
||||
}
|
||||
|
||||
super.requestFocus();
|
||||
frame.requestFocus();
|
||||
giveClientFocus();
|
||||
}
|
||||
|
||||
private void revalidateMinimumSize()
|
||||
{
|
||||
// The JFrame only respects minimumSize if it was set by setMinimumSize, for some reason. (atleast on windows/native)
|
||||
this.setMinimumSize(this.getLayout().minimumLayoutSize(this));
|
||||
}
|
||||
|
||||
void expand(PluginPanel panel)
|
||||
private void expand(PluginPanel panel)
|
||||
{
|
||||
if (pluginPanel != null)
|
||||
{
|
||||
@@ -406,9 +456,11 @@ public class ClientUI extends JFrame
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isInScreenBounds((int) getLocationOnScreen().getX() + getWidth() + PANEL_EXPANDED_WIDTH, (int) getLocationOnScreen().getY()))
|
||||
if (SwingUtil.isInScreenBounds(
|
||||
frame.getLocationOnScreen().y + frame.getWidth() + PANEL_EXPANDED_WIDTH,
|
||||
frame.getLocationOnScreen().y))
|
||||
{
|
||||
this.setSize(getWidth() + PANEL_EXPANDED_WIDTH, getHeight());
|
||||
frame.setSize(frame.getWidth() + PANEL_EXPANDED_WIDTH, frame.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,57 +477,42 @@ public class ClientUI extends JFrame
|
||||
panel.onActivate();
|
||||
|
||||
wrappedPanel.repaint();
|
||||
revalidateMinimumSize();
|
||||
SwingUtil.revalidateMinimumSize(frame);
|
||||
}
|
||||
|
||||
void contract()
|
||||
private void contract()
|
||||
{
|
||||
boolean wasMinimumWidth = this.getWidth() == (int) this.getMinimumSize().getWidth();
|
||||
boolean wasMinimumWidth = frame.getWidth() == frame.getMinimumSize().width;
|
||||
pluginPanel.onDeactivate();
|
||||
navContainer.remove(0);
|
||||
navContainer.setMinimumSize(new Dimension(0, 0));
|
||||
navContainer.setMaximumSize(new Dimension(0, Integer.MAX_VALUE));
|
||||
navContainer.setMaximumSize(new Dimension(0, 0));
|
||||
navContainer.revalidate();
|
||||
giveClientFocus();
|
||||
revalidateMinimumSize();
|
||||
SwingUtil.revalidateMinimumSize(frame);
|
||||
|
||||
if (wasMinimumWidth)
|
||||
{
|
||||
this.setSize((int) this.getMinimumSize().getWidth(), getHeight());
|
||||
frame.setSize(frame.getMinimumSize().width, frame.getHeight());
|
||||
}
|
||||
else if (getWidth() < Toolkit.getDefaultToolkit().getScreenSize().getWidth())
|
||||
else if (frame.getWidth() < Toolkit.getDefaultToolkit().getScreenSize().getWidth())
|
||||
{
|
||||
this.setSize(getWidth() - PANEL_EXPANDED_WIDTH, getHeight());
|
||||
frame.setSize(frame.getWidth() - PANEL_EXPANDED_WIDTH, frame.getHeight());
|
||||
}
|
||||
|
||||
pluginPanel = null;
|
||||
}
|
||||
|
||||
private boolean isInScreenBounds(int x, int y)
|
||||
private void giveClientFocus()
|
||||
{
|
||||
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
return x >= 0 && x <= size.getWidth() && y >= 0 && y <= size.getHeight();
|
||||
}
|
||||
|
||||
private void checkExit()
|
||||
{
|
||||
int result = JOptionPane.OK_OPTION;
|
||||
|
||||
// only ask if not logged out
|
||||
if (client != null && client instanceof Client && ((Client) client).getGameState() != GameState.LOGIN_SCREEN)
|
||||
if (client instanceof Client)
|
||||
{
|
||||
result = JOptionPane.showConfirmDialog(this, "Are you sure you want to exit?", "Exit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||
final Canvas c = ((Client) client).getCanvas();
|
||||
c.requestFocusInWindow();
|
||||
}
|
||||
|
||||
if (result == JOptionPane.OK_OPTION)
|
||||
else if (client != null)
|
||||
{
|
||||
runelite.shutdown();
|
||||
System.exit(0);
|
||||
client.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
public PluginToolbar getPluginToolbar()
|
||||
{
|
||||
return pluginToolbar;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2017-2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.con>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,30 +25,57 @@
|
||||
*/
|
||||
package net.runelite.client.ui;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.function.Supplier;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Map;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Slf4j
|
||||
public class NavigationButton extends JButton
|
||||
/**
|
||||
* UI navigation button.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@EqualsAndHashCode(of = {"name", "tooltip"})
|
||||
public class NavigationButton
|
||||
{
|
||||
@Getter
|
||||
private final Supplier<PluginPanel> panelSupplier;
|
||||
/**
|
||||
* Button name.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
public NavigationButton(String name, Image icon)
|
||||
{
|
||||
this(name, icon, null);
|
||||
}
|
||||
/**
|
||||
* Icon of button.
|
||||
*/
|
||||
private final BufferedImage icon;
|
||||
|
||||
public NavigationButton(String name, Image icon, Supplier<PluginPanel> panelSupplier)
|
||||
{
|
||||
super();
|
||||
setName(name);
|
||||
setToolTipText(name);
|
||||
setIcon(new ImageIcon(icon));
|
||||
this.panelSupplier = panelSupplier;
|
||||
}
|
||||
/**
|
||||
* Tooltip to show when hovered.
|
||||
*/
|
||||
private String tooltip;
|
||||
|
||||
/**
|
||||
* Button selection state
|
||||
*/
|
||||
private boolean selected;
|
||||
|
||||
/**
|
||||
* On select action of the button.
|
||||
*/
|
||||
private Runnable onSelect;
|
||||
|
||||
/**
|
||||
* On click action of the button.
|
||||
*/
|
||||
private Runnable onClick;
|
||||
|
||||
/**
|
||||
* Plugin panel, used when expanding and contracting sidebar.
|
||||
*/
|
||||
private PluginPanel panel;
|
||||
|
||||
/**
|
||||
* Map of key-value pairs for setting the popup menu
|
||||
*/
|
||||
private Map<String, Runnable> popup;
|
||||
}
|
||||
|
||||
@@ -24,87 +24,60 @@
|
||||
*/
|
||||
package net.runelite.client.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import java.util.Comparator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Supplier;
|
||||
import javax.swing.JToolBar;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.client.events.PluginToolbarButtonAdded;
|
||||
import net.runelite.client.events.PluginToolbarButtonRemoved;
|
||||
|
||||
@Slf4j
|
||||
public class PluginToolbar extends JToolBar
|
||||
/**
|
||||
* Plugin toolbar buttons holder.
|
||||
*/
|
||||
@Singleton
|
||||
public class PluginToolbar
|
||||
{
|
||||
public static final int TOOLBAR_WIDTH = 36, TOOLBAR_HEIGHT = 503;
|
||||
private final EventBus eventBus;
|
||||
private final TreeSet<NavigationButton> buttons = new TreeSet<>(Comparator.comparing(NavigationButton::getName));
|
||||
|
||||
private final ClientUI ui;
|
||||
private final TreeSet<NavigationButton> buttons = new TreeSet<>(Comparator.comparing(Component::getName));
|
||||
|
||||
private NavigationButton current;
|
||||
|
||||
public PluginToolbar(ClientUI ui)
|
||||
@Inject
|
||||
private PluginToolbar(final EventBus eventBus)
|
||||
{
|
||||
super(JToolBar.VERTICAL);
|
||||
this.ui = ui;
|
||||
|
||||
super.setFloatable(false);
|
||||
super.setSize(new Dimension(TOOLBAR_WIDTH, TOOLBAR_HEIGHT));
|
||||
super.setMinimumSize(new Dimension(TOOLBAR_WIDTH, TOOLBAR_HEIGHT));
|
||||
super.setPreferredSize(new Dimension(TOOLBAR_WIDTH, TOOLBAR_HEIGHT));
|
||||
super.setMaximumSize(new Dimension(TOOLBAR_WIDTH, Integer.MAX_VALUE));
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
public void addNavigation(NavigationButton button)
|
||||
/**
|
||||
* Add navigation.
|
||||
*
|
||||
* @param button the button
|
||||
*/
|
||||
public void addNavigation(final NavigationButton button)
|
||||
{
|
||||
button.addActionListener((ae) -> onClick(button));
|
||||
button.setToolTipText(button.getName());
|
||||
|
||||
if (buttons.contains(button))
|
||||
{
|
||||
log.warn("Button already in container '{}'", button.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
buttons.add(button);
|
||||
if (buttons.add(button))
|
||||
{
|
||||
int index = buttons.headSet(button).size();
|
||||
eventBus.post(new PluginToolbarButtonAdded(button, index));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove navigation.
|
||||
*
|
||||
* @param button the button
|
||||
*/
|
||||
public void removeNavigation(final NavigationButton button)
|
||||
{
|
||||
int index = buttons.headSet(button).size();
|
||||
add(button, index);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void removeNavigation(NavigationButton button)
|
||||
{
|
||||
buttons.remove(button);
|
||||
remove(button);
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void onClick(NavigationButton button)
|
||||
{
|
||||
Supplier<PluginPanel> panelSupplier = button.getPanelSupplier();
|
||||
if (panelSupplier == null)
|
||||
if (buttons.remove(button))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
current.setSelected(false);
|
||||
}
|
||||
|
||||
if (current == button)
|
||||
{
|
||||
ui.contract();
|
||||
current = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = button;
|
||||
current.setSelected(true);
|
||||
|
||||
PluginPanel pluginPanel = panelSupplier.get();
|
||||
ui.expand(pluginPanel);
|
||||
eventBus.post(new PluginToolbarButtonRemoved(button, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* Copyright (c) 2017-2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,174 +25,78 @@
|
||||
*/
|
||||
package net.runelite.client.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Image;
|
||||
import java.awt.LayoutManager2;
|
||||
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.JPanel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.client.events.TitleToolbarButtonAdded;
|
||||
import net.runelite.client.events.TitleToolbarButtonRemoved;
|
||||
|
||||
@Slf4j
|
||||
public class TitleToolbar extends JPanel
|
||||
/**
|
||||
* Title toolbar buttons holder.
|
||||
*/
|
||||
@Singleton
|
||||
public class TitleToolbar
|
||||
{
|
||||
private static final int TITLEBAR_SIZE = 23;
|
||||
private static final int ITEM_PADDING = 4;
|
||||
private final EventBus eventBus;
|
||||
private final TreeSet<NavigationButton> buttons = new TreeSet<>(Comparator.comparing(NavigationButton::getTooltip));
|
||||
|
||||
public TitleToolbar(RuneLiteProperties properties)
|
||||
@Inject
|
||||
private TitleToolbar(final EventBus eventBus)
|
||||
{
|
||||
// The only other layout manager that would manage it's preferred size without padding
|
||||
// was the GroupLayout manager, which doesn't work with dynamic layouts like this one.
|
||||
// Primarily, it would not remove components unless it was immediately repainted.
|
||||
setLayout(new LayoutManager2()
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add navigation.
|
||||
*
|
||||
* @param button the button
|
||||
*/
|
||||
public void addNavigation(final NavigationButton button)
|
||||
{
|
||||
if (buttons.contains(button))
|
||||
{
|
||||
@Override
|
||||
public void addLayoutComponent(String name, Component comp)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLayoutComponent(Component comp, Object constraints)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLayoutComponent(Component comp)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent)
|
||||
{
|
||||
int width = parent.getComponentCount() * (TITLEBAR_SIZE + ITEM_PADDING);
|
||||
return new Dimension(width, TITLEBAR_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize(Container parent)
|
||||
{
|
||||
return preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension maximumLayoutSize(Container parent)
|
||||
{
|
||||
return preferredLayoutSize(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLayoutAlignmentX(Container target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLayoutAlignmentY(Container target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateLayout(Container target)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent)
|
||||
{
|
||||
int x = 0;
|
||||
for (Component c : parent.getComponents())
|
||||
{
|
||||
x += ITEM_PADDING;
|
||||
int height = c.getPreferredSize().height;
|
||||
if (height > TITLEBAR_SIZE)
|
||||
{
|
||||
height = TITLEBAR_SIZE;
|
||||
}
|
||||
c.setBounds(x, (TITLEBAR_SIZE - height) / 2, TITLEBAR_SIZE, height);
|
||||
x += TITLEBAR_SIZE;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
BufferedImage discordIcon;
|
||||
BufferedImage invertedIcon;
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
discordIcon = ImageIO.read(ClientUI.class.getResourceAsStream("discord.png"));
|
||||
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);
|
||||
return;
|
||||
}
|
||||
catch (IOException ex)
|
||||
|
||||
if (buttons.add(button))
|
||||
{
|
||||
log.warn("unable to load discord button", ex);
|
||||
int index = buttons.headSet(button).size();
|
||||
eventBus.post(new TitleToolbarButtonAdded(button, index));
|
||||
}
|
||||
}
|
||||
|
||||
public void addButton(JButton button, Image iconImage, Image invertedIconImage)
|
||||
/**
|
||||
* Remove navigation.
|
||||
*
|
||||
* @param button the button
|
||||
*/
|
||||
public void removeNavigation(final NavigationButton button)
|
||||
{
|
||||
final int iconSize = TITLEBAR_SIZE - 6;
|
||||
ImageIcon icon = new ImageIcon(iconImage.getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH));
|
||||
ImageIcon invertedIcon;
|
||||
if (invertedIconImage == null)
|
||||
{
|
||||
invertedIcon = icon;
|
||||
}
|
||||
else
|
||||
{
|
||||
invertedIcon = new ImageIcon(invertedIconImage.getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH));
|
||||
}
|
||||
int index = buttons.headSet(button).size();
|
||||
|
||||
button.setIcon(icon);
|
||||
button.setRolloverIcon(invertedIcon);
|
||||
button.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE);
|
||||
button.setFocusable(false);
|
||||
|
||||
add(button);
|
||||
revalidate();
|
||||
repaint();
|
||||
if (buttons.remove(button))
|
||||
{
|
||||
eventBus.post(new TitleToolbarButtonRemoved(button, index));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Component c)
|
||||
/**
|
||||
* Refresh all buttons
|
||||
*/
|
||||
public void refresh()
|
||||
{
|
||||
super.remove(c);
|
||||
revalidate();
|
||||
repaint();
|
||||
final Iterator<NavigationButton> iterator = buttons.iterator();
|
||||
int index = 0;
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
final NavigationButton button = iterator.next();
|
||||
eventBus.post(new TitleToolbarButtonRemoved(button, index));
|
||||
eventBus.post(new TitleToolbarButtonAdded(button, index));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,10 @@ import java.awt.datatransfer.StringSelection;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
|
||||
/**
|
||||
* Utility class used for browser navigation
|
||||
@@ -45,21 +42,13 @@ import net.runelite.client.ui.ClientUI;
|
||||
@Slf4j
|
||||
public class LinkBrowser
|
||||
{
|
||||
private final Provider<ClientUI> clientUIProvider;
|
||||
|
||||
@Inject
|
||||
private LinkBrowser(final Provider<ClientUI> clientUIProvider)
|
||||
{
|
||||
this.clientUIProvider = clientUIProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to navigate to specified URL in browser. In case operation fails, displays message box with message
|
||||
* and copies link to clipboard to navigate to.
|
||||
* @param url url to open
|
||||
* @return true if operation was successful
|
||||
*/
|
||||
public boolean browse(final String url)
|
||||
public static boolean browse(final String url)
|
||||
{
|
||||
if (!Desktop.isDesktopSupported())
|
||||
{
|
||||
@@ -93,18 +82,11 @@ public class LinkBrowser
|
||||
* Open swing message box with specified message and copy data to clipboard
|
||||
* @param message message to show
|
||||
*/
|
||||
private void showMessageBox(final String message, final String data)
|
||||
private static void showMessageBox(final String message, final String data)
|
||||
{
|
||||
final ClientUI clientUI = clientUIProvider.get();
|
||||
|
||||
if (clientUI == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
final int result = JOptionPane.showConfirmDialog(clientUI, message, "Message",
|
||||
final int result = JOptionPane.showConfirmDialog(null, message, "Message",
|
||||
JOptionPane.OK_CANCEL_OPTION);
|
||||
|
||||
if (result == JOptionPane.OK_OPTION)
|
||||
|
||||
@@ -26,8 +26,8 @@ package net.runelite.client.util;
|
||||
|
||||
import com.apple.eawt.Application;
|
||||
import com.apple.eawt.FullScreenUtilities;
|
||||
import javax.swing.JFrame;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
|
||||
/**
|
||||
* A class with OSX-specific functions to improve integration.
|
||||
@@ -40,7 +40,7 @@ public class OSXUtil
|
||||
*
|
||||
* @param gui The gui to enable the fullscreen on.
|
||||
*/
|
||||
public static void tryEnableFullscreen(ClientUI gui)
|
||||
public static void tryEnableFullscreen(JFrame gui)
|
||||
{
|
||||
if (OSType.getOSType() == OSType.MacOS)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* 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.util;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.Window;
|
||||
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.util.Enumeration;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Consumer;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
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 org.pushingpixels.substance.internal.SubstanceSynapse;
|
||||
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
||||
|
||||
/**
|
||||
* Various Swing utilities.
|
||||
*/
|
||||
@Slf4j
|
||||
public class SwingUtil
|
||||
{
|
||||
/**
|
||||
* Sets some sensible defaults for swing.
|
||||
* IMPORTANT! Needs to be called before main frame creation
|
||||
*/
|
||||
public static void setupDefaults()
|
||||
{
|
||||
// Force heavy-weight popups/tooltips.
|
||||
// Prevents them from being obscured by the game applet.
|
||||
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
|
||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||
|
||||
// Do not render shadows under popups/tooltips.
|
||||
// Fixes black boxes under popups that are above the game applet.
|
||||
System.setProperty("jgoodies.popupDropShadowEnabled", "false");
|
||||
|
||||
// Do not fill in background on repaint. Reduces flickering when
|
||||
// the applet is resized.
|
||||
System.setProperty("sun.awt.noerasebackground", "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely sets Swing theme
|
||||
*
|
||||
* @param laf the swing look and feel
|
||||
*/
|
||||
public static void setTheme(@Nonnull final LookAndFeel laf)
|
||||
{
|
||||
try
|
||||
{
|
||||
UIManager.setLookAndFeel(laf);
|
||||
}
|
||||
catch (UnsupportedLookAndFeelException ex)
|
||||
{
|
||||
log.warn("Unable to set look and feel", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default Swing font.
|
||||
* IMPORTANT! Needs to be called before main frame creation
|
||||
*
|
||||
* @param font the new font to use
|
||||
*/
|
||||
public static void setFont(@Nonnull final Font font)
|
||||
{
|
||||
final FontUIResource f = new FontUIResource(font);
|
||||
final Enumeration keys = UIManager.getDefaults().keys();
|
||||
|
||||
while (keys.hasMoreElements())
|
||||
{
|
||||
final Object key = keys.nextElement();
|
||||
final Object value = UIManager.get(key);
|
||||
|
||||
if (value instanceof FontUIResource)
|
||||
{
|
||||
UIManager.put(key, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create tray icon.
|
||||
*
|
||||
* @param icon the icon
|
||||
* @param title the title
|
||||
* @param frame the frame
|
||||
* @return the tray icon
|
||||
*/
|
||||
@Nullable
|
||||
public static TrayIcon createTrayIcon(@Nonnull final Image icon, @Nonnull final String title, @Nonnull final Frame frame)
|
||||
{
|
||||
if (!SystemTray.isSupported())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final SystemTray systemTray = SystemTray.getSystemTray();
|
||||
final TrayIcon trayIcon = new TrayIcon(icon, title);
|
||||
trayIcon.setImageAutoSize(true);
|
||||
|
||||
try
|
||||
{
|
||||
systemTray.add(trayIcon);
|
||||
}
|
||||
catch (AWTException ex)
|
||||
{
|
||||
log.debug("Unable to add system tray icon", ex);
|
||||
return trayIcon;
|
||||
}
|
||||
|
||||
// Bring to front when tray icon is clicked
|
||||
trayIcon.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
frame.setVisible(true);
|
||||
frame.setState(Frame.NORMAL); // Restore
|
||||
}
|
||||
});
|
||||
|
||||
return trayIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if point is in screen bounds.
|
||||
*
|
||||
* @param x the x
|
||||
* @param y the y
|
||||
* @return the boolean
|
||||
*/
|
||||
public static boolean isInScreenBounds(final int x, final int y)
|
||||
{
|
||||
final Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
final Rectangle bounds = new Rectangle(size);
|
||||
return bounds.contains(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add graceful exit callback.
|
||||
*
|
||||
* @param frame the frame
|
||||
* @param callback the callback
|
||||
* @param confirmRequired the confirm required
|
||||
*/
|
||||
public static void addGracefulExitCallback(@Nonnull final JFrame frame, @Nonnull final Runnable callback, @Nonnull final Callable<Boolean> confirmRequired)
|
||||
{
|
||||
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event)
|
||||
{
|
||||
int result = JOptionPane.OK_OPTION;
|
||||
|
||||
try
|
||||
{
|
||||
if (confirmRequired.call())
|
||||
{
|
||||
result = JOptionPane.showConfirmDialog(
|
||||
frame,
|
||||
"Are you sure you want to exit?", "Exit",
|
||||
JOptionPane .OK_CANCEL_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unexpected exception occurred while check for confirm required", e);
|
||||
}
|
||||
|
||||
if (result == JOptionPane.OK_OPTION)
|
||||
{
|
||||
callback.run();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Revalidate minimum frame size.
|
||||
*
|
||||
* @param frame the frame
|
||||
*/
|
||||
public static void revalidateMinimumSize(final JFrame frame)
|
||||
{
|
||||
// The JFrame only respects minimumSize if it was set by setMinimumSize, for some reason. (atleast on windows/native)
|
||||
frame.setMinimumSize(frame.getLayout().minimumLayoutSize(frame));
|
||||
}
|
||||
|
||||
private static BufferedImage resizeImage(BufferedImage image, int newWidth, int newHeight)
|
||||
{
|
||||
final Image tmp = image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
|
||||
final BufferedImage dimg = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
final Graphics2D g2d = dimg.createGraphics();
|
||||
g2d.drawImage(tmp, 0, 0, null);
|
||||
g2d.dispose();
|
||||
return dimg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create swing button from navigation button.
|
||||
*
|
||||
* @param navigationButton the navigation button
|
||||
* @param iconSize the icon size (in case it is 0 default icon size will be used)
|
||||
* @param specialCallback the special callback
|
||||
* @return the swing button
|
||||
*/
|
||||
public static JButton createSwingButton(
|
||||
@Nonnull final NavigationButton navigationButton,
|
||||
int iconSize,
|
||||
@Nullable final Consumer<JButton> specialCallback)
|
||||
{
|
||||
|
||||
final BufferedImage scaledImage = iconSize > 0
|
||||
? resizeImage(navigationButton.getIcon(), iconSize, iconSize)
|
||||
: navigationButton.getIcon();
|
||||
|
||||
final JButton button = new JButton();
|
||||
button.setName(navigationButton.getName());
|
||||
button.setToolTipText(navigationButton.getTooltip());
|
||||
button.setIcon(new ImageIcon(scaledImage));
|
||||
button.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE);
|
||||
button.setFocusable(false);
|
||||
button.addActionListener(e ->
|
||||
{
|
||||
if (specialCallback != null)
|
||||
{
|
||||
specialCallback.accept(button);
|
||||
}
|
||||
|
||||
if (navigationButton.getOnClick() != null)
|
||||
{
|
||||
navigationButton.getOnClick().run();
|
||||
}
|
||||
});
|
||||
|
||||
if (navigationButton.getPopup() != null)
|
||||
{
|
||||
final JPopupMenu popupMenu = new JPopupMenu();
|
||||
|
||||
navigationButton.getPopup().forEach((name, callback) ->
|
||||
{
|
||||
final JMenuItem menuItem = new JMenuItem(name);
|
||||
menuItem.addActionListener((e) -> callback.run());
|
||||
popupMenu.add(menuItem);
|
||||
});
|
||||
|
||||
button.setComponentPopupMenu(popupMenu);
|
||||
}
|
||||
|
||||
navigationButton.setOnSelect(() -> button.setSelected(navigationButton.isSelected()));
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if custom substance title pane is present.
|
||||
*
|
||||
* @param frame the parent frame
|
||||
* @return true if title pane is present
|
||||
*/
|
||||
public static boolean isCustomTitlePanePresent(final Window frame)
|
||||
{
|
||||
return SubstanceCoreUtilities.getTitlePaneComponent(frame) != null;
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 67 KiB |
@@ -45,7 +45,6 @@ import joptsimple.OptionSet;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.RuneLiteModule;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -67,9 +66,6 @@ public class PluginManagerTest
|
||||
private RuneLite runelite;
|
||||
private Set<Class> pluginClasses;
|
||||
|
||||
@Mock
|
||||
ClientUI clientUi;
|
||||
|
||||
@Mock
|
||||
Client client;
|
||||
|
||||
@@ -83,7 +79,6 @@ public class PluginManagerTest
|
||||
RuneLite.setInjector(injector);
|
||||
|
||||
runelite = injector.getInstance(RuneLite.class);
|
||||
runelite.setGui(clientUi);
|
||||
|
||||
// Find plugins we expect to have
|
||||
pluginClasses = new HashSet<>();
|
||||
|
||||
Reference in New Issue
Block a user