Remove need to extend JToolBar in PluginToolbar
- Create PluginToolbar through Guice - Create separate component class for toolbar layout - Create custom navigation button component to not depend on swing - Create new events that are fired on new toolbar button addition and removal Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
This commit is contained in:
@@ -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,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,11 +39,14 @@ import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
@@ -58,6 +61,8 @@ 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.util.OSType;
|
||||
import net.runelite.client.util.OSXUtil;
|
||||
import net.runelite.client.util.SwingUtil;
|
||||
@@ -97,9 +102,6 @@ public class ClientUI
|
||||
@Getter
|
||||
private TrayIcon trayIcon;
|
||||
|
||||
@Getter
|
||||
private PluginToolbar pluginToolbar;
|
||||
|
||||
@Getter
|
||||
private TitleToolbar titleToolbar;
|
||||
|
||||
@@ -111,6 +113,8 @@ public class ClientUI
|
||||
private JFrame frame;
|
||||
private JPanel navContainer;
|
||||
private PluginPanel pluginPanel;
|
||||
private ClientPluginToolbar pluginToolbar;
|
||||
private JButton currentButton;
|
||||
|
||||
@Inject
|
||||
private ClientUI(
|
||||
@@ -193,6 +197,56 @@ public class ClientUI
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPluginToolbarButtonAdded(final PluginToolbarButtonAdded event)
|
||||
{
|
||||
final JButton button = new JButton();
|
||||
button.setName(event.getButton().getName());
|
||||
button.setToolTipText(event.getButton().getTooltip());
|
||||
button.setToolTipText(event.getButton().getTooltip());
|
||||
button.setIcon(new ImageIcon(event.getButton().getIcon()));
|
||||
button.addActionListener(e ->
|
||||
{
|
||||
final Supplier<PluginPanel> panelSupplier = event.getButton().getPanel();
|
||||
|
||||
if (panelSupplier == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentButton != null)
|
||||
{
|
||||
currentButton.setSelected(false);
|
||||
}
|
||||
|
||||
if (currentButton == button)
|
||||
{
|
||||
contract();
|
||||
currentButton = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentButton = button;
|
||||
currentButton.setSelected(true);
|
||||
expand(panelSupplier.get());
|
||||
}
|
||||
|
||||
if (event.getButton().getOnClick() != null)
|
||||
{
|
||||
event.getButton().getOnClick().run();
|
||||
}
|
||||
});
|
||||
|
||||
event.getButton().setOnSelect(() -> button.setSelected(event.getButton().isSelected()));
|
||||
SwingUtilities.invokeLater(() -> pluginToolbar.addComponent(event.getIndex(), event.getButton(), button));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPluginToolbarButtonRemoved(final PluginToolbarButtonRemoved event)
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> pluginToolbar.removeComponent(event.getButton()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize UI.
|
||||
*
|
||||
@@ -243,7 +297,7 @@ public class ClientUI
|
||||
navContainer.setMaximumSize(new Dimension(0, Integer.MAX_VALUE));
|
||||
container.add(navContainer);
|
||||
|
||||
pluginToolbar = new PluginToolbar(this);
|
||||
pluginToolbar = new ClientPluginToolbar();
|
||||
container.add(pluginToolbar);
|
||||
|
||||
titleToolbar = new TitleToolbar(properties);
|
||||
@@ -378,12 +432,7 @@ public class ClientUI
|
||||
giveClientFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand panel.
|
||||
*
|
||||
* @param panel the panel
|
||||
*/
|
||||
public void expand(PluginPanel panel)
|
||||
private void expand(PluginPanel panel)
|
||||
{
|
||||
if (pluginPanel != null)
|
||||
{
|
||||
@@ -415,10 +464,7 @@ public class ClientUI
|
||||
SwingUtil.revalidateMinimumSize(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract. panel.
|
||||
*/
|
||||
public void contract()
|
||||
private void contract()
|
||||
{
|
||||
boolean wasMinimumWidth = frame.getWidth() == frame.getMinimumSize().width;
|
||||
pluginPanel.onDeactivate();
|
||||
|
||||
@@ -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,50 @@
|
||||
*/
|
||||
package net.runelite.client.ui;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.function.Supplier;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Slf4j
|
||||
public class NavigationButton extends JButton
|
||||
/**
|
||||
* UI navigation button.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
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;
|
||||
|
||||
/**
|
||||
* Supplier for plugin panel, used when expanding and contracting sidebar.
|
||||
*/
|
||||
private Supplier<PluginPanel> panel;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user