From a4914cf7eec7b200d16a9bc435876bbed77af4dd Mon Sep 17 00:00:00 2001 From: Max Weber Date: Fri, 2 Feb 2018 05:13:21 -0700 Subject: [PATCH] Add info panel plugin --- .../runelite/client/RuneLiteProperties.java | 6 + .../client/plugins/info/InfoPanel.java | 173 ++++++++++++++++++ .../client/plugins/info/InfoPlugin.java | 64 +++++++ .../client/plugins/info/JRichTextPane.java | 99 ++++++++++ .../client/plugins/info/info_icon.png | Bin 0 -> 1810 bytes .../net/runelite/client/runelite.properties | 2 +- 6 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/info/info_icon.png diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java index 557bc675b1..f01c70a946 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLiteProperties.java @@ -38,6 +38,7 @@ public class RuneLiteProperties { private static final String RUNELITE_TITLE = "runelite.title"; private static final String RUNELITE_VERSION = "runelite.version"; + private static final String RUNESCAPE_VERSION = "runescape.version"; private final Properties properties = new Properties(); @@ -64,4 +65,9 @@ public class RuneLiteProperties { return properties.getProperty(RUNELITE_VERSION); } + + public String getRunescapeVersion() + { + return properties.getProperty(RUNESCAPE_VERSION); + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java new file mode 100644 index 0000000000..e58c12c5f6 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPanel.java @@ -0,0 +1,173 @@ +/* + * 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.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.util.concurrent.ScheduledExecutorService; +import javax.annotation.Nullable; +import javax.swing.GroupLayout; +import javax.swing.JLabel; +import javax.swing.LayoutStyle; +import javax.swing.event.HyperlinkEvent; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.events.SessionClose; +import net.runelite.api.events.SessionOpen; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.account.SessionManager; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.util.RunnableExceptionLogger; + +@Slf4j +public class InfoPanel extends PluginPanel +{ + private final static String RUNELITE_LOGIN = "https://runelite_login/"; + + @Inject + @Nullable + private Client client; + + @Inject + private RuneLiteProperties runeLiteProperties; + + @Inject + private EventBus eventBus; + + @Inject + private SessionManager sessionManager; + + @Inject + private ScheduledExecutorService executor; + + private final GroupLayout layout = new GroupLayout(this); + + private final JLabel usernameHeader = new JLabel(); + private final JRichTextPane username = new JRichTextPane(); + + void init() + { + setLayout(layout); + + final Font smallFont = FontManager.getRunescapeSmallFont(); + + final JLabel runeliteVersionHeader = new JLabel("RuneLite version"); + runeliteVersionHeader.setFont(smallFont); + final JLabel runeliteVersion = new JLabel(runeLiteProperties.getVersion()); + + final JLabel runescapeVersionHeader = new JLabel("OldSchool Engine"); + runescapeVersionHeader.setFont(smallFont); + + String engineVer = "Unknown"; + if (client != null) + { + engineVer = String.format("Rev %s", runeLiteProperties.getRunescapeVersion()); + } + final JLabel runescapeVersion = new JLabel(engineVer); + + usernameHeader.setFont(smallFont); + username.enableAutoLinkHandler(false); + username.addHyperlinkListener(e -> + { + if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null) + { + if (e.getURL().toString().equals(RUNELITE_LOGIN)) + { + executor.execute(RunnableExceptionLogger.wrap(sessionManager::login)); + } + } + }); + setNotLoggedIn(); + + final JRichTextPane issueLink = new JRichTextPane("text/html", + "RuneLite is open source!
" + + "Found an issue? Want a feature?
" + + "" + + "Open an issue on GitHub!" + + "" + ); + + layout.setVerticalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup() + .addComponent(runeliteVersionHeader) + .addComponent(runescapeVersionHeader) + ).addGroup(layout.createParallelGroup() + .addComponent(runeliteVersion) + .addComponent(runescapeVersion) + ).addGap(6) + .addComponent(usernameHeader) + .addGroup(layout.createParallelGroup() + .addComponent(username) + ) + .addGap(12) + .addComponent(issueLink) + ); + + layout.setHorizontalGroup(layout.createParallelGroup() + .addGroup(layout.createSequentialGroup() + .addComponent(runeliteVersionHeader) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addComponent(runescapeVersionHeader) + ).addGroup(layout.createSequentialGroup() + .addComponent(runeliteVersion) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addComponent(runescapeVersion) + ) + .addComponent(usernameHeader) + .addComponent(username) + .addComponent(issueLink) + ); + + eventBus.register(this); + } + + private void setNotLoggedIn() + { + username.setContentType("text/html"); + username.setText("Login to sync settings to the cloud."); + usernameHeader.setText("Not logged in"); + } + + @Subscribe + private void onSessionOpen(SessionOpen sessionOpen) + { + String name = sessionManager.getAccountSession().getUsername(); + if (name != null) + { + username.setContentType("text/plain"); + username.setText(name); + usernameHeader.setText("Logged in as"); + } + } + + @Subscribe + private void onSessionClose(SessionClose e) + { + setNotLoggedIn(); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java new file mode 100644 index 0000000000..8a1a1163b4 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/InfoPlugin.java @@ -0,0 +1,64 @@ +/* + * 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.plugins.info; + +import com.google.inject.Binder; +import javax.imageio.ImageIO; +import javax.inject.Inject; +import net.runelite.client.plugins.Plugin; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ClientUI; +import net.runelite.client.ui.NavigationButton; + +@PluginDescriptor( + name = "Info panel plugin", + loadWhenOutdated = true +) +public class InfoPlugin extends Plugin +{ + @Inject + private ClientUI ui; + + @Override + public void configure(Binder binder) + { + binder.bind(InfoPanel.class); + } + + @Override + protected void startUp() throws Exception + { + final InfoPanel panel = injector.getInstance(InfoPanel.class); + panel.init(); + + final NavigationButton navButton = new NavigationButton( + "Info", + ImageIO.read(getClass().getResourceAsStream("info_icon.png")), + () -> panel + ); + + ui.getPluginToolbar().addNavigation(navButton); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java b/runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java new file mode 100644 index 0000000000..21b8f46cd5 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/info/JRichTextPane.java @@ -0,0 +1,99 @@ +/* + * 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.plugins.info; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URISyntaxException; +import javax.swing.BorderFactory; +import javax.swing.JEditorPane; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.text.html.HTMLEditorKit; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class JRichTextPane extends JEditorPane +{ + private HyperlinkListener linkHandler; + + public JRichTextPane() + { + super(); + setHighlighter(null); + setEditable(false); + setOpaque(false); + enableAutoLinkHandler(true); + setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + HTMLEditorKit ek = (HTMLEditorKit) getEditorKitForContentType("text/html"); + ek.getStyleSheet().addRule("a {color: #DDDDDD }"); + } + + public JRichTextPane(String type, String text) + { + this(); + setContentType(type); + setText(text); + } + + public void enableAutoLinkHandler(boolean enable) + { + if (enable != (linkHandler != null)) + { + if (enable) + { + linkHandler = e -> + { + log.info(e.toString()); + if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null) + { + if (Desktop.isDesktopSupported()) + { + try + { + Desktop.getDesktop().browse(e.getURL().toURI()); + } + catch (URISyntaxException | IOException ex) + { + log.info("Error opening link", ex); + } + } + } + }; + addHyperlinkListener(linkHandler); + } + else + { + removeHyperlinkListener(linkHandler); + linkHandler = null; + } + } + } + + public boolean getAutoLinkHandlerEnabled() + { + return linkHandler != null; + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/info/info_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/info/info_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..565f2a48b259a09ac4f977bcb06d33910dab5275 GIT binary patch literal 1810 zcmcIlU2NM_6n0y+T2rlLgVC-<)Oa9Z;Mh)L$M%*sZPG4bxRfqZyBD@=-1|DLx_gym=Y2sUI|B^q{F-rc}a~ZbmPa6Xb#M&)2WF@EOHfR z3Z7@H99J%vL*+;aJ9$n}6ouo%TsX`U1nVwY9;mREyQ9gFLayPMwr66C_8EbW7rZz_ zl-5%y*)3YjZIp==jH>{f6GFV7QWL0Y>qASW7TWd37fF%}Z27^Xxuf5|`-6HjSEU zve3yS{n(6YL0onp_w_X3CH;cBFKmpfg-aqjEbzB(*di*cpxcyRECCJ(?#~D zu(9A5&);8fT8It8(W;LMctMFlS!SUj32Y2SAuB6UorR(tlXVG2WGUBVd&V)zdjpEM zv-+waVa)L|5TiNBN&?EUl1NnPQBh`fL6pLL4u}ybGBh;Q9Ck{8bctC4dBoXPo}vFy zlf*^rXc&^3NBmwU>?Dh{=@R3X8gIuwG~ZYiO}f@{Dlq&`k28jEF@j9vwt0u@ZA@pK zwp>7jbRF~SFc;^%GH}pno>cljT8q1zbQdhHFMMOR|8K$@B{d4b$|Eu|ImS58Zu@85&U+rX07oy29-F+ac?@do6KIuJnXteTZ@cTld02V2VeRdh8sn- literal 0 HcmV?d00001 diff --git a/runelite-client/src/main/resources/net/runelite/client/runelite.properties b/runelite-client/src/main/resources/net/runelite/client/runelite.properties index b8516ea64c..684a13c581 100644 --- a/runelite-client/src/main/resources/net/runelite/client/runelite.properties +++ b/runelite-client/src/main/resources/net/runelite/client/runelite.properties @@ -1,3 +1,3 @@ runelite.title=RuneLite runelite.version=${project.version} - +runescape.version=${rs.version}