From cc026314acc213d130cacfa986321e83ac1e65a6 Mon Sep 17 00:00:00 2001 From: TheRealNull Date: Thu, 24 Dec 2020 14:14:41 -0500 Subject: [PATCH] add brand color, hook our splash into theirs --- .../client/ui/OpenOSRSSplashScreen.java | 161 +++++++++++++++++ .../client/ui/components/InfoPanel.java | 163 ++++++++++++++++++ .../client/ui/components/MessagePanel.java | 163 ++++++++++++++++++ .../java/net/runelite/client/RuneLite.java | 4 +- .../net/runelite/client/ui/ColorScheme.java | 6 + .../net/runelite/client/ui/SplashScreen.java | 6 +- .../net/runelite/client/util/LinkBrowser.java | 51 ++++++ 7 files changed, 552 insertions(+), 2 deletions(-) create mode 100644 runelite-client/src/main/java/com/openosrs/client/ui/OpenOSRSSplashScreen.java create mode 100644 runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java create mode 100644 runelite-client/src/main/java/com/openosrs/client/ui/components/MessagePanel.java diff --git a/runelite-client/src/main/java/com/openosrs/client/ui/OpenOSRSSplashScreen.java b/runelite-client/src/main/java/com/openosrs/client/ui/OpenOSRSSplashScreen.java new file mode 100644 index 0000000000..2615cb8278 --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/ui/OpenOSRSSplashScreen.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2019, TheStonedTurtle + * 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 com.openosrs.client.ui; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.ui.ClientUI; +import net.runelite.client.ui.ColorScheme; +import com.openosrs.client.ui.components.InfoPanel; +import com.openosrs.client.ui.components.MessagePanel; + +@Slf4j +public class OpenOSRSSplashScreen extends JFrame +{ + private static OpenOSRSSplashScreen INSTANCE; + public static final Dimension FRAME_SIZE = new Dimension(600, 350); + + @Getter + private final MessagePanel messagePanel = new MessagePanel(); + + private OpenOSRSSplashScreen() + { + this.setTitle("OpenOSRS"); + this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.setSize(FRAME_SIZE); + this.setLayout(new BorderLayout()); + this.setUndecorated(true); + this.setIconImage(ClientUI.ICON); + + final JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setPreferredSize(OpenOSRSSplashScreen.FRAME_SIZE); + + panel.add(new InfoPanel(), BorderLayout.EAST); + panel.add(messagePanel, BorderLayout.WEST); + + this.setContentPane(panel); + pack(); + + this.setLocationRelativeTo(null); + this.setVisible(true); + } + + public static boolean showing() + { + return INSTANCE != null; + } + + public static void setError(String title, String content) + { + if (INSTANCE != null) + { + INSTANCE.setErrorInstance(title, content); + } + } + + private void setErrorInstance(String title, String content) + { + messagePanel.setMessageContent(content); + messagePanel.setMessageTitle("Error!"); + + messagePanel.getBarLabel().setText(title); + messagePanel.getBar().setBackground(ColorScheme.PROGRESS_ERROR_COLOR.darker()); + messagePanel.getBar().setForeground(ColorScheme.PROGRESS_ERROR_COLOR); + + this.getContentPane().revalidate(); + this.getContentPane().repaint(); + } + + private void setBarText(final String text) + { + final JProgressBar bar = messagePanel.getBar(); + bar.setString(text); + bar.setStringPainted(text != null); + bar.revalidate(); + bar.repaint(); + } + + private void setMessage(final String msg, final double value) + { + messagePanel.getBarLabel().setText(msg); + messagePanel.getBar().setMaximum(1000); + messagePanel.getBar().setValue((int) (value * 1000)); + setBarText(null); + + this.getContentPane().revalidate(); + this.getContentPane().repaint(); + } + + public static void init() + { + SwingUtilities.invokeLater(() -> + { + try + { + INSTANCE = new OpenOSRSSplashScreen(); + } + catch (Exception e) + { + log.warn("Unable to start splash screen", e); + } + }); + } + + public static void close() + { + SwingUtilities.invokeLater(() -> + { + if (INSTANCE == null) + { + return; + } + + INSTANCE.setVisible(false); + INSTANCE.dispose(); + INSTANCE = null; + }); + } + + public static void stage(double startProgress, double endProgress, String progressText, int done, int total) + { + String progress = done + " / " + total; + stage(startProgress + ((endProgress - startProgress) * done / total), progressText + " " + progress); + } + + public static void stage(double overallProgress, String progressText) + { + if (INSTANCE != null) + { + INSTANCE.setMessage(progressText, overallProgress); + } + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java b/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java new file mode 100644 index 0000000000..f966797a93 --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/ui/components/InfoPanel.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019, TheStonedTurtle + * 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 com.openosrs.client.ui.components; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.MatteBorder; +import lombok.extern.slf4j.Slf4j; +import net.runelite.client.RuneLiteProperties; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import com.openosrs.client.ui.OpenOSRSSplashScreen; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.LinkBrowser; + +@Slf4j +public class InfoPanel extends JPanel +{ + private static final Color DARK_GREY = new Color(10, 10, 10, 255); + + private static final BufferedImage TRANSPARENT_LOGO = ImageUtil.getResourceStreamFromClass(InfoPanel.class, "/openosrs.png"); + static final Dimension PANEL_SIZE = new Dimension(200, OpenOSRSSplashScreen.FRAME_SIZE.height); + private static final Dimension VERSION_SIZE = new Dimension(PANEL_SIZE.width, 25); + private static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite"); + private static final File LOGS_DIR = new File(RUNELITE_DIR, "logs"); + + public InfoPanel() + { + this.setLayout(new GridBagLayout()); + this.setPreferredSize(PANEL_SIZE); + this.setBackground(new Color(38, 38, 38)); + + final GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; + c.ipady = 5; + + // Logo + final ImageIcon transparentLogo = new ImageIcon(); + if (TRANSPARENT_LOGO != null) + { + transparentLogo.setImage(TRANSPARENT_LOGO.getScaledInstance(128, 128, Image.SCALE_SMOOTH)); + } + final JLabel logo = new JLabel(transparentLogo); + + c.anchor = GridBagConstraints.NORTH; + c.weighty = 1; + this.add(logo, c); + c.gridy++; + c.anchor = GridBagConstraints.SOUTH; + c.weighty = 0; + + // OpenOSRS version + this.add(createPanelTextButton("OpenOSRS Version: " + RuneLiteProperties.getLauncherVersion()), c); + c.gridy++; + + final JLabel logsFolder = createPanelButton("Open logs folder", null, () -> LinkBrowser.openLocalFile(LOGS_DIR)); + this.add(logsFolder, c); + c.gridy++; + + final JLabel discord = createPanelButton("Get help on Discord", "Instant invite link to join the openosrs discord", () -> LinkBrowser.browse(RuneLiteProperties.getDiscordInvite())); + this.add(discord, c); + c.gridy++; + + final JLabel troubleshooting = createPanelButton("Troubleshooting steps", "Opens a link to the troubleshooting wiki", () -> LinkBrowser.browse(RuneLiteProperties.getTroubleshootingLink())); + this.add(troubleshooting, c); + c.gridy++; + + final JLabel exit = createPanelButton("Exit", "Closes the application immediately", () -> System.exit(0)); + this.add(exit, c); + c.gridy++; + } + + private static JLabel createPanelTextButton(final String title) + { + final JLabel textButton = new JLabel(title); + textButton.setFont(FontManager.getRunescapeSmallFont()); + textButton.setHorizontalAlignment(JLabel.CENTER); + textButton.setForeground(ColorScheme.BRAND_BLUE); + textButton.setBackground(null); + textButton.setPreferredSize(VERSION_SIZE); + textButton.setMinimumSize(VERSION_SIZE); + textButton.setBorder(new MatteBorder(1, 0, 0, 0, DARK_GREY)); + + return textButton; + } + + private static JLabel createPanelButton(final String name, final String tooltip, final Runnable runnable) + { + final JLabel btn = new JLabel(name, JLabel.CENTER); + btn.setToolTipText(tooltip); + btn.setOpaque(true); + btn.setBackground(null); + btn.setForeground(Color.WHITE); + btn.setFont(FontManager.getRunescapeFont()); + btn.setBorder(new CompoundBorder( + new MatteBorder(1, 0, 0, 0, DARK_GREY), + new EmptyBorder(3, 0, 3, 0)) + ); + btn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + btn.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + runnable.run(); + } + + @Override + public void mouseEntered(MouseEvent e) + { + btn.setBackground(new Color(60, 60, 60)); + btn.repaint(); + } + + @Override + public void mouseExited(MouseEvent e) + { + btn.setBackground(null); + btn.repaint(); + } + }); + + return btn; + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/com/openosrs/client/ui/components/MessagePanel.java b/runelite-client/src/main/java/com/openosrs/client/ui/components/MessagePanel.java new file mode 100644 index 0000000000..63170159e5 --- /dev/null +++ b/runelite-client/src/main/java/com/openosrs/client/ui/components/MessagePanel.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019, TheStonedTurtle + * 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 com.openosrs.client.ui.components; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.border.EmptyBorder; +import javax.swing.border.MatteBorder; +import javax.swing.plaf.basic.BasicProgressBarUI; +import lombok.AccessLevel; +import lombok.Getter; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import com.openosrs.client.ui.OpenOSRSSplashScreen; +import net.runelite.client.ui.components.CustomScrollBarUI; + +@Getter +public class MessagePanel extends JPanel +{ + private static final Dimension PANEL_SIZE = new Dimension(OpenOSRSSplashScreen.FRAME_SIZE.width - InfoPanel.PANEL_SIZE.width, OpenOSRSSplashScreen.FRAME_SIZE.height); + private static final Dimension BAR_SIZE = new Dimension(PANEL_SIZE.width, 30); + private static final int MESSAGE_AREA_PADDING = 15; + + private final JLabel titleLabel = new JLabel("Welcome to OpenOSRS"); + private final JLabel messageArea; + private final JLabel barLabel = new JLabel("Connecting with gameserver (try 1/10)"); + private final JProgressBar bar = new JProgressBar(0, 100); + + @Getter(AccessLevel.NONE) + private final JScrollPane scrollPane; + + public MessagePanel() + { + this.setPreferredSize(PANEL_SIZE); + this.setLayout(new GridBagLayout()); + this.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + final GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.NORTH; + c.weightx = 1; + c.gridx = 0; + c.gridy = 0; + c.ipady = 25; + + // main message + titleLabel.setFont(new Font(FontManager.getRunescapeFont().getName(), FontManager.getRunescapeFont().getStyle(), 32)); + titleLabel.setHorizontalAlignment(JLabel.CENTER); + titleLabel.setForeground(Color.WHITE); + this.add(titleLabel, c); + c.gridy++; + + // alternate message action + messageArea = new JLabel("
Open-source client for Old School RuneScape with more functionality and less restrictions.
") + { + @Override + public Dimension getPreferredSize() + { + final Dimension results = super.getPreferredSize(); + results.width = PANEL_SIZE.width - MESSAGE_AREA_PADDING; + return results; + } + }; + messageArea.setFont(new Font(FontManager.getRunescapeFont().getName(), FontManager.getRunescapeSmallFont().getStyle(), 16)); + messageArea.setForeground(Color.WHITE); + messageArea.setBorder(new EmptyBorder(0, MESSAGE_AREA_PADDING, 0, MESSAGE_AREA_PADDING)); + + scrollPane = new JScrollPane(messageArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0)); + scrollPane.getVerticalScrollBar().setUI(new CustomScrollBarUI()); + final JViewport viewport = scrollPane.getViewport(); + viewport.setForeground(Color.WHITE); + viewport.setBackground(ColorScheme.DARKER_GRAY_COLOR); + viewport.setOpaque(true); + + c.weighty = 1; + c.fill = 1; + this.add(scrollPane, c); + c.gridy++; + + c.weighty = 0; + c.weightx = 1; + c.ipady = 5; + + barLabel.setFont(FontManager.getRunescapeFont()); + barLabel.setHorizontalAlignment(JLabel.CENTER); + barLabel.setForeground(Color.WHITE); + barLabel.setBorder(new EmptyBorder(5, 0, 5, 0)); + this.add(barLabel, c); + c.gridy++; + + bar.setBackground(ColorScheme.BRAND_BLUE_TRANSPARENT.darker()); + bar.setForeground(ColorScheme.BRAND_BLUE); + bar.setMinimumSize(BAR_SIZE); + bar.setMaximumSize(BAR_SIZE); + bar.setBorder(new MatteBorder(0, 0, 0, 0, Color.LIGHT_GRAY)); + bar.setUI(new BasicProgressBarUI() + { + protected Color getSelectionBackground() + { + return ColorScheme.DARKER_GRAY_COLOR; + } + + protected Color getSelectionForeground() + { + return ColorScheme.DARKER_GRAY_COLOR; + } + }); + bar.setFont(FontManager.getRunescapeFont()); + bar.setVisible(true); + this.add(bar, c); + c.gridy++; + } + + public void setMessageContent(String content) + { + if (!content.startsWith(""; + } + + messageArea.setText(content); + messageArea.revalidate(); + messageArea.repaint(); + } + + public void setMessageTitle(String text) + { + titleLabel.setText(text); + titleLabel.revalidate(); + titleLabel.repaint(); + } +} \ No newline at end of file diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 865c94d847..be3b14c976 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -74,6 +74,7 @@ import net.runelite.client.rs.ClientUpdateCheckMode; import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.FatalErrorDialog; +import com.openosrs.client.ui.OpenOSRSSplashScreen; import net.runelite.client.ui.SplashScreen; import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayRenderer; @@ -248,6 +249,7 @@ public class RuneLite final OkHttpClient okHttpClient = okHttpClientBuilder.build(); SplashScreen.init(); + OpenOSRSSplashScreen.init(); SplashScreen.stage(0, "Retrieving client", ""); try @@ -466,6 +468,6 @@ public class RuneLite //Fixes win10 scaling when not 100% while using Anti-Aliasing with GPU System.setProperty("sun.java2d.uiScale", "1.0"); - System.setProperty("runelite.launcher.version", "OpenOSRS Injected"); + System.setProperty("runelite.launcher.version", "" + RuneLiteAPI.getVersion()); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java b/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java index 5be1250547..b66c62d7fd 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ColorScheme.java @@ -31,6 +31,12 @@ import java.awt.Color; */ public class ColorScheme { + /* The blue color used for the branding's accents */ + public static final Color BRAND_BLUE = new Color(25, 194, 255); + + /* The blue color used for the branding's accents, with lowered opacity */ + public static final Color BRAND_BLUE_TRANSPARENT = new Color(25, 194, 255, 120); + /* The orange color used for the branding's accents */ public static final Color BRAND_ORANGE = new Color(220, 138, 0); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java b/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java index 77cac7340b..ad5e2325ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/SplashScreen.java @@ -24,6 +24,7 @@ */ package net.runelite.client.ui; +import com.openosrs.client.ui.OpenOSRSSplashScreen; import java.awt.Color; import java.awt.Container; import java.awt.Font; @@ -130,7 +131,7 @@ public class SplashScreen extends JFrame implements ActionListener timer.setRepeats(true); timer.start(); - setVisible(true); + //setVisible(true); } @Override @@ -207,11 +208,13 @@ public class SplashScreen extends JFrame implements ActionListener INSTANCE.dispose(); INSTANCE = null; }); + OpenOSRSSplashScreen.close(); } public static void stage(double overallProgress, @Nullable String actionText, String subActionText) { stage(overallProgress, actionText, subActionText, null); + OpenOSRSSplashScreen.stage(overallProgress, subActionText); } public static void stage(double startProgress, double endProgress, @@ -230,6 +233,7 @@ public class SplashScreen extends JFrame implements ActionListener progress = done + " / " + total; } stage(startProgress + ((endProgress - startProgress) * done / total), actionText, subActionText, progress); + OpenOSRSSplashScreen.stage(startProgress, endProgress, subActionText, done, total); } public static void stage(double overallProgress, @Nullable String actionText, String subActionText, @Nullable String progressText) diff --git a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java index e8965029c1..5637180ad0 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java +++ b/runelite-client/src/main/java/net/runelite/client/util/LinkBrowser.java @@ -207,4 +207,55 @@ public class LinkBrowser } }); } + + + /** + * Tries to open the specified {@code File} with the systems default text editor. If operation fails + * an error message is displayed with the option to copy the absolute file path to clipboard. + * + * @param file the File instance of the log file + * @return did the file open successfully? + */ + public static boolean openLocalFile(final File file) + { + if (file == null || !file.exists()) + { + return false; + } + + if (attemptOpenLocalFile(file)) + { + log.debug("Opened log file through Desktop#edit to {}", file); + return true; + } + + showMessageBox("Unable to open log file. Press 'OK' and the file path will be copied to your clipboard", file.getAbsolutePath()); + return false; + } + + private static boolean attemptOpenLocalFile(final File file) + { + if (!Desktop.isDesktopSupported()) + { + return false; + } + + final Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.OPEN)) + { + return false; + } + + try + { + desktop.open(file); + return true; + } + catch (IOException ex) + { + log.warn("Failed to open Desktop#edit {}", file, ex); + return false; + } + } }