From 4119db3c4fc064019bccf1ed113214bf3abeb16d Mon Sep 17 00:00:00 2001 From: Owain van Brakel Date: Thu, 27 Feb 2020 05:13:24 +0100 Subject: [PATCH] externalmanager: Rework panel --- .../events/ExternalRepositoryChanged.java | 35 + .../client/plugins/ExternalPluginManager.java | 20 +- .../plugins/openosrs/OpenOSRSPlugin.java | 4 +- .../externals/ExternalPluginManagerPanel.java | 152 ++++ ...ginManagerPanel.java => PluginsPanel.java} | 711 ++++++------------ .../openosrs/externals/RadioButtonPanel.java | 56 -- .../openosrs/externals/RepositoryBox.java | 155 ++++ .../openosrs/externals/RepositoryPanel.java | 49 ++ .../runelite/client/ui/JMultilineLabel.java | 27 + .../openosrs/externals/config_back_icon.png | Bin 267 -> 0 bytes .../openosrs/externals/discord_icon.png | Bin 0 -> 312 bytes 11 files changed, 682 insertions(+), 527 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/events/ExternalRepositoryChanged.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java rename runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/{PluginManagerPanel.java => PluginsPanel.java} (50%) delete mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RadioButtonPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java create mode 100644 runelite-client/src/main/java/net/runelite/client/ui/JMultilineLabel.java delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/config_back_icon.png create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/discord_icon.png diff --git a/runelite-client/src/main/java/net/runelite/client/events/ExternalRepositoryChanged.java b/runelite-client/src/main/java/net/runelite/client/events/ExternalRepositoryChanged.java new file mode 100644 index 0000000000..7ae9e3624e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/events/ExternalRepositoryChanged.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 Owain van Brakel + * 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.Data; +import net.runelite.api.events.Event; + +@Data +public class ExternalRepositoryChanged implements Event +{ + private final String owner; + private final boolean added; +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java index ecee004d6c..eec6d2bb2e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/ExternalPluginManager.java @@ -48,6 +48,7 @@ import net.runelite.client.config.ConfigManager; import net.runelite.client.config.OpenOSRSConfig; import net.runelite.client.eventbus.EventBus; import net.runelite.client.events.ExternalPluginChanged; +import net.runelite.client.events.ExternalRepositoryChanged; import net.runelite.client.ui.RuneLiteSplashScreen; import net.runelite.client.util.SwingUtil; import org.pf4j.DefaultPluginManager; @@ -262,6 +263,7 @@ class ExternalPluginManager { DefaultUpdateRepository respository = new DefaultUpdateRepository(owner + toRepositoryUrl(owner, name), toRepositoryUrl(owner, name)); updateManager.addRepository(respository); + eventBus.post(ExternalRepositoryChanged.class, new ExternalRepositoryChanged(owner + toRepositoryUrl(owner, name), true)); saveConfig(); } catch (MalformedURLException e) @@ -273,6 +275,7 @@ class ExternalPluginManager public void removeRepository(String owner) { updateManager.removeRepository(owner); + eventBus.post(ExternalRepositoryChanged.class, new ExternalRepositoryChanged(owner, false)); saveConfig(); } @@ -594,7 +597,7 @@ class ExternalPluginManager return null; } - public void install(String pluginId) throws VerifyException + public boolean install(String pluginId) throws VerifyException { if (getDisabledPlugins().contains(pluginId)) @@ -604,12 +607,12 @@ class ExternalPluginManager startPlugins(loadPlugin(pluginId), true, false); - return; + return true; } if (getStartedPlugins().stream().anyMatch(ev -> ev.getPluginId().equals(pluginId))) { - return; + return true; } // Null version returns the last release version of this plugin for given system version @@ -629,9 +632,10 @@ class ExternalPluginManager } catch (InvocationTargetException | InterruptedException ignored) { + return false; } - return; + return true; } updateManager.installPlugin(pluginId, null); @@ -649,20 +653,22 @@ class ExternalPluginManager install(pluginId); } - + return false; } - public void uninstall(String pluginId) + public boolean uninstall(String pluginId) { Path pluginPath = stopPlugin(pluginId); if (pluginPath == null) { - return; + return false; } externalPluginManager.stopPlugin(pluginId); externalPluginManager.disablePlugin(pluginId); + + return true; } public void update() diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java index 69558520b2..e7d1dc858a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/OpenOSRSPlugin.java @@ -45,7 +45,7 @@ import net.runelite.client.input.KeyListener; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import net.runelite.client.plugins.openosrs.externals.PluginManagerPanel; +import net.runelite.client.plugins.openosrs.externals.ExternalPluginManagerPanel; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.NavigationButton; import net.runelite.client.util.HotkeyListener; @@ -98,7 +98,7 @@ public class OpenOSRSPlugin extends Plugin @Override protected void startUp() { - PluginManagerPanel panel = injector.getInstance(PluginManagerPanel.class); + ExternalPluginManagerPanel panel = injector.getInstance(ExternalPluginManagerPanel.class); final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "externalmanager_icon.png"); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java new file mode 100644 index 0000000000..e01e2aa509 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/ExternalPluginManagerPanel.java @@ -0,0 +1,152 @@ +package net.runelite.client.plugins.openosrs.externals; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.concurrent.ScheduledExecutorService; +import javax.inject.Inject; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.border.EmptyBorder; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.plugins.ExternalPluginManager; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.PluginPanel; +import net.runelite.client.util.ImageUtil; + +public class ExternalPluginManagerPanel extends PluginPanel +{ + private static final ImageIcon ADD_ICON; + private static final ImageIcon ADD_HOVER_ICON; + + static + { + final BufferedImage addIcon = + ImageUtil.recolorImage( + ImageUtil.getResourceStreamFromClass(ExternalPluginManagerPanel.class, "add_icon.png"), ColorScheme.BRAND_BLUE + ); + ADD_ICON = new ImageIcon(addIcon); + ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); + } + + private final ExternalPluginManager externalPluginManager; + private final ScheduledExecutorService executor; + private final EventBus eventBus; + + @Inject + private ExternalPluginManagerPanel(ExternalPluginManager externalPluginManager, ScheduledExecutorService executor, EventBus eventBus) + { + super(false); + + this.externalPluginManager = externalPluginManager; + this.executor = executor; + this.eventBus = eventBus; + + buildPanel(); + } + + private void buildPanel() + { + removeAll(); + + setLayout(new BorderLayout(0, 10)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + + add(titleBar(), BorderLayout.NORTH); + add(tabbedPane(), BorderLayout.CENTER); + + revalidate(); + repaint(); + } + + private JPanel titleBar() + { + JPanel titlePanel = new JPanel(new BorderLayout()); + titlePanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + + JLabel title = new JLabel(); + JLabel addRepo = new JLabel(ADD_ICON); + + title.setText("External Plugin Manager"); + title.setForeground(Color.WHITE); + + addRepo.setToolTipText("Add new repository"); + addRepo.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent mouseEvent) + { + JTextField owner = new JTextField(); + JTextField name = new JTextField(); + Object[] message = { + "Github Repository owner:", owner, + "Github Repository name:", name + }; + + int option = JOptionPane.showConfirmDialog(null, message, "Add repository", JOptionPane.OK_CANCEL_OPTION); + if (option != JOptionPane.OK_OPTION || owner.getText().equals("") || name.getText().equals("")) + { + return; + } + + if (ExternalPluginManager.testRepository(owner.getText(), name.getText())) + { + JOptionPane.showMessageDialog(null, "This doesn't appear to be a valid repository.", "Error!", JOptionPane.ERROR_MESSAGE); + return; + } + + externalPluginManager.addRepository(owner.getText(), name.getText()); + } + + @Override + public void mouseEntered(MouseEvent mouseEvent) + { + addRepo.setIcon(ADD_HOVER_ICON); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) + { + addRepo.setIcon(ADD_ICON); + } + }); + + titlePanel.add(title, BorderLayout.WEST); + titlePanel.add(addRepo, BorderLayout.EAST); + + return titlePanel; + } + + private JTabbedPane tabbedPane() + { + JTabbedPane mainTabPane = new JTabbedPane(); + + PluginsPanel pluginPanel = new PluginsPanel(this.externalPluginManager, this.executor, this.eventBus); + JScrollPane repositoryPanel = wrapContainer(new RepositoryPanel(this.externalPluginManager, this.eventBus)); + + mainTabPane.add("Plugins", pluginPanel); + mainTabPane.add("Repositories", repositoryPanel); + + return mainTabPane; + } + + static JScrollPane wrapContainer(final JPanel container) + { + final JPanel wrapped = new JPanel(new BorderLayout()); + wrapped.add(container, BorderLayout.NORTH); + + final JScrollPane scroller = new JScrollPane(wrapped); + scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scroller.getVerticalScrollBar().setPreferredSize(new Dimension(8, 0)); + + return scroller; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginManagerPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginsPanel.java similarity index 50% rename from runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginManagerPanel.java rename to runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginsPanel.java index bba3feda80..2060e13e76 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginManagerPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/PluginsPanel.java @@ -18,28 +18,24 @@ import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; -import javax.inject.Inject; -import javax.swing.BoxLayout; import javax.swing.ImageIcon; +import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollBar; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.JToggleButton; +import javax.swing.JTabbedPane; import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.border.EmptyBorder; import lombok.extern.slf4j.Slf4j; import net.runelite.client.eventbus.EventBus; import net.runelite.client.events.ExternalPluginChanged; -import net.runelite.client.events.ExternalPluginsLoaded; +import net.runelite.client.events.ExternalRepositoryChanged; import net.runelite.client.plugins.ExternalPluginManager; +import static net.runelite.client.plugins.openosrs.externals.ExternalPluginManagerPanel.wrapContainer; import net.runelite.client.ui.ColorScheme; -import net.runelite.client.ui.DynamicGridLayout; import net.runelite.client.ui.FontManager; import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.components.IconTextField; @@ -54,14 +50,9 @@ import org.pf4j.update.UpdateRepository; import org.pf4j.update.VerifyException; @Slf4j -public class PluginManagerPanel extends PluginPanel +public class PluginsPanel extends JPanel { private static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance(); - - private static final ImageIcon SECTION_EXPAND_ICON; - private static final ImageIcon SECTION_EXPAND_ICON_HOVER; - private static final ImageIcon SECTION_RETRACT_ICON; - private static final ImageIcon SECTION_RETRACT_ICON_HOVER; private static final ImageIcon ADD_ICON; private static final ImageIcon ADD_HOVER_ICON; private static final ImageIcon DELETE_ICON; @@ -71,20 +62,9 @@ public class PluginManagerPanel extends PluginPanel static { - final BufferedImage backIcon = ImageUtil.getResourceStreamFromClass(PluginManagerPanel.class, "config_back_icon.png"); - final BufferedImage orangeBackIcon = ImageUtil.fillImage(backIcon, ColorScheme.BRAND_BLUE); - - final BufferedImage sectionRetractIcon = ImageUtil.rotateImage(orangeBackIcon, Math.PI * 1.5); - SECTION_RETRACT_ICON = new ImageIcon(sectionRetractIcon); - SECTION_RETRACT_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(sectionRetractIcon, -100)); - - final BufferedImage sectionExpandIcon = ImageUtil.rotateImage(orangeBackIcon, Math.PI); - SECTION_EXPAND_ICON = new ImageIcon(sectionExpandIcon); - SECTION_EXPAND_ICON_HOVER = new ImageIcon(ImageUtil.alphaOffset(sectionExpandIcon, -100)); - final BufferedImage addIcon = ImageUtil.recolorImage( - ImageUtil.getResourceStreamFromClass(PluginManagerPanel.class, "add_icon.png"), ColorScheme.BRAND_BLUE + ImageUtil.getResourceStreamFromClass(PluginsPanel.class, "add_icon.png"), ColorScheme.BRAND_BLUE ); ADD_ICON = new ImageIcon(addIcon); ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f)); @@ -92,7 +72,7 @@ public class PluginManagerPanel extends PluginPanel final BufferedImage deleteImg = ImageUtil.recolorImage( ImageUtil.resizeCanvas( - ImageUtil.getResourceStreamFromClass(PluginManagerPanel.class, "delete_icon.png"), 14, 14 + ImageUtil.getResourceStreamFromClass(PluginsPanel.class, "delete_icon.png"), 14, 14 ), ColorScheme.BRAND_BLUE ); DELETE_ICON = new ImageIcon(deleteImg); @@ -105,35 +85,73 @@ public class PluginManagerPanel extends PluginPanel private final ExternalPluginManager externalPluginManager; private final UpdateManager updateManager; private final ScheduledExecutorService executor; + private final EventBus eventBus; + private final IconTextField searchBar = new IconTextField(); + private final JPanel filterwrapper = new JPanel(new BorderLayout(0, 10)); private final List installedPluginsList = new ArrayList<>(); private final List availablePluginsList = new ArrayList<>(); - private final JPanel repositoriesPanel = new JPanel(); private final JPanel installedPluginsPanel = new JPanel(new GridBagLayout()); private final JPanel availablePluginsPanel = new JPanel(new GridBagLayout()); - private String filterMode = "Available plugins"; - private int scrollBarPosition; - private JScrollBar scrollbar; + + private JComboBox filterComboBox; private Set deps; - @Inject - private PluginManagerPanel(ExternalPluginManager externalPluginManager, EventBus eventBus, ScheduledExecutorService executor) + PluginsPanel(ExternalPluginManager externalPluginManager, ScheduledExecutorService executor, EventBus eventBus) { - super(false); - this.externalPluginManager = externalPluginManager; this.updateManager = externalPluginManager.getUpdateManager(); this.executor = executor; + this.eventBus = eventBus; - eventBus.subscribe(ExternalPluginsLoaded.class, "loading-externals", (e) -> { - eventBus.unregister("loading-externals"); - eventBus.subscribe(ExternalPluginChanged.class, this, this::onExternalPluginChanged); + setLayout(new BorderLayout(0, 10)); + setBackground(ColorScheme.DARK_GRAY_COLOR); + + buildFilter(); + + JTabbedPane mainTabPane = new JTabbedPane(); + + mainTabPane.add("Installed", wrapContainer(installedPluginsPanel())); + mainTabPane.add("Available", wrapContainer(availablePluginsPanel())); + + add(filterwrapper, BorderLayout.NORTH); + add(mainTabPane, BorderLayout.CENTER); + + eventBus.subscribe(ExternalPluginChanged.class, this, this::onExternalPluginChanged); + eventBus.subscribe(ExternalRepositoryChanged.class, this, (e) -> { + buildFilter(); reloadPlugins(); + repaint(); }); + reloadPlugins(); + } + + private void buildFilter() + { + filterwrapper.removeAll(); + DeferredDocumentChangedListener listener = new DeferredDocumentChangedListener(); listener.addChangeListener(e -> - onSearchBarChanged()); + { + installedPlugins(); + availablePlugins(); + }); + + filterwrapper.setBorder(new EmptyBorder(10, 10, 0, 10)); + + List repositories = getRepositories(); + filterComboBox = new JComboBox<>(repositories.toArray(new String[0])); + filterComboBox.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH - 20, 30)); + filterComboBox.addActionListener(e -> { + installedPlugins(); + availablePlugins(); + }); + + if (repositories.size() > 2) + { + filterwrapper.add(filterComboBox, BorderLayout.NORTH); + } searchBar.setIcon(IconTextField.Icon.SEARCH); searchBar.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH - 20, 30)); @@ -141,151 +159,19 @@ public class PluginManagerPanel extends PluginPanel searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR); searchBar.getDocument().addDocumentListener(listener); - buildPanel(); + filterwrapper.add(searchBar, BorderLayout.CENTER); } - private static boolean mismatchesSearchTerms(String search, PluginInfo pluginInfo) + private List getRepositories() { - final String[] searchTerms = search.toLowerCase().split(" "); - final String[] pluginTerms = (pluginInfo.name + " " + pluginInfo.description).toLowerCase().split("[/\\s]"); - for (String term : searchTerms) + List repositories = new ArrayList<>(); + repositories.add("All"); + for (UpdateRepository updateRepository : this.updateManager.getRepositories()) { - if (Arrays.stream(pluginTerms).noneMatch((t) -> t.contains(term) || - DISTANCE.apply(t, term) > 0.9)) - { - return true; - } - } - return false; - } - - private JPanel addSection(String name, JPanel sectionContent) - { - final JPanel section = new JPanel(); - section.setLayout(new BoxLayout(section, BoxLayout.Y_AXIS)); - - JPanel item = new JPanel(); - item.setLayout(new BorderLayout()); - - JLabel headerLabel = new JLabel(name); - headerLabel.setFont(FontManager.getRunescapeFont()); - headerLabel.setForeground(ColorScheme.BRAND_BLUE); - - final JToggleButton collapse = new JToggleButton(SECTION_EXPAND_ICON); - - SwingUtil.removeButtonDecorations(collapse); - collapse.setRolloverIcon(SECTION_EXPAND_ICON_HOVER); - collapse.setSelectedIcon(SECTION_RETRACT_ICON); - collapse.setRolloverSelectedIcon(SECTION_RETRACT_ICON_HOVER); - collapse.setToolTipText("Retract"); - collapse.setPreferredSize(new Dimension(20, 20)); - collapse.setFont(collapse.getFont().deriveFont(16.0f)); - collapse.setBorder(null); - collapse.setMargin(new Insets(0, 0, 0, 0)); - headerLabel.setBorder(new EmptyBorder(0, 6, 0, 0)); - - item.add(collapse, BorderLayout.WEST); - item.add(headerLabel, BorderLayout.CENTER); - - final JPanel sectionContents = new JPanel(); - sectionContents.setLayout(new DynamicGridLayout(0, 1, 0, 5)); - sectionContents.setBorder(new EmptyBorder(6, 5, 0, 0)); - section.add(item, BorderLayout.NORTH); - section.add(sectionContents, BorderLayout.SOUTH); - - sectionContents.add(sectionContent); - - final MouseAdapter adapter = new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - toggleSection(collapse, sectionContents); - } - }; - collapse.addActionListener(e -> toggleSection(collapse, sectionContents)); - headerLabel.addMouseListener(adapter); - - return section; - } - - private void toggleSection(JToggleButton button, JPanel contents) - { - boolean newState = !contents.isVisible(); - button.setSelected(newState); - contents.setVisible(newState); - button.setToolTipText(newState ? "Retract" : "Expand"); - SwingUtilities.invokeLater(() -> - { - contents.revalidate(); - contents.repaint(); - }); - } - - private JPanel filterPanel() - { - JPanel filterPanel = new JPanel(); - filterPanel.setLayout(new BorderLayout(0, 5)); - filterPanel.setBorder(new EmptyBorder(0, 10, 10, 10)); - - JRadioButton repositories = new JRadioButton("Repositories"); - repositories.setSelected(filterMode.equals("Repositories")); - JRadioButton plugins = new JRadioButton("Plugins"); - plugins.setSelected(filterMode.contains("plugins")); - - JRadioButton available = new JRadioButton("Available"); - available.setSelected(filterMode.contains("Available")); - JRadioButton installed = new JRadioButton("Installed"); - installed.setSelected(filterMode.contains("Installed")); - - repositories.addActionListener(ev -> { - filterMode = "Repositories"; - buildPanel(); - }); - - plugins.addActionListener(ev -> { - filterMode = "Available plugins"; - onSearchBarChanged(); - buildPanel(); - }); - - available.addActionListener(ev -> { - filterMode = "Available plugins"; - onSearchBarChanged(); - buildPanel(); - }); - - installed.addActionListener(ev -> { - filterMode = "Installed plugins"; - onSearchBarChanged(); - buildPanel(); - }); - - RadioButtonPanel mainRadioPanel = new RadioButtonPanel("Show", repositories, plugins); - RadioButtonPanel pluginRadioPanel = new RadioButtonPanel("Plugins", available, installed); - - filterPanel.add(mainRadioPanel, BorderLayout.NORTH); - - if (!filterMode.equals("Repositories")) - { - filterPanel.add(pluginRadioPanel, BorderLayout.CENTER); + repositories.add(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")); } - return filterPanel; - } - - private void buildPanel() - { - removeAll(); - - setLayout(new BorderLayout(0, 10)); - setBackground(ColorScheme.DARK_GRAY_COLOR); - - add(titleBar(), BorderLayout.NORTH); - add(wrapContainer(getContentPanels()), BorderLayout.CENTER); - - revalidate(); - repaint(); + return repositories; } private JLabel titleLabel(String text) @@ -300,81 +186,97 @@ public class PluginManagerPanel extends PluginPanel return title; } - private JPanel titleBar() + private JPanel installedPluginsPanel() { - JPanel titlePanel = new JPanel(new BorderLayout()); - titlePanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + JPanel installedPluginsContainer = new JPanel(); + installedPluginsContainer.setLayout(new BorderLayout(0, 5)); + installedPluginsContainer.setBorder(new EmptyBorder(0, 10, 10, 10)); + installedPluginsContainer.add(installedPluginsPanel, BorderLayout.CENTER); - JLabel title = new JLabel(); - JLabel addRepo = new JLabel(ADD_ICON); - - title.setText("External Plugin Manager"); - title.setForeground(Color.WHITE); - - addRepo.setToolTipText("Add new repository"); - addRepo.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseEvent) - { - JTextField owner = new JTextField(); - JTextField name = new JTextField(); - Object[] message = { - "Github Repository owner:", owner, - "Github Repository name:", name - }; - - int option = JOptionPane.showConfirmDialog(null, message, "Add repository", JOptionPane.OK_CANCEL_OPTION); - if (option != JOptionPane.OK_OPTION || owner.getText().equals("") || name.getText().equals("")) - { - return; - } - - if (ExternalPluginManager.testRepository(owner.getText(), name.getText())) - { - JOptionPane.showMessageDialog(null, "This doesn't appear to be a valid repository.", "Error!", JOptionPane.ERROR_MESSAGE); - return; - } - - externalPluginManager.addRepository(owner.getText(), name.getText()); - - repositories(); - reloadPlugins(); - buildPanel(); - } - - @Override - public void mouseEntered(MouseEvent mouseEvent) - { - addRepo.setIcon(ADD_HOVER_ICON); - } - - @Override - public void mouseExited(MouseEvent mouseEvent) - { - addRepo.setIcon(ADD_ICON); - } - }); - - titlePanel.add(title, BorderLayout.WEST); - titlePanel.add(addRepo, BorderLayout.EAST); - - return titlePanel; + return installedPluginsContainer; } - // Wrap the panel inside a scroll pane - private JScrollPane wrapContainer(final JPanel container) + private JPanel availablePluginsPanel() { - final JPanel wrapped = new JPanel(new BorderLayout()); - wrapped.add(container, BorderLayout.NORTH); + JPanel availablePluginsContainer = new JPanel(); + availablePluginsContainer.setLayout(new BorderLayout(0, 5)); + availablePluginsContainer.setBorder(new EmptyBorder(0, 10, 10, 10)); + availablePluginsContainer.add(availablePluginsPanel, BorderLayout.CENTER); - final JScrollPane scroller = new JScrollPane(wrapped); - scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scroller.getVerticalScrollBar().setPreferredSize(new Dimension(8, 0)); + return availablePluginsContainer; + } - this.scrollbar = scroller.getVerticalScrollBar(); + static boolean mismatchesSearchTerms(String search, PluginInfo pluginInfo) + { + final String[] searchTerms = search.toLowerCase().split(" "); + final String[] pluginTerms = (pluginInfo.name + " " + pluginInfo.description).toLowerCase().split("[/\\s]"); + for (String term : searchTerms) + { + if (Arrays.stream(pluginTerms).noneMatch((t) -> t.contains(term) || + DISTANCE.apply(t, term) > 0.9)) + { + return true; + } + } + return false; + } - return scroller; + private void reloadPlugins() + { + fetchPlugins(); + + try + { + SwingUtil.syncExec(() -> { + this.installedPlugins(); + this.availablePlugins(); + }); + + } + catch (InvocationTargetException | InterruptedException e) + { + e.printStackTrace(); + } + } + + private void fetchPlugins() + { + List availablePlugins = null; + List plugins = null; + List disabledPlugins = externalPluginManager.getDisabledPlugins(); + + try + { + availablePlugins = updateManager.getAvailablePlugins(); + plugins = updateManager.getPlugins(); + } + catch (JsonSyntaxException ex) + { + log.error(String.valueOf(ex)); + } + + if (availablePlugins == null || plugins == null) + { + JOptionPane.showMessageDialog(null, "The external plugin list could not be loaded.", "Error", JOptionPane.ERROR_MESSAGE); + return; + } + + availablePluginsList.clear(); + installedPluginsList.clear(); + + deps = externalPluginManager.getDependencies(); + + for (PluginInfo pluginInfo : plugins) + { + if (availablePlugins.contains(pluginInfo) || disabledPlugins.contains(pluginInfo.id)) + { + availablePluginsList.add(pluginInfo); + } + else + { + installedPluginsList.add(pluginInfo); + } + } } private void onExternalPluginChanged(ExternalPluginChanged externalPluginChanged) @@ -444,205 +346,8 @@ public class PluginManagerPanel extends PluginPanel } } - private void reloadPlugins() - { - fetchPlugins(); - - try - { - SwingUtil.syncExec(() -> { - this.installedPlugins(); - this.availablePlugins(); - - resetScrollValue(); - }); - - } - catch (InvocationTargetException | InterruptedException e) - { - e.printStackTrace(); - } - - resetScrollValue(); - } - - private void onSearchBarChanged() - { - if (filterMode.contains("Installed plugins")) - { - installedPlugins(); - } - else if (filterMode.contains("Available plugins")) - { - availablePlugins(); - } - } - - private JPanel getContentPanels() - { - JPanel contentPanel = new JPanel(); - contentPanel.setLayout(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(5, 0, 5, 0); - - contentPanel.add(addSection("Filter", filterPanel()), c); - - if (filterMode.equals("Repositories")) - { - c.gridy++; - contentPanel.add(repositoriesPanel(), c); - } - else if (filterMode.contains("Installed plugins")) - { - c.gridy++; - contentPanel.add(installedPluginsPanel(), c); - } - else if (filterMode.contains("Available plugins")) - { - c.gridy++; - contentPanel.add(availablePluginsPanel(), c); - } - - return contentPanel; - } - - private JPanel repositoriesPanel() - { - JPanel installedRepositoriesPanel = new JPanel(); - installedRepositoriesPanel.setLayout(new BorderLayout(0, 5)); - installedRepositoriesPanel.setBorder(new EmptyBorder(0, 10, 10, 10)); - installedRepositoriesPanel.add(titleLabel("Repositories"), BorderLayout.NORTH); - installedRepositoriesPanel.add(repositoriesPanel, BorderLayout.CENTER); - - repositories(); - - return installedRepositoriesPanel; - } - - private JPanel installedPluginsPanel() - { - JPanel installedPluginsContainer = new JPanel(); - installedPluginsContainer.setLayout(new BorderLayout(0, 5)); - installedPluginsContainer.setBorder(new EmptyBorder(0, 10, 10, 10)); - installedPluginsContainer.add(titleLabel(filterMode), BorderLayout.NORTH); - installedPluginsContainer.add(searchBar, BorderLayout.CENTER); - installedPluginsContainer.add(installedPluginsPanel, BorderLayout.SOUTH); - - return installedPluginsContainer; - } - - private JPanel availablePluginsPanel() - { - JPanel availablePluginsContainer = new JPanel(); - availablePluginsContainer.setLayout(new BorderLayout(0, 5)); - availablePluginsContainer.setBorder(new EmptyBorder(0, 10, 10, 10)); - availablePluginsContainer.add(titleLabel(filterMode), BorderLayout.NORTH); - availablePluginsContainer.add(searchBar, BorderLayout.CENTER); - availablePluginsContainer.add(availablePluginsPanel, BorderLayout.SOUTH); - - return availablePluginsContainer; - } - - private void repositories() - { - repositoriesPanel.removeAll(); - repositoriesPanel.setLayout(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - - for (UpdateRepository repository : externalPluginManager.getRepositories()) - { - String name = repository.getId().replace(repository.getUrl().toString(), ""); - ExternalBox repositoryBox = new ExternalBox(name, repository.getUrl()); - - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1.0; - c.gridy += 1; - c.insets = new Insets(5, 0, 0, 0); - - repositoriesPanel.add(repositoryBox, c); - - if (name.equals("OpenOSRS")) - { - repositoryBox.install.setVisible(false); - continue; - } - - repositoryBox.install.setIcon(DELETE_ICON); - repositoryBox.install.setToolTipText("Remove"); - repositoryBox.install.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent e) - { - externalPluginManager.removeRepository(repository.getId()); - - repositories(); - reloadPlugins(); - } - - @Override - public void mouseEntered(MouseEvent e) - { - repositoryBox.install.setIcon(DELETE_HOVER_ICON); - } - - @Override - public void mouseExited(MouseEvent e) - { - repositoryBox.install.setIcon(DELETE_ICON); - } - }); - } - } - - private void fetchPlugins() - { - List availablePlugins = null; - List plugins = null; - List disabledPlugins = externalPluginManager.getDisabledPlugins(); - - try - { - availablePlugins = updateManager.getAvailablePlugins(); - plugins = updateManager.getPlugins(); - } - catch (JsonSyntaxException ex) - { - log.error(String.valueOf(ex)); - } - - if (availablePlugins == null || plugins == null) - { - JOptionPane.showMessageDialog(null, "The external plugin list could not be loaded.", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - - availablePluginsList.clear(); - installedPluginsList.clear(); - deps = externalPluginManager.getDependencies(); - - for (PluginInfo pluginInfo : plugins) - { - if (availablePlugins.contains(pluginInfo) || disabledPlugins.contains(pluginInfo.id)) - { - availablePluginsList.add(pluginInfo); - } - else - { - installedPluginsList.add(pluginInfo); - } - } - } - private void installedPlugins() { - JPanel panel = new JPanel(); - panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); installedPluginsPanel.removeAll(); @@ -650,12 +355,30 @@ public class PluginManagerPanel extends PluginPanel for (PluginInfo pluginInfo : installedPluginsList) { - if (!search.equals("") && mismatchesSearchTerms(search, pluginInfo)) { continue; } + if (filterComboBox.getSelectedIndex() != 0) + { + boolean filtered = true; + String filter = String.valueOf(filterComboBox.getSelectedItem()); + for (UpdateRepository updateRepository : updateManager.getRepositories()) + { + if (filter.equals(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")) && + pluginInfo.getRepositoryId().equals(updateRepository.getId())) + { + filtered = false; + } + } + + if (filtered) + { + continue; + } + } + ExternalBox pluginBox = new ExternalBox(pluginInfo); pluginBox.pluginInfo = pluginInfo; @@ -676,8 +399,6 @@ public class PluginManagerPanel extends PluginPanel private void availablePlugins() { - JPanel panel = new JPanel(); - panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); availablePluginsPanel.removeAll(); @@ -690,6 +411,25 @@ public class PluginManagerPanel extends PluginPanel continue; } + if (filterComboBox.getSelectedIndex() != 0) + { + boolean filtered = true; + String filter = String.valueOf(filterComboBox.getSelectedItem()); + for (UpdateRepository updateRepository : updateManager.getRepositories()) + { + if (filter.equals(updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", "")) && + pluginInfo.getRepositoryId().equals(updateRepository.getId())) + { + filtered = false; + } + } + + if (filtered) + { + continue; + } + } + ExternalBox pluginBox = new ExternalBox(pluginInfo); pluginBox.pluginInfo = pluginInfo; @@ -708,6 +448,7 @@ public class PluginManagerPanel extends PluginPanel } } + private void pluginInstallButton(JLabel install, PluginInfo pluginInfo, boolean installed, boolean hideAction) { install.setIcon(installed ? hideAction ? DELETE_ICON_GRAY : DELETE_ICON : ADD_ICON); @@ -720,8 +461,6 @@ public class PluginManagerPanel extends PluginPanel @Override public void mousePressed(MouseEvent e) { - saveScrollValue(); - if (installed) { if (hideAction) @@ -732,14 +471,70 @@ public class PluginManagerPanel extends PluginPanel { install.setIcon(null); install.setText("Uninstalling"); - executor.submit(() -> externalPluginManager.uninstall(pluginInfo.id)); + + SwingWorker worker = new SwingWorker<>() + { + @Override + protected Boolean doInBackground() + { + return externalPluginManager.uninstall(pluginInfo.id); + } + + @Override + protected void done() + { + + boolean status = false; + try + { + status = get(); + } + catch (InterruptedException | ExecutionException e) + { + } + + if (!status) + { + pluginInstallButton(install, pluginInfo, installed, hideAction); + } + } + }; + worker.execute(); } } else { install.setIcon(null); install.setText("Installing"); - executor.submit(() -> installPlugin(pluginInfo)); + + SwingWorker worker = new SwingWorker<>() + { + @Override + protected Boolean doInBackground() + { + return installPlugin(pluginInfo); + } + + @Override + protected void done() + { + + boolean status = false; + try + { + status = get(); + } + catch (InterruptedException | ExecutionException e) + { + } + + if (!status) + { + pluginInstallButton(install, pluginInfo, installed, hideAction); + } + } + }; + worker.execute(); } } @@ -767,11 +562,11 @@ public class PluginManagerPanel extends PluginPanel }); } - private void installPlugin(PluginInfo pluginInfo) + private boolean installPlugin(PluginInfo pluginInfo) { try { - externalPluginManager.install(pluginInfo.id); + return externalPluginManager.install(pluginInfo.id); } catch (VerifyException ex) { @@ -784,15 +579,7 @@ public class PluginManagerPanel extends PluginPanel { } } - } - private void saveScrollValue() - { - scrollBarPosition = scrollbar.getValue(); - } - - private void resetScrollValue() - { - scrollbar.setValue(scrollBarPosition); + return false; } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RadioButtonPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RadioButtonPanel.java deleted file mode 100644 index 27c4ac3b97..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RadioButtonPanel.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.runelite.client.plugins.openosrs.externals; - -import java.awt.FlowLayout; -import java.awt.GridLayout; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JPanel; -import javax.swing.JRadioButton; - -public class RadioButtonPanel extends JPanel -{ - public static final Orientation VERTICAL = Orientation.VERTICAL; - public static final Orientation HORIZONTAL = Orientation.HORIZONTAL; - - private ButtonGroup buttonGroup = new ButtonGroup(); - - public RadioButtonPanel(String title, JRadioButton... buttons) - { - this(VERTICAL, title, buttons); - } - - public RadioButtonPanel(Orientation orientation, String title, JRadioButton... buttons) - { - if (orientation == VERTICAL) - { - this.setLayout(new GridLayout(buttons.length, 1)); - } - else - { - this.setLayout(new FlowLayout(FlowLayout.LEADING)); - } - - for (JRadioButton button : buttons) - { - buttonGroup.add(button); - this.add(button); - } - - if (title != null) - { - this.setBorder(BorderFactory.createTitledBorder( - BorderFactory.createEtchedBorder(), title)); - } - } - - public void clearSelection() - { - buttonGroup.clearSelection(); - } - - private enum Orientation - { - VERTICAL, - HORIZONTAL - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java new file mode 100644 index 0000000000..da989c1015 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryBox.java @@ -0,0 +1,155 @@ +package net.runelite.client.plugins.openosrs.externals; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.Optional; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import net.runelite.client.plugins.ExternalPluginManager; +import net.runelite.client.ui.ColorScheme; +import net.runelite.client.ui.FontManager; +import net.runelite.client.ui.JMultilineLabel; +import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.LinkBrowser; +import org.pf4j.update.PluginInfo; +import org.pf4j.update.UpdateRepository; + +public class RepositoryBox extends JPanel +{ + private static final Font normalFont = FontManager.getRunescapeFont(); + private static final Font smallFont = FontManager.getRunescapeSmallFont(); + private static final ImageIcon DELETE_ICON; + private static final ImageIcon DELETE_HOVER_ICON; + private static final ImageIcon DISCORD_ICON; + private static final ImageIcon DISCORD_HOVER_ICON; + + static + { + final BufferedImage deleteImg = + ImageUtil.recolorImage( + ImageUtil.resizeCanvas( + ImageUtil.getResourceStreamFromClass(ExternalPluginManagerPanel.class, "delete_icon.png"), 14, 14 + ), ColorScheme.BRAND_BLUE + ); + DELETE_ICON = new ImageIcon(deleteImg); + DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, 0.53f)); + + final BufferedImage discordImg = + ImageUtil.recolorImage( + ImageUtil.resizeCanvas( + ImageUtil.getResourceStreamFromClass(ExternalPluginManagerPanel.class, "discord_icon.png"), 14, 14 + ), Color.WHITE + ); + DISCORD_ICON = new ImageIcon(discordImg); + DISCORD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(discordImg, 0.53f)); + } + + RepositoryBox(ExternalPluginManager externalPluginManager, UpdateRepository updateRepository) + { + setLayout(new BorderLayout()); + setBackground(ColorScheme.DARKER_GRAY_COLOR); + + String name = updateRepository.getId().replace(updateRepository.getUrl().toString(), ""); + String urlString = updateRepository.getUrl().toString().replace("https://raw.githubusercontent.com/", "").replace("/master/", ""); + + JPanel titleWrapper = new JPanel(new BorderLayout()); + titleWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR); + titleWrapper.setBorder(new CompoundBorder( + BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.DARK_GRAY_COLOR), + BorderFactory.createLineBorder(ColorScheme.DARKER_GRAY_COLOR) + )); + + JLabel title = new JLabel(); + title.setText(name); + title.setFont(normalFont); + title.setBorder(null); + title.setBackground(ColorScheme.DARKER_GRAY_COLOR); + title.setPreferredSize(new Dimension(0, 24)); + title.setForeground(Color.WHITE); + title.setBorder(new EmptyBorder(0, 8, 0, 0)); + + JPanel titleActions = new JPanel(new BorderLayout(3, 0)); + titleActions.setBorder(new EmptyBorder(0, 0, 0, 8)); + titleActions.setBackground(ColorScheme.DARKER_GRAY_COLOR); + + Optional firstPlugin = updateRepository.getPlugins().values().stream().findFirst(); + + if (firstPlugin.isPresent() && !firstPlugin.get().projectUrl.equals("")) + { + JLabel support = new JLabel(); + support.setIcon(DISCORD_ICON); + support.setToolTipText("Support"); + support.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent e) + { + LinkBrowser.browse(firstPlugin.get().projectUrl); + } + + @Override + public void mouseEntered(MouseEvent e) + { + support.setIcon(DISCORD_HOVER_ICON); + } + + @Override + public void mouseExited(MouseEvent e) + { + support.setIcon(DISCORD_ICON); + } + }); + + titleActions.add(support, BorderLayout.WEST); + } + + if (!name.equals("OpenOSRS")) + { + JLabel install = new JLabel(); + install.setIcon(DELETE_ICON); + install.setToolTipText("Remove"); + install.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent e) + { + externalPluginManager.removeRepository(updateRepository.getId()); + } + + @Override + public void mouseEntered(MouseEvent e) + { + install.setIcon(DELETE_HOVER_ICON); + } + + @Override + public void mouseExited(MouseEvent e) + { + install.setIcon(DELETE_ICON); + } + }); + + titleActions.add(install, BorderLayout.EAST); + } + + titleWrapper.add(title, BorderLayout.CENTER); + titleWrapper.add(titleActions, BorderLayout.EAST); + + JMultilineLabel repository = new JMultilineLabel(); + repository.setText(urlString.split("/", 2)[1]); + repository.setFont(smallFont); + repository.setDisabledTextColor(Color.WHITE); + + add(titleWrapper, BorderLayout.NORTH); + add(repository, BorderLayout.CENTER); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java new file mode 100644 index 0000000000..4b541ccd04 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/openosrs/externals/RepositoryPanel.java @@ -0,0 +1,49 @@ +package net.runelite.client.plugins.openosrs.externals; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import net.runelite.client.eventbus.EventBus; +import net.runelite.client.events.ExternalRepositoryChanged; +import net.runelite.client.plugins.ExternalPluginManager; +import net.runelite.client.ui.ColorScheme; +import org.pf4j.update.UpdateRepository; + +public class RepositoryPanel extends JPanel +{ + private final ExternalPluginManager externalPluginManager; + + private final GridBagConstraints c = new GridBagConstraints(); + + RepositoryPanel(ExternalPluginManager externalPluginManager, EventBus eventBus) + { + this.externalPluginManager = externalPluginManager; + + setLayout(new GridBagLayout()); + setBackground(ColorScheme.DARK_GRAY_COLOR); + setBorder(new EmptyBorder(0, 10, 0, 10)); + + createPanel(); + + eventBus.subscribe(ExternalRepositoryChanged.class, this, (e) -> createPanel()); + } + + private void createPanel() + { + removeAll(); + + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridy = 0; + c.insets = new Insets(5, 0, 0, 0); + + for (UpdateRepository repository : externalPluginManager.getRepositories()) + { + final RepositoryBox p = new RepositoryBox(externalPluginManager, repository); + add(p, c); + c.gridy++; + } + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/JMultilineLabel.java b/runelite-client/src/main/java/net/runelite/client/ui/JMultilineLabel.java new file mode 100644 index 0000000000..a321967ef7 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/ui/JMultilineLabel.java @@ -0,0 +1,27 @@ +package net.runelite.client.ui; + +import javax.swing.JLabel; +import javax.swing.JTextArea; +import javax.swing.border.EmptyBorder; +import javax.swing.text.DefaultCaret; + +public class JMultilineLabel extends JTextArea +{ + private static final long serialVersionUID = 1L; + + public JMultilineLabel() + { + super(); + setEditable(false); + setCursor(null); + setOpaque(false); + setFocusable(false); + setWrapStyleWord(true); + setLineWrap(true); + setBorder(new EmptyBorder(0, 8, 0, 8)); + setAlignmentY(JLabel.CENTER_ALIGNMENT); + + DefaultCaret caret = (DefaultCaret) getCaret(); + caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + } +} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/config_back_icon.png b/runelite-client/src/main/resources/net/runelite/client/plugins/openosrs/externals/config_back_icon.png deleted file mode 100644 index 42c78a7e5ec7f6f885d86f00204e63fc75a63acf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eO!3HGrSK5O(oCO|{#S9GG!XV7ZFl&wkP;jrO zi(`n!#H;5PdbuzPv_8yty}`ag(k!C4sdSaAkCe}D*BYkzhg6zo__VP$&oG(yDmf#< zEW)QLQ8#?YslB^H{UvAotUvc*|D=>zDVOf8)opxV*s^)5)1+vbgucJua`!UtJ7joo zV|1wgUS7|0g2BR0px`S{ z7sn8b(`PT+ay1o5uoWD1ytMaVSm8&uys6H;jqIE@PQfBq?y>JEX(-4j{3uk(pfBLk zq3~_b2QK|ZL9-9#f2g!yv453D^X_lgvsi*JxGX!!^JSl-tXV;uuFQjDeH)sEzrV=k z)|+sMeHC9wbx?lsjh02}8#=3ecPjiy-XV5^b)&|U4Q&A_is?H~JgSOl-LB#CDB!iv za~&bcvnxcRdgo6&$Wk-$=bY5uxNfnEM+v9o|5a=9-C4}ax5vWc!Nrd*T6|w^-P<^=>1Ca+VStKd#~;iIhl1-3g~MFPgg&e IbxsLQ0KpxAjQ{`u literal 0 HcmV?d00001