Merge pull request #1419 from psikoi/color-scheme-orange-dark
"RuneLite Obsidian" Client Redesign
@@ -77,12 +77,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.runelite.pushingpixels</groupId>
|
<groupId>net.runelite.pushingpixels</groupId>
|
||||||
<artifactId>substance</artifactId>
|
<artifactId>substance</artifactId>
|
||||||
<version>8.0.00-dev</version>
|
<version>8.0.02</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.runelite.pushingpixels</groupId>
|
<groupId>net.runelite.pushingpixels</groupId>
|
||||||
<artifactId>trident</artifactId>
|
<artifactId>trident</artifactId>
|
||||||
<version>1.4</version>
|
<version>1.5.00</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ public class RuneLiteProperties
|
|||||||
private static final String RUNESCAPE_VERSION = "runescape.version";
|
private static final String RUNESCAPE_VERSION = "runescape.version";
|
||||||
private static final String DISCORD_APP_ID = "runelite.discord.appid";
|
private static final String DISCORD_APP_ID = "runelite.discord.appid";
|
||||||
private static final String DISCORD_INVITE = "runelite.discord.invite";
|
private static final String DISCORD_INVITE = "runelite.discord.invite";
|
||||||
|
private static final String GITHUB_LINK = "runelite.github.link";
|
||||||
|
private static final String PATREON_LINK = "runelite.patreon.link";
|
||||||
|
|
||||||
private final Properties properties = new Properties();
|
private final Properties properties = new Properties();
|
||||||
|
|
||||||
@@ -82,4 +84,14 @@ public class RuneLiteProperties
|
|||||||
{
|
{
|
||||||
return properties.getProperty(DISCORD_INVITE);
|
return properties.getProperty(DISCORD_INVITE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public String getGithubLink()
|
||||||
|
{
|
||||||
|
return properties.getProperty(GITHUB_LINK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPatreonLink()
|
||||||
|
{
|
||||||
|
return properties.getProperty(PATREON_LINK);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,7 +37,6 @@ import java.awt.event.MouseAdapter;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -61,6 +60,7 @@ import javax.swing.JTextField;
|
|||||||
import javax.swing.SpinnerModel;
|
import javax.swing.SpinnerModel;
|
||||||
import javax.swing.SpinnerNumberModel;
|
import javax.swing.SpinnerNumberModel;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
@@ -75,16 +75,22 @@ import net.runelite.client.plugins.Plugin;
|
|||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
import net.runelite.client.plugins.PluginInstantiationException;
|
import net.runelite.client.plugins.PluginInstantiationException;
|
||||||
import net.runelite.client.plugins.PluginManager;
|
import net.runelite.client.plugins.PluginManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.DynamicGridLayout;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.ui.components.ComboBoxListRenderer;
|
||||||
|
import net.runelite.client.ui.components.IconTextField;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class ConfigPanel extends PluginPanel
|
public class ConfigPanel extends PluginPanel
|
||||||
{
|
{
|
||||||
private static final int TEXT_FIELD_WIDTH = 7;
|
private static final int TEXT_FIELD_WIDTH = 7;
|
||||||
private static final int SPINNER_FIELD_WIDTH = 6;
|
private static final int SPINNER_FIELD_WIDTH = 6;
|
||||||
private static BufferedImage CONFIG_ICON;
|
|
||||||
private static BufferedImage UNCHECK_ICON;
|
private static final ImageIcon CONFIG_ICON;
|
||||||
private static BufferedImage CHECK_ICON;
|
private static final ImageIcon ON_SWITCHER;
|
||||||
|
private static final ImageIcon OFF_SWITCHER;
|
||||||
|
private static final ImageIcon SEARCH;
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
@@ -92,14 +98,15 @@ public class ConfigPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
synchronized (ImageIO.class)
|
synchronized (ImageIO.class)
|
||||||
{
|
{
|
||||||
CONFIG_ICON = ImageIO.read(ConfigPanel.class.getResourceAsStream("config_icon.png"));
|
CONFIG_ICON = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("config_edit_icon.png")));
|
||||||
UNCHECK_ICON = ImageIO.read(ConfigPanel.class.getResourceAsStream("disabled.png"));
|
ON_SWITCHER = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("switchers/on.png")));
|
||||||
CHECK_ICON = ImageIO.read(ConfigPanel.class.getResourceAsStream("enabled.png"));
|
OFF_SWITCHER = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("switchers/off.png")));
|
||||||
|
SEARCH = new ImageIcon(ImageIO.read(IconTextField.class.getResourceAsStream("search.png")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
log.warn("Failed to read icon", e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +114,7 @@ public class ConfigPanel extends PluginPanel
|
|||||||
private final ConfigManager configManager;
|
private final ConfigManager configManager;
|
||||||
private final ScheduledExecutorService executorService;
|
private final ScheduledExecutorService executorService;
|
||||||
private final RuneLiteConfig runeLiteConfig;
|
private final RuneLiteConfig runeLiteConfig;
|
||||||
private final JTextField searchBar = new JTextField();
|
private final IconTextField searchBar = new IconTextField();
|
||||||
private Map<String, JPanel> children = new TreeMap<>();
|
private Map<String, JPanel> children = new TreeMap<>();
|
||||||
private int scrollBarPosition = 0;
|
private int scrollBarPosition = 0;
|
||||||
|
|
||||||
@@ -119,6 +126,10 @@ public class ConfigPanel extends PluginPanel
|
|||||||
this.executorService = executorService;
|
this.executorService = executorService;
|
||||||
this.runeLiteConfig = runeLiteConfig;
|
this.runeLiteConfig = runeLiteConfig;
|
||||||
|
|
||||||
|
searchBar.setIcon(SEARCH);
|
||||||
|
searchBar.setPreferredSize(new Dimension(100, 30));
|
||||||
|
searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR);
|
||||||
searchBar.getDocument().addDocumentListener(new DocumentListener()
|
searchBar.getDocument().addDocumentListener(new DocumentListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@@ -140,6 +151,10 @@ public class ConfigPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
setLayout(new DynamicGridLayout(0, 1, 0, 5));
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
rebuildPluginList();
|
rebuildPluginList();
|
||||||
openConfigList();
|
openConfigList();
|
||||||
}
|
}
|
||||||
@@ -150,42 +165,54 @@ public class ConfigPanel extends PluginPanel
|
|||||||
Map<String, JPanel> newChildren = new TreeMap<>();
|
Map<String, JPanel> newChildren = new TreeMap<>();
|
||||||
|
|
||||||
pluginManager.getPlugins().stream()
|
pluginManager.getPlugins().stream()
|
||||||
.filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).hidden())
|
.filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).hidden())
|
||||||
.sorted(Comparator.comparing(left -> left.getClass().getAnnotation(PluginDescriptor.class).name()))
|
.sorted(Comparator.comparing(left -> left.getClass().getAnnotation(PluginDescriptor.class).name()))
|
||||||
.forEach(plugin ->
|
.forEach(plugin ->
|
||||||
{
|
{
|
||||||
final Config pluginConfigProxy = pluginManager.getPluginConfigProxy(plugin);
|
final Config pluginConfigProxy = pluginManager.getPluginConfigProxy(plugin);
|
||||||
final String pluginName = plugin.getClass().getAnnotation(PluginDescriptor.class).name();
|
final String pluginName = plugin.getClass().getAnnotation(PluginDescriptor.class).name();
|
||||||
|
|
||||||
final JPanel groupPanel = buildGroupPanel();
|
final JPanel groupPanel = buildGroupPanel();
|
||||||
groupPanel.add(new JLabel(pluginName), BorderLayout.CENTER);
|
|
||||||
|
|
||||||
final JPanel buttonPanel = new JPanel();
|
JLabel name = new JLabel(pluginName);
|
||||||
buttonPanel.setLayout(new GridLayout(1, 2, 3, 0));
|
name.setForeground(Color.WHITE);
|
||||||
groupPanel.add(buttonPanel, BorderLayout.LINE_END);
|
|
||||||
|
|
||||||
final JButton editConfigButton = buildConfigButton(pluginConfigProxy);
|
groupPanel.add(name, BorderLayout.CENTER);
|
||||||
buttonPanel.add(editConfigButton);
|
|
||||||
|
|
||||||
final JButton toggleButton = buildToggleButton(plugin);
|
final JPanel buttonPanel = new JPanel();
|
||||||
buttonPanel.add(toggleButton);
|
buttonPanel.setOpaque(false);
|
||||||
|
buttonPanel.setLayout(new GridLayout(1, 2));
|
||||||
|
groupPanel.add(buttonPanel, BorderLayout.LINE_END);
|
||||||
|
|
||||||
newChildren.put(pluginName, groupPanel);
|
final JLabel editConfigButton = buildConfigButton(pluginConfigProxy);
|
||||||
});
|
buttonPanel.add(editConfigButton);
|
||||||
|
|
||||||
|
final JLabel toggleButton = buildToggleButton(plugin);
|
||||||
|
toggleButton.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||||
|
buttonPanel.add(toggleButton);
|
||||||
|
|
||||||
|
newChildren.put(pluginName, groupPanel);
|
||||||
|
});
|
||||||
|
|
||||||
final JPanel groupPanel = buildGroupPanel();
|
final JPanel groupPanel = buildGroupPanel();
|
||||||
groupPanel.add(new JLabel("RuneLite"), BorderLayout.CENTER);
|
|
||||||
|
JLabel name = new JLabel("RuneLite");
|
||||||
|
name.setForeground(Color.WHITE);
|
||||||
|
|
||||||
|
groupPanel.add(name, BorderLayout.CENTER);
|
||||||
|
|
||||||
final JPanel buttonPanel = new JPanel();
|
final JPanel buttonPanel = new JPanel();
|
||||||
buttonPanel.setLayout(new GridLayout(1, 2, 3, 0));
|
buttonPanel.setOpaque(false);
|
||||||
|
buttonPanel.setLayout(new GridLayout(1, 2));
|
||||||
groupPanel.add(buttonPanel, BorderLayout.LINE_END);
|
groupPanel.add(buttonPanel, BorderLayout.LINE_END);
|
||||||
|
|
||||||
final JButton editConfigButton = buildConfigButton(runeLiteConfig);
|
final JLabel editConfigButton = buildConfigButton(runeLiteConfig);
|
||||||
buttonPanel.add(editConfigButton);
|
buttonPanel.add(editConfigButton);
|
||||||
|
|
||||||
final JButton toggleButton = buildToggleButton(null);
|
final JLabel toggleButton = buildToggleButton(null);
|
||||||
|
toggleButton.setVisible(false);
|
||||||
buttonPanel.add(toggleButton);
|
buttonPanel.add(toggleButton);
|
||||||
|
|
||||||
newChildren.put("RuneLite", groupPanel);
|
newChildren.put("RuneLite", groupPanel);
|
||||||
|
|
||||||
children = newChildren;
|
children = newChildren;
|
||||||
@@ -197,15 +224,17 @@ public class ConfigPanel extends PluginPanel
|
|||||||
// Create base panel for the config button and enabled/disabled button
|
// Create base panel for the config button and enabled/disabled button
|
||||||
final JPanel groupPanel = new JPanel();
|
final JPanel groupPanel = new JPanel();
|
||||||
groupPanel.setLayout(new BorderLayout(3, 0));
|
groupPanel.setLayout(new BorderLayout(3, 0));
|
||||||
|
groupPanel.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH, 20));
|
||||||
|
groupPanel.setOpaque(false);
|
||||||
return groupPanel;
|
return groupPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JButton buildConfigButton(Config config)
|
private JLabel buildConfigButton(Config config)
|
||||||
{
|
{
|
||||||
// Create edit config button and disable it by default
|
// Create edit config button and disable it by default
|
||||||
final JButton editConfigButton = new JButton(new ImageIcon(CONFIG_ICON));
|
final JLabel editConfigButton = new JLabel(CONFIG_ICON);
|
||||||
editConfigButton.setPreferredSize(new Dimension(32, 0));
|
editConfigButton.setPreferredSize(new Dimension(25, 0));
|
||||||
editConfigButton.setEnabled(false);
|
editConfigButton.setVisible(false);
|
||||||
|
|
||||||
// If we have configuration proxy enable the button and add edit config listener
|
// If we have configuration proxy enable the button and add edit config listener
|
||||||
if (config != null)
|
if (config != null)
|
||||||
@@ -215,8 +244,15 @@ public class ConfigPanel extends PluginPanel
|
|||||||
|
|
||||||
if (!configEmpty)
|
if (!configEmpty)
|
||||||
{
|
{
|
||||||
editConfigButton.addActionListener(ae -> openGroupConfigPanel(config, configDescriptor, configManager));
|
editConfigButton.addMouseListener(new MouseAdapter()
|
||||||
editConfigButton.setEnabled(true);
|
{
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
openGroupConfigPanel(config, configDescriptor, configManager);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editConfigButton.setVisible(true);
|
||||||
editConfigButton.setToolTipText("Edit plugin configuration");
|
editConfigButton.setToolTipText("Edit plugin configuration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,11 +260,11 @@ public class ConfigPanel extends PluginPanel
|
|||||||
return editConfigButton;
|
return editConfigButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JButton buildToggleButton(Plugin plugin)
|
private JLabel buildToggleButton(Plugin plugin)
|
||||||
{
|
{
|
||||||
// Create enabling/disabling button
|
// Create enabling/disabling button
|
||||||
final JButton toggleButton = new JButton(new ImageIcon(CHECK_ICON));
|
final JLabel toggleButton = new JLabel(ON_SWITCHER);
|
||||||
toggleButton.setPreferredSize(new Dimension(32, 0));
|
toggleButton.setPreferredSize(new Dimension(25, 0));
|
||||||
|
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
@@ -238,36 +274,43 @@ public class ConfigPanel extends PluginPanel
|
|||||||
|
|
||||||
highlightButton(toggleButton, pluginManager.isPluginEnabled(plugin));
|
highlightButton(toggleButton, pluginManager.isPluginEnabled(plugin));
|
||||||
|
|
||||||
toggleButton.addActionListener(e -> executorService.submit(() ->
|
toggleButton.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
final boolean enabled = pluginManager.isPluginEnabled(plugin);
|
@Override
|
||||||
pluginManager.setPluginEnabled(plugin, !enabled);
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (enabled)
|
executorService.submit(() ->
|
||||||
{
|
{
|
||||||
pluginManager.stopPlugin(plugin);
|
final boolean enabled = pluginManager.isPluginEnabled(plugin);
|
||||||
}
|
pluginManager.setPluginEnabled(plugin, !enabled);
|
||||||
else
|
|
||||||
{
|
|
||||||
pluginManager.startPlugin(plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (PluginInstantiationException ex)
|
|
||||||
{
|
|
||||||
log.warn("Error during starting/stopping plugin {}", plugin.getClass().getSimpleName(), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
highlightButton(toggleButton, !enabled);
|
try
|
||||||
}));
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
pluginManager.stopPlugin(plugin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pluginManager.startPlugin(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (PluginInstantiationException ex)
|
||||||
|
{
|
||||||
|
log.warn("Error during starting/stopping plugin {}", plugin.getClass().getSimpleName(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightButton(toggleButton, !enabled);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return toggleButton;
|
return toggleButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void highlightButton(JButton button, boolean enabled)
|
private void highlightButton(JLabel button, boolean enabled)
|
||||||
{
|
{
|
||||||
button.setIcon(enabled ? new ImageIcon(CHECK_ICON) : new ImageIcon(UNCHECK_ICON));
|
button.setIcon(enabled ? ON_SWITCHER : OFF_SWITCHER);
|
||||||
button.setToolTipText(enabled ? "Disable plugin" : "Enable plugin");
|
button.setToolTipText(enabled ? "Disable plugin" : "Enable plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +344,11 @@ public class ConfigPanel extends PluginPanel
|
|||||||
private void openConfigList()
|
private void openConfigList()
|
||||||
{
|
{
|
||||||
removeAll();
|
removeAll();
|
||||||
add(new JLabel("Plugin Configuration", SwingConstants.CENTER));
|
|
||||||
|
JLabel title = new JLabel("Configuration", SwingConstants.LEFT);
|
||||||
|
title.setForeground(Color.WHITE);
|
||||||
|
|
||||||
|
add(title);
|
||||||
add(searchBar);
|
add(searchBar);
|
||||||
|
|
||||||
onSearchBarChanged();
|
onSearchBarChanged();
|
||||||
@@ -331,6 +378,7 @@ public class ConfigPanel extends PluginPanel
|
|||||||
if (component instanceof JCheckBox)
|
if (component instanceof JCheckBox)
|
||||||
{
|
{
|
||||||
JCheckBox checkbox = (JCheckBox) component;
|
JCheckBox checkbox = (JCheckBox) component;
|
||||||
|
checkbox.setOpaque(false);
|
||||||
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), "" + checkbox.isSelected());
|
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), "" + checkbox.isSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,6 +403,8 @@ public class ConfigPanel extends PluginPanel
|
|||||||
if (component instanceof JComboBox)
|
if (component instanceof JComboBox)
|
||||||
{
|
{
|
||||||
JComboBox jComboBox = (JComboBox) component;
|
JComboBox jComboBox = (JComboBox) component;
|
||||||
|
jComboBox.setRenderer(new ComboBoxListRenderer());
|
||||||
|
jComboBox.setForeground(Color.WHITE);
|
||||||
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), ((Enum) jComboBox.getSelectedItem()).name());
|
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), ((Enum) jComboBox.getSelectedItem()).name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,6 +426,7 @@ public class ConfigPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
|
|
||||||
JPanel item = new JPanel();
|
JPanel item = new JPanel();
|
||||||
|
item.setOpaque(false);
|
||||||
item.setLayout(new BorderLayout());
|
item.setLayout(new BorderLayout());
|
||||||
name = cid.getItem().name();
|
name = cid.getItem().name();
|
||||||
JLabel configEntryName = new JLabel(name);
|
JLabel configEntryName = new JLabel(name);
|
||||||
@@ -385,6 +436,8 @@ public class ConfigPanel extends PluginPanel
|
|||||||
if (cid.getType() == boolean.class)
|
if (cid.getType() == boolean.class)
|
||||||
{
|
{
|
||||||
JCheckBox checkbox = new JCheckBox();
|
JCheckBox checkbox = new JCheckBox();
|
||||||
|
checkbox.setOpaque(false);
|
||||||
|
checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||||
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName())));
|
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName())));
|
||||||
checkbox.addActionListener(ae -> changeConfiguration(config, checkbox, cd, cid));
|
checkbox.addActionListener(ae -> changeConfiguration(config, checkbox, cd, cid));
|
||||||
|
|
||||||
@@ -462,6 +515,7 @@ public class ConfigPanel extends PluginPanel
|
|||||||
if (cid.getType() == Dimension.class)
|
if (cid.getType() == Dimension.class)
|
||||||
{
|
{
|
||||||
JPanel dimensionPanel = new JPanel();
|
JPanel dimensionPanel = new JPanel();
|
||||||
|
dimensionPanel.setOpaque(false);
|
||||||
dimensionPanel.setLayout(new BorderLayout());
|
dimensionPanel.setLayout(new BorderLayout());
|
||||||
|
|
||||||
String str = configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName());
|
String str = configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName());
|
||||||
@@ -482,7 +536,7 @@ public class ConfigPanel extends PluginPanel
|
|||||||
heightSpinnerTextField.setColumns(4);
|
heightSpinnerTextField.setColumns(4);
|
||||||
|
|
||||||
ChangeListener listener = e ->
|
ChangeListener listener = e ->
|
||||||
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue());
|
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue());
|
||||||
|
|
||||||
widthSpinner.addChangeListener(listener);
|
widthSpinner.addChangeListener(listener);
|
||||||
heightSpinner.addChangeListener(listener);
|
heightSpinner.addChangeListener(listener);
|
||||||
@@ -498,6 +552,9 @@ public class ConfigPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
Class<? extends Enum> type = (Class<? extends Enum>) cid.getType();
|
Class<? extends Enum> type = (Class<? extends Enum>) cid.getType();
|
||||||
JComboBox box = new JComboBox(type.getEnumConstants());
|
JComboBox box = new JComboBox(type.getEnumConstants());
|
||||||
|
box.setPreferredSize(new Dimension(box.getPreferredSize().width, 25));
|
||||||
|
box.setRenderer(new ComboBoxListRenderer());
|
||||||
|
box.setForeground(Color.WHITE);
|
||||||
box.setFocusable(false);
|
box.setFocusable(false);
|
||||||
box.setPrototypeDisplayValue("XXXXXXXX"); //sorry but this is the way to keep the size of the combobox in check.
|
box.setPrototypeDisplayValue("XXXXXXXX"); //sorry but this is the way to keep the size of the combobox in check.
|
||||||
try
|
try
|
||||||
@@ -541,4 +598,4 @@ public class ConfigPanel extends PluginPanel
|
|||||||
revalidate();
|
revalidate();
|
||||||
getScrollPane().getVerticalScrollBar().setValue(0);
|
getScrollPane().getVerticalScrollBar().setValue(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,6 +78,7 @@ public class ConfigPlugin extends Plugin
|
|||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("Configuration")
|
.name("Configuration")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(0)
|
||||||
.panel(configPanel)
|
.panel(configPanel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import javax.swing.JButton;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -52,6 +53,8 @@ public class DevToolsPanel extends PluginPanel
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.widgetInspector = widgetInspector;
|
this.widgetInspector = widgetInspector;
|
||||||
|
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
varTracker = new VarTracker(client);
|
varTracker = new VarTracker(client);
|
||||||
add(createOptionsPanel());
|
add(createOptionsPanel());
|
||||||
}
|
}
|
||||||
@@ -59,6 +62,7 @@ public class DevToolsPanel extends PluginPanel
|
|||||||
private JPanel createOptionsPanel()
|
private JPanel createOptionsPanel()
|
||||||
{
|
{
|
||||||
final JPanel container = new JPanel();
|
final JPanel container = new JPanel();
|
||||||
|
container.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
container.setLayout(new GridLayout(0, 2, 3, 3));
|
container.setLayout(new GridLayout(0, 2, 3, 3));
|
||||||
|
|
||||||
final JButton renderPlayersBtn = new JButton("Players");
|
final JButton renderPlayersBtn = new JButton("Players");
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ public class DevToolsPlugin extends Plugin
|
|||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("Developer Tools")
|
.name("Developer Tools")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(1)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -27,15 +27,16 @@ package net.runelite.client.plugins.farmingtracker;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
public enum CropState
|
public enum CropState
|
||||||
{
|
{
|
||||||
HARVESTABLE(Color.GREEN),
|
HARVESTABLE(ColorScheme.PROGRESS_COMPLETE_COLOR),
|
||||||
GROWING(Color.GREEN),
|
GROWING(ColorScheme.PROGRESS_COMPLETE_COLOR),
|
||||||
DISEASED(Color.ORANGE),
|
DISEASED(ColorScheme.PROGRESS_INPROGRESS_COLOR),
|
||||||
DEAD(Color.RED);
|
DEAD(ColorScheme.PROGRESS_ERROR_COLOR);
|
||||||
|
|
||||||
private final Color color;
|
private final Color color;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Abex
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,13 +25,19 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.farmingtracker;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import javax.swing.GroupLayout;
|
import java.awt.GridLayout;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
|
import net.runelite.client.ui.components.ThinProgressBar;
|
||||||
|
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
class FarmingPatchPanel extends JPanel
|
class FarmingPatchPanel extends JPanel
|
||||||
@@ -38,42 +45,43 @@ class FarmingPatchPanel extends JPanel
|
|||||||
private final FarmingPatch patch;
|
private final FarmingPatch patch;
|
||||||
private final JLabel icon = new JLabel();
|
private final JLabel icon = new JLabel();
|
||||||
private final JLabel estimate = new JLabel();
|
private final JLabel estimate = new JLabel();
|
||||||
private final JProgressBar progress = new JProgressBar();
|
private final ThinProgressBar progress = new ThinProgressBar();
|
||||||
|
|
||||||
FarmingPatchPanel(FarmingPatch patch)
|
FarmingPatchPanel(FarmingPatch patch)
|
||||||
{
|
{
|
||||||
this.patch = patch;
|
this.patch = patch;
|
||||||
|
|
||||||
GroupLayout layout = new GroupLayout(this);
|
setLayout(new BorderLayout());
|
||||||
this.setLayout(layout);
|
setOpaque(false);
|
||||||
|
setBorder(new EmptyBorder(7, 0, 0, 0));
|
||||||
|
|
||||||
|
JPanel topContainer = new JPanel();
|
||||||
|
topContainer.setBorder(new EmptyBorder(7, 7, 6, 0));
|
||||||
|
topContainer.setLayout(new BorderLayout());
|
||||||
|
topContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
|
||||||
final JLabel location = new JLabel(patch.getRegion().getName() + " " + patch.getName());
|
|
||||||
location.setFont(FontManager.getRunescapeSmallFont());
|
|
||||||
icon.setMinimumSize(new Dimension(36, 32));
|
icon.setMinimumSize(new Dimension(36, 32));
|
||||||
|
|
||||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
JPanel infoPanel = new JPanel();
|
||||||
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
infoPanel.setOpaque(false);
|
||||||
.addComponent(icon)
|
infoPanel.setLayout(new GridLayout(2, 1));
|
||||||
.addGroup(layout.createSequentialGroup()
|
infoPanel.setBorder(new EmptyBorder(4, 4, 4, 0));
|
||||||
.addGap(1)
|
|
||||||
.addComponent(location)
|
|
||||||
.addGap(1)
|
|
||||||
.addComponent(estimate)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.addComponent(progress, 8, 8, 8)
|
|
||||||
.addGap(4)
|
|
||||||
);
|
|
||||||
|
|
||||||
layout.setHorizontalGroup(layout.createParallelGroup()
|
final JLabel location = new JShadowedLabel(patch.getRegion().getName()
|
||||||
.addGroup(layout.createSequentialGroup()
|
+ (Strings.isNullOrEmpty(patch.getName()) ? "" : " (" + patch.getName() + ")"));
|
||||||
.addComponent(icon)
|
location.setFont(FontManager.getRunescapeSmallFont());
|
||||||
.addGroup(layout.createParallelGroup()
|
location.setForeground(Color.WHITE);
|
||||||
.addComponent(location)
|
|
||||||
.addComponent(estimate)
|
estimate.setFont(FontManager.getRunescapeSmallFont());
|
||||||
)
|
estimate.setForeground(Color.GRAY);
|
||||||
)
|
|
||||||
.addComponent(progress)
|
infoPanel.add(location);
|
||||||
);
|
infoPanel.add(estimate);
|
||||||
|
|
||||||
|
topContainer.add(icon, BorderLayout.WEST);
|
||||||
|
topContainer.add(infoPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
add(topContainer, BorderLayout.NORTH);
|
||||||
|
add(progress, BorderLayout.SOUTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Abex
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,11 +25,13 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.farmingtracker;
|
package net.runelite.client.plugins.farmingtracker;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
@@ -37,9 +40,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
@@ -47,7 +51,11 @@ import net.runelite.api.vars.Autoweed;
|
|||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.game.AsyncBufferedImage;
|
import net.runelite.client.game.AsyncBufferedImage;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
||||||
|
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class FarmingTrackerPanel extends PluginPanel
|
class FarmingTrackerPanel extends PluginPanel
|
||||||
@@ -61,6 +69,10 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
|
|
||||||
private List<FarmingPatchPanel> patchPanels = new ArrayList<>();
|
private List<FarmingPatchPanel> patchPanels = new ArrayList<>();
|
||||||
|
|
||||||
|
/* This is the panel the tabs' respective panels will be displayed on. */
|
||||||
|
private final JPanel display = new JPanel();
|
||||||
|
private final MaterialTabGroup tabGroup = new MaterialTabGroup(display);
|
||||||
|
|
||||||
FarmingTrackerPanel(
|
FarmingTrackerPanel(
|
||||||
Client client,
|
Client client,
|
||||||
ItemManager itemManager,
|
ItemManager itemManager,
|
||||||
@@ -77,11 +89,19 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
display.setOpaque(false);
|
||||||
|
display.setBorder(new EmptyBorder(10, 10, 8, 10));
|
||||||
|
|
||||||
|
tabGroup.setBorder(new EmptyBorder(10, 1, 0, 0));
|
||||||
|
|
||||||
|
add(tabGroup, BorderLayout.NORTH);
|
||||||
|
add(display, BorderLayout.CENTER);
|
||||||
|
|
||||||
JTabbedPane tabs = new JTabbedPane();
|
|
||||||
farmingWorld.getTabs().forEach((tab, patches) ->
|
farmingWorld.getTabs().forEach((tab, patches) ->
|
||||||
{
|
{
|
||||||
JPanel panel = new JPanel(new GridBagLayout())
|
JPanel container = new JPanel(new GridBagLayout())
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize()
|
public Dimension getPreferredSize()
|
||||||
@@ -89,7 +109,7 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
return new Dimension(PluginPanel.PANEL_WIDTH, super.getPreferredSize().height);
|
return new Dimension(PluginPanel.PANEL_WIDTH, super.getPreferredSize().height);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
panel.setBorder(new EmptyBorder(2, 6, 6, 6));
|
container.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
GridBagConstraints c = new GridBagConstraints();
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
@@ -97,43 +117,82 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
c.gridx = 0;
|
c.gridx = 0;
|
||||||
c.gridy = 0;
|
c.gridy = 0;
|
||||||
|
|
||||||
|
PatchImplementation lastImpl = null;
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
for (FarmingPatch patch : patches)
|
for (FarmingPatch patch : patches)
|
||||||
{
|
{
|
||||||
FarmingPatchPanel p = new FarmingPatchPanel(patch);
|
FarmingPatchPanel p = new FarmingPatchPanel(patch);
|
||||||
|
|
||||||
|
/* Show labels to subdivide tabs into sections */
|
||||||
|
if (patch.getImplementation() != lastImpl && !Strings.isNullOrEmpty(patch.getImplementation().getName()))
|
||||||
|
{
|
||||||
|
JLabel groupLabel = new JLabel(patch.getImplementation().getName());
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
groupLabel.setBorder(new EmptyBorder(4, 0, 0, 0));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
groupLabel.setBorder(new EmptyBorder(15, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
groupLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
container.add(groupLabel, c);
|
||||||
|
c.gridy++;
|
||||||
|
lastImpl = patch.getImplementation();
|
||||||
|
}
|
||||||
|
|
||||||
patchPanels.add(p);
|
patchPanels.add(p);
|
||||||
panel.add(p, c);
|
container.add(p, c);
|
||||||
c.gridy++;
|
c.gridy++;
|
||||||
|
|
||||||
|
/* This is a weird hack to remove the top border on the first tracker of every tab */
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
p.setBorder(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JPanel wrapped = new JPanel(new BorderLayout());
|
JPanel wrapped = new JPanel(new BorderLayout());
|
||||||
wrapped.add(panel, BorderLayout.NORTH);
|
wrapped.add(container, BorderLayout.NORTH);
|
||||||
|
wrapped.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
JScrollPane scroller = new JScrollPane(wrapped);
|
JScrollPane scroller = new JScrollPane(wrapped);
|
||||||
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
scroller.getVerticalScrollBar().setUnitIncrement(16);
|
scroller.getVerticalScrollBar().setPreferredSize(new Dimension(16, 0));
|
||||||
|
scroller.getVerticalScrollBar().setBorder(new EmptyBorder(0, 9, 0, 0));
|
||||||
|
scroller.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
MaterialTab materialTab = new MaterialTab("", tabGroup, scroller);
|
||||||
|
materialTab.setName(tab.getName());
|
||||||
|
|
||||||
AsyncBufferedImage icon = itemManager.getImage(tab.getItemID());
|
AsyncBufferedImage icon = itemManager.getImage(tab.getItemID());
|
||||||
tabs.addTab(null, null, scroller, tab.getName());
|
|
||||||
int idx = tabs.getTabCount() - 1;
|
|
||||||
Runnable resize = () ->
|
Runnable resize = () ->
|
||||||
{
|
{
|
||||||
tabs.setIconAt(idx, new ImageIcon(icon.getScaledInstance(24, 21, Image.SCALE_SMOOTH)));
|
BufferedImage subIcon = icon.getSubimage(0, 0, 32, 32);
|
||||||
|
materialTab.setIcon(new ImageIcon(subIcon.getScaledInstance(24, 24, Image.SCALE_SMOOTH)));
|
||||||
|
materialTab.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
materialTab.setVerticalAlignment(SwingConstants.CENTER);
|
||||||
|
materialTab.setOpaque(true);
|
||||||
|
materialTab.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
materialTab.setPreferredSize(new Dimension(30, 27));
|
||||||
};
|
};
|
||||||
icon.onChanged(resize);
|
icon.onChanged(resize);
|
||||||
resize.run();
|
resize.run();
|
||||||
|
|
||||||
|
materialTab.setOnSelectEvent(() -> config.setPatch(tab));
|
||||||
|
|
||||||
|
tabGroup.addTab(materialTab);
|
||||||
if (config.patch() == tab)
|
if (config.patch() == tab)
|
||||||
{
|
{
|
||||||
tabs.setSelectedComponent(scroller);
|
tabGroup.select(materialTab);
|
||||||
}
|
}
|
||||||
tabs.addChangeListener(e ->
|
|
||||||
{
|
|
||||||
if (tabs.getSelectedComponent() == scroller)
|
|
||||||
{
|
|
||||||
config.setPatch(tab);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
add(tabs, BorderLayout.CENTER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
@@ -178,10 +237,11 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
PatchState state = unixTime <= 0 ? null : patch.getImplementation().forVarbitValue(value);
|
PatchState state = unixTime <= 0 ? null : patch.getImplementation().forVarbitValue(value);
|
||||||
if (state == null)
|
if (state == null)
|
||||||
{
|
{
|
||||||
panel.getIcon().setIcon(null);
|
itemManager.getImage(Produce.WEEDS.getItemID()).addTo(panel.getIcon());
|
||||||
panel.getIcon().setToolTipText("Unknown state");
|
panel.getIcon().setToolTipText("Unknown state");
|
||||||
panel.getProgress().setMaximum(0);
|
panel.getProgress().setMaximumValue(0);
|
||||||
panel.getProgress().setValue(0);
|
panel.getProgress().setValue(0);
|
||||||
|
panel.getProgress().setVisible(false);
|
||||||
panel.getEstimate().setText("Unknown");
|
panel.getEstimate().setText("Unknown");
|
||||||
panel.getProgress().setBackground(null);
|
panel.getProgress().setBackground(null);
|
||||||
}
|
}
|
||||||
@@ -298,9 +358,20 @@ class FarmingTrackerPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.getProgress().setBackground(state.getCropState().getColor().darker());
|
/* Hide any fully grown weeds' progress bar. */
|
||||||
panel.getProgress().setMaximum(stages - 1);
|
if (state.getProduce() != Produce.WEEDS
|
||||||
panel.getProgress().setValue(stage);
|
|| (state.getProduce() == Produce.WEEDS && !autoweed && stage < stages - 1))
|
||||||
|
{
|
||||||
|
panel.getProgress().setVisible(true);
|
||||||
|
panel.getProgress().setForeground(state.getCropState().getColor().darker());
|
||||||
|
panel.getProgress().setMaximumValue(stages - 1);
|
||||||
|
panel.getProgress().setValue(stage);
|
||||||
|
panel.getProgress().update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
panel.getProgress().setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ public class FarmingTrackerPlugin extends Plugin
|
|||||||
.name("Farming Tracker")
|
.name("Farming Tracker")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
|
.priority(4)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
pluginToolbar.addNavigation(navButton);
|
pluginToolbar.addNavigation(navButton);
|
||||||
|
|||||||
@@ -60,24 +60,24 @@ public class FarmingWorld
|
|||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Ardougne", 10290,
|
add(new FarmingRegion("Ardougne", 10290,
|
||||||
new FarmingPatch("Bush", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||||
));
|
));
|
||||||
add(new FarmingRegion("Ardougne", 10548,
|
add(new FarmingRegion("Ardougne", 10548,
|
||||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("Flower", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Brimhaven", 11058,
|
add(new FarmingRegion("Brimhaven", 11058,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE),
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.FRUIT_TREE),
|
||||||
new FarmingPatch("Spirit Tree", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Catherby", 11062,
|
add(new FarmingRegion("Catherby", 11062,
|
||||||
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("Flower", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||||
));
|
));
|
||||||
add(new FarmingRegion("Catherby", 11317,
|
add(new FarmingRegion("Catherby", 11317,
|
||||||
@@ -85,20 +85,20 @@ public class FarmingWorld
|
|||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Champion's Guild", 12596,
|
add(new FarmingRegion("Champion's Guild", 12596,
|
||||||
new FarmingPatch("Bush", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Draynor Manor", 12340,
|
add(new FarmingRegion("Draynor Manor", 12340,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BELLADONNA)
|
new FarmingPatch("Belladonna", Varbits.FARMING_4771, PatchImplementation.BELLADONNA)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Entrana", 11060,
|
add(new FarmingRegion("Entrana", 11060,
|
||||||
new FarmingPatch("Hops", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Etceteria", 10300,
|
add(new FarmingRegion("Etceteria", 10300,
|
||||||
new FarmingPatch("Bush", Varbits.FARMING_4771, PatchImplementation.BUSH),
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH),
|
||||||
new FarmingPatch("Spirit Tree", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4772, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Falador", 11828,
|
add(new FarmingRegion("Falador", 11828,
|
||||||
@@ -107,7 +107,7 @@ public class FarmingWorld
|
|||||||
add(new FarmingRegion("Falador", 12083,
|
add(new FarmingRegion("Falador", 12083,
|
||||||
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("Flower", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -141,11 +141,11 @@ public class FarmingWorld
|
|||||||
add(new FarmingRegion("Kourend", 7222,
|
add(new FarmingRegion("Kourend", 7222,
|
||||||
new FarmingPatch("North East", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North East", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South West", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("Flower", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||||
));
|
));
|
||||||
add(new FarmingRegion("Kourend", 6711,
|
add(new FarmingRegion("Kourend", 6711,
|
||||||
new FarmingPatch("Spirit Tree", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
));
|
||||||
add(new FarmingRegion("Kourend", 7223,
|
add(new FarmingRegion("Kourend", 7223,
|
||||||
new FarmingPatch("West 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
new FarmingPatch("West 1", Varbits.GRAPES_4953, PatchImplementation.GRAPES),
|
||||||
@@ -167,7 +167,7 @@ public class FarmingWorld
|
|||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Lumbridge", 12851,
|
add(new FarmingRegion("Lumbridge", 12851,
|
||||||
new FarmingPatch("Hops", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HOPS)
|
||||||
));
|
));
|
||||||
add(new FarmingRegion("Lumbridge", 12594,
|
add(new FarmingRegion("Lumbridge", 12594,
|
||||||
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.TREE)
|
||||||
@@ -179,17 +179,17 @@ public class FarmingWorld
|
|||||||
add(new FarmingRegion("Morytania", 14391,
|
add(new FarmingRegion("Morytania", 14391,
|
||||||
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("North West", Varbits.FARMING_4771, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
new FarmingPatch("South East", Varbits.FARMING_4772, PatchImplementation.ALLOTMENT),
|
||||||
new FarmingPatch("Flower", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
new FarmingPatch("", Varbits.FARMING_4773, PatchImplementation.FLOWER),
|
||||||
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
new FarmingPatch("", Varbits.FARMING_4774, PatchImplementation.HERB)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
add(new FarmingRegion("Port Sarim", 12082,
|
add(new FarmingRegion("Port Sarim", 12082,
|
||||||
new FarmingPatch("Spirit tree", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.SPIRIT_TREE)
|
||||||
));
|
));
|
||||||
|
|
||||||
add(new FarmingRegion("Rimmington", 11570,
|
add(new FarmingRegion("Rimmington", 11570,
|
||||||
new FarmingPatch("Bush", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.BUSH)
|
||||||
), 11826);
|
), 11826);
|
||||||
|
|
||||||
add(new FarmingRegion("Seers' Village", 10551,
|
add(new FarmingRegion("Seers' Village", 10551,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum PatchImplementation
|
public enum PatchImplementation
|
||||||
{
|
{
|
||||||
CACTUS(Tab.SPECIAL)
|
CACTUS(Tab.SPECIAL, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -84,7 +84,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BELLADONNA(Tab.SPECIAL)
|
BELLADONNA(Tab.SPECIAL, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -122,7 +122,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MUSHROOM(Tab.SPECIAL)
|
MUSHROOM(Tab.SPECIAL, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -160,7 +160,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ALLOTMENT(Tab.ALLOTMENT)
|
ALLOTMENT(Tab.ALLOTMENT, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -473,240 +473,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FLOWER(Tab.SPECIAL)
|
HERB(Tab.HERB, "")
|
||||||
{
|
|
||||||
@Override
|
|
||||||
PatchState forVarbitValue(int value)
|
|
||||||
{
|
|
||||||
if (value >= 0 && value <= 3)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7842,7841,7840
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3 - value);
|
|
||||||
}
|
|
||||||
if (value >= 4 && value <= 7)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 8 && value <= 11)
|
|
||||||
{
|
|
||||||
// Marigold[,Inspect,,Guide,] 7867,7868,7869,7870
|
|
||||||
return new PatchState(Produce.MARIGOLD, CropState.GROWING, value - 8);
|
|
||||||
}
|
|
||||||
if (value == 12)
|
|
||||||
{
|
|
||||||
// Marigold[Pick,Inspect,,Guide,] 7871
|
|
||||||
return new PatchState(Produce.MARIGOLD, CropState.HARVESTABLE, 12 - value);
|
|
||||||
}
|
|
||||||
if (value >= 13 && value <= 16)
|
|
||||||
{
|
|
||||||
// Rosemary[,Inspect,,Guide,] 7899,7900,7901,7902
|
|
||||||
return new PatchState(Produce.ROSEMARY, CropState.GROWING, value - 13);
|
|
||||||
}
|
|
||||||
if (value == 17)
|
|
||||||
{
|
|
||||||
// Rosemary[Pick,Inspect,,Guide,] 7903
|
|
||||||
return new PatchState(Produce.ROSEMARY, CropState.HARVESTABLE, 17 - value);
|
|
||||||
}
|
|
||||||
if (value >= 18 && value <= 21)
|
|
||||||
{
|
|
||||||
// Nasturtium[,Inspect,,Guide,] 7883,7884,7885,7886
|
|
||||||
return new PatchState(Produce.NASTURTIUM, CropState.GROWING, value - 18);
|
|
||||||
}
|
|
||||||
if (value == 22)
|
|
||||||
{
|
|
||||||
// Nasturtium[Pick,Inspect,,Guide,] 7887
|
|
||||||
return new PatchState(Produce.NASTURTIUM, CropState.HARVESTABLE, 22 - value);
|
|
||||||
}
|
|
||||||
if (value >= 23 && value <= 26)
|
|
||||||
{
|
|
||||||
// Woad[,Inspect,,Guide,] 7919,7920,7921,7922
|
|
||||||
return new PatchState(Produce.WOAD, CropState.GROWING, value - 23);
|
|
||||||
}
|
|
||||||
if (value == 27)
|
|
||||||
{
|
|
||||||
// Woad[Pick,Inspect,,Guide,] 7923
|
|
||||||
return new PatchState(Produce.WOAD, CropState.HARVESTABLE, 27 - value);
|
|
||||||
}
|
|
||||||
if (value >= 28 && value <= 31)
|
|
||||||
{
|
|
||||||
// Limpwurt[,Inspect,,Guide,] 7851,7852,7853,7854
|
|
||||||
return new PatchState(Produce.LIMPWURT, CropState.GROWING, value - 28);
|
|
||||||
}
|
|
||||||
if (value == 32)
|
|
||||||
{
|
|
||||||
// Limpwurt[Pick,Inspect,,Guide,] 7855
|
|
||||||
return new PatchState(Produce.LIMPWURT, CropState.HARVESTABLE, 32 - value);
|
|
||||||
}
|
|
||||||
if (value >= 33 && value <= 35)
|
|
||||||
{
|
|
||||||
// Scarecrow[Rake,Inspect,,Guide,Remove] 7918,7917,7916
|
|
||||||
return new PatchState(Produce.SCARECROW, CropState.GROWING, 35 - value);
|
|
||||||
}
|
|
||||||
if (value == 36)
|
|
||||||
{
|
|
||||||
// Scarecrow[Remove,Inspect,,Guide,] 7915
|
|
||||||
return new PatchState(Produce.SCARECROW, CropState.GROWING, 0);
|
|
||||||
}
|
|
||||||
if (value >= 37 && value <= 71)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 72 && value <= 75)
|
|
||||||
{
|
|
||||||
// Marigold[,Inspect,,Guide,] 7872,7873,7874,7875
|
|
||||||
return new PatchState(Produce.MARIGOLD, CropState.GROWING, value - 72);
|
|
||||||
}
|
|
||||||
if (value == 76)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 77 && value <= 80)
|
|
||||||
{
|
|
||||||
// Rosemary[,Inspect,,Guide,] 7904,7905,7906,7907
|
|
||||||
return new PatchState(Produce.ROSEMARY, CropState.GROWING, value - 77);
|
|
||||||
}
|
|
||||||
if (value == 81)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 82 && value <= 85)
|
|
||||||
{
|
|
||||||
// Nasturtium[,Inspect,,Guide,] 7888,7889,7890,7891
|
|
||||||
return new PatchState(Produce.NASTURTIUM, CropState.GROWING, value - 82);
|
|
||||||
}
|
|
||||||
if (value == 86)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 87 && value <= 90)
|
|
||||||
{
|
|
||||||
// Woad[,Inspect,,Guide,] 7924,7925,7926,7927
|
|
||||||
return new PatchState(Produce.WOAD, CropState.GROWING, value - 87);
|
|
||||||
}
|
|
||||||
if (value == 91)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 92 && value <= 95)
|
|
||||||
{
|
|
||||||
// Limpwurt[,Inspect,,Guide,] 7856,7857,7858,7859
|
|
||||||
return new PatchState(Produce.LIMPWURT, CropState.GROWING, value - 92);
|
|
||||||
}
|
|
||||||
if (value >= 96 && value <= 136)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 137 && value <= 139)
|
|
||||||
{
|
|
||||||
// Diseased marigold[Cure,Inspect,,Guide,] 7876,7877,7878
|
|
||||||
return new PatchState(Produce.MARIGOLD, CropState.DISEASED, value - 136);
|
|
||||||
}
|
|
||||||
if (value >= 140 && value <= 141)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 142 && value <= 144)
|
|
||||||
{
|
|
||||||
// Diseased rosemary[Cure,Inspect,,Guide,] 7908,7909,7910
|
|
||||||
return new PatchState(Produce.ROSEMARY, CropState.DISEASED, value - 141);
|
|
||||||
}
|
|
||||||
if (value >= 145 && value <= 146)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 147 && value <= 149)
|
|
||||||
{
|
|
||||||
// Diseased nasturtium[Cure,Inspect,,Guide,] 7892,7893,7894
|
|
||||||
return new PatchState(Produce.NASTURTIUM, CropState.DISEASED, value - 146);
|
|
||||||
}
|
|
||||||
if (value >= 150 && value <= 151)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 152 && value <= 154)
|
|
||||||
{
|
|
||||||
// Diseased woad[Cure,Inspect,,Guide,] 7928,7929,7930
|
|
||||||
return new PatchState(Produce.WOAD, CropState.DISEASED, value - 151);
|
|
||||||
}
|
|
||||||
if (value >= 155 && value <= 156)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 157 && value <= 159)
|
|
||||||
{
|
|
||||||
// Diseased limpwurt[Cure,Inspect,,Guide,] 7860,7861,7862
|
|
||||||
return new PatchState(Produce.LIMPWURT, CropState.DISEASED, value - 156);
|
|
||||||
}
|
|
||||||
if (value >= 160 && value <= 200)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 201 && value <= 203)
|
|
||||||
{
|
|
||||||
// Dead marigold[Clear,Inspect,,Guide,] 7879,7880,7881,7882
|
|
||||||
return new PatchState(Produce.MARIGOLD, CropState.DEAD, value - 200);
|
|
||||||
}
|
|
||||||
if (value == 205)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 206 && value <= 208)
|
|
||||||
{
|
|
||||||
// Dead rosemary[Clear,Inspect,,Guide,] 7911,7912,7913,7914
|
|
||||||
return new PatchState(Produce.ROSEMARY, CropState.DEAD, value - 205);
|
|
||||||
}
|
|
||||||
if (value == 210)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 211 && value <= 213)
|
|
||||||
{
|
|
||||||
// Dead nasturtium[Clear,Inspect,,Guide,] 7895,7896,7897,7898
|
|
||||||
return new PatchState(Produce.NASTURTIUM, CropState.DEAD, value - 210);
|
|
||||||
}
|
|
||||||
if (value == 215)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 216 && value <= 218)
|
|
||||||
{
|
|
||||||
// Dead woad[Clear,Inspect,,Guide,] 7931,7932,7933,7934
|
|
||||||
return new PatchState(Produce.WOAD, CropState.DEAD, value - 215);
|
|
||||||
}
|
|
||||||
if (value == 220)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
if (value >= 221 && value <= 224)
|
|
||||||
{
|
|
||||||
// Dead limpwurt[Clear,Inspect,,Guide,] 7863,7864,7865,7866
|
|
||||||
return new PatchState(Produce.LIMPWURT, CropState.DEAD, value - 220);
|
|
||||||
}
|
|
||||||
if (value >= 225 && value <= 255)
|
|
||||||
{
|
|
||||||
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
|
||||||
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
HERB(Tab.HERB)
|
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -970,7 +737,240 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BUSH(Tab.SPECIAL)
|
FLOWER(Tab.HERB, "Flowers")
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
PatchState forVarbitValue(int value)
|
||||||
|
{
|
||||||
|
if (value >= 0 && value <= 3)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7842,7841,7840
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3 - value);
|
||||||
|
}
|
||||||
|
if (value >= 4 && value <= 7)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 8 && value <= 11)
|
||||||
|
{
|
||||||
|
// Marigold[,Inspect,,Guide,] 7867,7868,7869,7870
|
||||||
|
return new PatchState(Produce.MARIGOLD, CropState.GROWING, value - 8);
|
||||||
|
}
|
||||||
|
if (value == 12)
|
||||||
|
{
|
||||||
|
// Marigold[Pick,Inspect,,Guide,] 7871
|
||||||
|
return new PatchState(Produce.MARIGOLD, CropState.HARVESTABLE, 12 - value);
|
||||||
|
}
|
||||||
|
if (value >= 13 && value <= 16)
|
||||||
|
{
|
||||||
|
// Rosemary[,Inspect,,Guide,] 7899,7900,7901,7902
|
||||||
|
return new PatchState(Produce.ROSEMARY, CropState.GROWING, value - 13);
|
||||||
|
}
|
||||||
|
if (value == 17)
|
||||||
|
{
|
||||||
|
// Rosemary[Pick,Inspect,,Guide,] 7903
|
||||||
|
return new PatchState(Produce.ROSEMARY, CropState.HARVESTABLE, 17 - value);
|
||||||
|
}
|
||||||
|
if (value >= 18 && value <= 21)
|
||||||
|
{
|
||||||
|
// Nasturtium[,Inspect,,Guide,] 7883,7884,7885,7886
|
||||||
|
return new PatchState(Produce.NASTURTIUM, CropState.GROWING, value - 18);
|
||||||
|
}
|
||||||
|
if (value == 22)
|
||||||
|
{
|
||||||
|
// Nasturtium[Pick,Inspect,,Guide,] 7887
|
||||||
|
return new PatchState(Produce.NASTURTIUM, CropState.HARVESTABLE, 22 - value);
|
||||||
|
}
|
||||||
|
if (value >= 23 && value <= 26)
|
||||||
|
{
|
||||||
|
// Woad[,Inspect,,Guide,] 7919,7920,7921,7922
|
||||||
|
return new PatchState(Produce.WOAD, CropState.GROWING, value - 23);
|
||||||
|
}
|
||||||
|
if (value == 27)
|
||||||
|
{
|
||||||
|
// Woad[Pick,Inspect,,Guide,] 7923
|
||||||
|
return new PatchState(Produce.WOAD, CropState.HARVESTABLE, 27 - value);
|
||||||
|
}
|
||||||
|
if (value >= 28 && value <= 31)
|
||||||
|
{
|
||||||
|
// Limpwurt[,Inspect,,Guide,] 7851,7852,7853,7854
|
||||||
|
return new PatchState(Produce.LIMPWURT, CropState.GROWING, value - 28);
|
||||||
|
}
|
||||||
|
if (value == 32)
|
||||||
|
{
|
||||||
|
// Limpwurt[Pick,Inspect,,Guide,] 7855
|
||||||
|
return new PatchState(Produce.LIMPWURT, CropState.HARVESTABLE, 32 - value);
|
||||||
|
}
|
||||||
|
if (value >= 33 && value <= 35)
|
||||||
|
{
|
||||||
|
// Scarecrow[Rake,Inspect,,Guide,Remove] 7918,7917,7916
|
||||||
|
return new PatchState(Produce.SCARECROW, CropState.GROWING, 35 - value);
|
||||||
|
}
|
||||||
|
if (value == 36)
|
||||||
|
{
|
||||||
|
// Scarecrow[Remove,Inspect,,Guide,] 7915
|
||||||
|
return new PatchState(Produce.SCARECROW, CropState.GROWING, 0);
|
||||||
|
}
|
||||||
|
if (value >= 37 && value <= 71)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 72 && value <= 75)
|
||||||
|
{
|
||||||
|
// Marigold[,Inspect,,Guide,] 7872,7873,7874,7875
|
||||||
|
return new PatchState(Produce.MARIGOLD, CropState.GROWING, value - 72);
|
||||||
|
}
|
||||||
|
if (value == 76)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 77 && value <= 80)
|
||||||
|
{
|
||||||
|
// Rosemary[,Inspect,,Guide,] 7904,7905,7906,7907
|
||||||
|
return new PatchState(Produce.ROSEMARY, CropState.GROWING, value - 77);
|
||||||
|
}
|
||||||
|
if (value == 81)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 82 && value <= 85)
|
||||||
|
{
|
||||||
|
// Nasturtium[,Inspect,,Guide,] 7888,7889,7890,7891
|
||||||
|
return new PatchState(Produce.NASTURTIUM, CropState.GROWING, value - 82);
|
||||||
|
}
|
||||||
|
if (value == 86)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 87 && value <= 90)
|
||||||
|
{
|
||||||
|
// Woad[,Inspect,,Guide,] 7924,7925,7926,7927
|
||||||
|
return new PatchState(Produce.WOAD, CropState.GROWING, value - 87);
|
||||||
|
}
|
||||||
|
if (value == 91)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 92 && value <= 95)
|
||||||
|
{
|
||||||
|
// Limpwurt[,Inspect,,Guide,] 7856,7857,7858,7859
|
||||||
|
return new PatchState(Produce.LIMPWURT, CropState.GROWING, value - 92);
|
||||||
|
}
|
||||||
|
if (value >= 96 && value <= 136)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 137 && value <= 139)
|
||||||
|
{
|
||||||
|
// Diseased marigold[Cure,Inspect,,Guide,] 7876,7877,7878
|
||||||
|
return new PatchState(Produce.MARIGOLD, CropState.DISEASED, value - 136);
|
||||||
|
}
|
||||||
|
if (value >= 140 && value <= 141)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 142 && value <= 144)
|
||||||
|
{
|
||||||
|
// Diseased rosemary[Cure,Inspect,,Guide,] 7908,7909,7910
|
||||||
|
return new PatchState(Produce.ROSEMARY, CropState.DISEASED, value - 141);
|
||||||
|
}
|
||||||
|
if (value >= 145 && value <= 146)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 147 && value <= 149)
|
||||||
|
{
|
||||||
|
// Diseased nasturtium[Cure,Inspect,,Guide,] 7892,7893,7894
|
||||||
|
return new PatchState(Produce.NASTURTIUM, CropState.DISEASED, value - 146);
|
||||||
|
}
|
||||||
|
if (value >= 150 && value <= 151)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 152 && value <= 154)
|
||||||
|
{
|
||||||
|
// Diseased woad[Cure,Inspect,,Guide,] 7928,7929,7930
|
||||||
|
return new PatchState(Produce.WOAD, CropState.DISEASED, value - 151);
|
||||||
|
}
|
||||||
|
if (value >= 155 && value <= 156)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 157 && value <= 159)
|
||||||
|
{
|
||||||
|
// Diseased limpwurt[Cure,Inspect,,Guide,] 7860,7861,7862
|
||||||
|
return new PatchState(Produce.LIMPWURT, CropState.DISEASED, value - 156);
|
||||||
|
}
|
||||||
|
if (value >= 160 && value <= 200)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 201 && value <= 203)
|
||||||
|
{
|
||||||
|
// Dead marigold[Clear,Inspect,,Guide,] 7879,7880,7881,7882
|
||||||
|
return new PatchState(Produce.MARIGOLD, CropState.DEAD, value - 200);
|
||||||
|
}
|
||||||
|
if (value == 205)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 206 && value <= 208)
|
||||||
|
{
|
||||||
|
// Dead rosemary[Clear,Inspect,,Guide,] 7911,7912,7913,7914
|
||||||
|
return new PatchState(Produce.ROSEMARY, CropState.DEAD, value - 205);
|
||||||
|
}
|
||||||
|
if (value == 210)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 211 && value <= 213)
|
||||||
|
{
|
||||||
|
// Dead nasturtium[Clear,Inspect,,Guide,] 7895,7896,7897,7898
|
||||||
|
return new PatchState(Produce.NASTURTIUM, CropState.DEAD, value - 210);
|
||||||
|
}
|
||||||
|
if (value == 215)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 216 && value <= 218)
|
||||||
|
{
|
||||||
|
// Dead woad[Clear,Inspect,,Guide,] 7931,7932,7933,7934
|
||||||
|
return new PatchState(Produce.WOAD, CropState.DEAD, value - 215);
|
||||||
|
}
|
||||||
|
if (value == 220)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
if (value >= 221 && value <= 224)
|
||||||
|
{
|
||||||
|
// Dead limpwurt[Clear,Inspect,,Guide,] 7863,7864,7865,7866
|
||||||
|
return new PatchState(Produce.LIMPWURT, CropState.DEAD, value - 220);
|
||||||
|
}
|
||||||
|
if (value >= 225 && value <= 255)
|
||||||
|
{
|
||||||
|
// Flower Patch[Rake,Inspect,,Guide,] 7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843,7843
|
||||||
|
return new PatchState(Produce.WEEDS, CropState.GROWING, 3);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
BUSH(Tab.BUSH, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1209,7 +1209,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FRUIT_TREE(Tab.FRUIT_TREE)
|
FRUIT_TREE(Tab.FRUIT_TREE, "Fruit trees")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1458,7 +1458,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HOPS(Tab.SPECIAL)
|
HOPS(Tab.SPECIAL, "Hops")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -1761,7 +1761,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TREE(Tab.TREE)
|
TREE(Tab.TREE, "")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2049,7 +2049,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HARDWOOD_TREE(Tab.TREE)
|
HARDWOOD_TREE(Tab.TREE, "Hardwood Trees")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2137,7 +2137,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SPIRIT_TREE(Tab.TREE)
|
SPIRIT_TREE(Tab.TREE, "Spirit Trees")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2185,7 +2185,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SEAWEED(Tab.SPECIAL)
|
SEAWEED(Tab.SPECIAL, "Seaweed")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2223,7 +2223,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CALQUAT(Tab.FRUIT_TREE)
|
CALQUAT(Tab.FRUIT_TREE, "Calquat")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2271,7 +2271,7 @@ public enum PatchImplementation
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GRAPES(Tab.SPECIAL)
|
GRAPES(Tab.BUSH, "Grapes")
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
PatchState forVarbitValue(int value)
|
PatchState forVarbitValue(int value)
|
||||||
@@ -2300,4 +2300,6 @@ public enum PatchImplementation
|
|||||||
abstract PatchState forVarbitValue(int value);
|
abstract PatchState forVarbitValue(int value);
|
||||||
|
|
||||||
private final Tab tab;
|
private final Tab tab;
|
||||||
|
|
||||||
|
private final String name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public enum Tab
|
|||||||
HERB("Herbs", ItemID.GRIMY_RANARR_WEED),
|
HERB("Herbs", ItemID.GRIMY_RANARR_WEED),
|
||||||
TREE("Trees", ItemID.MAHOGANY_LOGS),
|
TREE("Trees", ItemID.MAHOGANY_LOGS),
|
||||||
FRUIT_TREE("Fruit Trees", ItemID.PINEAPPLE),
|
FRUIT_TREE("Fruit Trees", ItemID.PINEAPPLE),
|
||||||
|
BUSH("Bushes", ItemID.REDBERRIES),
|
||||||
SPECIAL("Special", ItemID.MUSHROOM);
|
SPECIAL("Special", ItemID.MUSHROOM);
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Lotto <https://github.com/devLotto>
|
* Copyright (c) 2018, Lotto <https://github.com/devLotto>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -28,6 +29,7 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.awt.GridLayout;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.font.FontRenderContext;
|
import java.awt.font.FontRenderContext;
|
||||||
@@ -43,13 +45,16 @@ import javax.swing.BoxLayout;
|
|||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
import net.runelite.client.util.LinkBrowser;
|
import net.runelite.client.util.LinkBrowser;
|
||||||
|
import net.runelite.client.util.SwingUtil;
|
||||||
import net.runelite.http.api.RuneLiteAPI;
|
import net.runelite.http.api.RuneLiteAPI;
|
||||||
import net.runelite.http.api.feed.FeedItem;
|
import net.runelite.http.api.feed.FeedItem;
|
||||||
import net.runelite.http.api.feed.FeedItemType;
|
import net.runelite.http.api.feed.FeedItemType;
|
||||||
@@ -63,8 +68,10 @@ import okhttp3.ResponseBody;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
class FeedPanel extends PluginPanel
|
class FeedPanel extends PluginPanel
|
||||||
{
|
{
|
||||||
private static BufferedImage RUNELITE_ICON;
|
private static final ImageIcon RUNELITE_ICON;
|
||||||
private static BufferedImage OSRS_ICON;
|
private static final ImageIcon OSRS_ICON;
|
||||||
|
private static final ImageIcon RESET_ICON;
|
||||||
|
private static final ImageIcon RESET_ICON_CLICK; //used as a click effect (darker version of the reset icon)
|
||||||
|
|
||||||
private static final Color TWEET_BACKGROUND = new Color(15, 15, 15);
|
private static final Color TWEET_BACKGROUND = new Color(15, 15, 15);
|
||||||
private static final Color OSRS_NEWS_BACKGROUND = new Color(36, 30, 19);
|
private static final Color OSRS_NEWS_BACKGROUND = new Color(36, 30, 19);
|
||||||
@@ -74,6 +81,11 @@ class FeedPanel extends PluginPanel
|
|||||||
private static final int CONTENT_WIDTH = 148;
|
private static final int CONTENT_WIDTH = 148;
|
||||||
private static final int TIME_WIDTH = 20;
|
private static final int TIME_WIDTH = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds all feed items.
|
||||||
|
*/
|
||||||
|
private final JPanel feedContainer = new JPanel();
|
||||||
|
|
||||||
private static final Comparator<FeedItem> FEED_ITEM_COMPARATOR = (o1, o2) ->
|
private static final Comparator<FeedItem> FEED_ITEM_COMPARATOR = (o1, o2) ->
|
||||||
{
|
{
|
||||||
if (o1.getType() != o2.getType())
|
if (o1.getType() != o2.getType())
|
||||||
@@ -97,24 +109,16 @@ class FeedPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
synchronized (ImageIO.class)
|
synchronized (ImageIO.class)
|
||||||
{
|
{
|
||||||
RUNELITE_ICON = ImageIO.read(FeedPanel.class.getResourceAsStream("runelite.png"));
|
BufferedImage reset = ImageIO.read(FeedPanel.class.getResourceAsStream("reset.png"));
|
||||||
|
RUNELITE_ICON = new ImageIcon(ImageIO.read(FeedPanel.class.getResourceAsStream("runelite.png")));
|
||||||
|
OSRS_ICON = new ImageIcon(ImageIO.read(FeedPanel.class.getResourceAsStream("osrs.png")));
|
||||||
|
RESET_ICON = new ImageIcon(reset);
|
||||||
|
RESET_ICON_CLICK = new ImageIcon(SwingUtil.grayscaleOffset(reset, -100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
log.warn("Client icon failed to load", e);
|
throw new RuntimeException(e);
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
synchronized (ImageIO.class)
|
|
||||||
{
|
|
||||||
OSRS_ICON = ImageIO.read(FeedPanel.class.getResourceAsStream("osrs.png"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
log.warn("OSRS icon failed to load", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +129,56 @@ class FeedPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.feedSupplier = feedSupplier;
|
this.feedSupplier = feedSupplier;
|
||||||
|
|
||||||
|
setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
feedContainer.setLayout(new GridLayout(0, 1, 0, 4));
|
||||||
|
feedContainer.setOpaque(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This header contains the "News Feed" title and a refresh icon button.
|
||||||
|
*/
|
||||||
|
JPanel header = new JPanel();
|
||||||
|
header.setOpaque(false);
|
||||||
|
header.setLayout(new BorderLayout());
|
||||||
|
header.setBorder(new EmptyBorder(0, 0, 9, 0));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A refresh icon button, when clicked, it will swap icons for feedback effect and then call
|
||||||
|
* the rebuildFeed method.
|
||||||
|
*/
|
||||||
|
JLabel reset = new JLabel();
|
||||||
|
reset.setIcon(RESET_ICON);
|
||||||
|
reset.setVerticalAlignment(SwingConstants.CENTER);
|
||||||
|
reset.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
reset.setToolTipText("Refresh");
|
||||||
|
|
||||||
|
reset.addMouseListener(new MouseAdapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
reset.setIcon(RESET_ICON_CLICK);
|
||||||
|
rebuildFeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
reset.setIcon(RESET_ICON);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JLabel title = new JLabel("News feed");
|
||||||
|
title.setForeground(Color.WHITE);
|
||||||
|
|
||||||
|
header.add(title, BorderLayout.WEST);
|
||||||
|
header.add(reset, BorderLayout.EAST);
|
||||||
|
|
||||||
|
add(header, BorderLayout.NORTH);
|
||||||
|
add(feedContainer, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rebuildFeed()
|
void rebuildFeed()
|
||||||
@@ -138,7 +192,7 @@ class FeedPanel extends PluginPanel
|
|||||||
|
|
||||||
SwingUtilities.invokeLater(() ->
|
SwingUtilities.invokeLater(() ->
|
||||||
{
|
{
|
||||||
removeAll();
|
feedContainer.removeAll();
|
||||||
|
|
||||||
feed.getItems()
|
feed.getItems()
|
||||||
.stream()
|
.stream()
|
||||||
@@ -207,14 +261,14 @@ class FeedPanel extends PluginPanel
|
|||||||
case OSRS_NEWS:
|
case OSRS_NEWS:
|
||||||
if (OSRS_ICON != null)
|
if (OSRS_ICON != null)
|
||||||
{
|
{
|
||||||
avatar.setIcon(new ImageIcon(OSRS_ICON));
|
avatar.setIcon(OSRS_ICON);
|
||||||
}
|
}
|
||||||
avatarAndRight.setBackground(OSRS_NEWS_BACKGROUND);
|
avatarAndRight.setBackground(OSRS_NEWS_BACKGROUND);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (RUNELITE_ICON != null)
|
if (RUNELITE_ICON != null)
|
||||||
{
|
{
|
||||||
avatar.setIcon(new ImageIcon(RUNELITE_ICON));
|
avatar.setIcon(RUNELITE_ICON);
|
||||||
}
|
}
|
||||||
avatarAndRight.setBackground(BLOG_POST_BACKGROUND);
|
avatarAndRight.setBackground(BLOG_POST_BACKGROUND);
|
||||||
break;
|
break;
|
||||||
@@ -296,7 +350,7 @@ class FeedPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
add(avatarAndRight);
|
feedContainer.add(avatarAndRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String durationToString(Duration duration)
|
private String durationToString(Duration duration)
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ public class FeedPlugin extends Plugin
|
|||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("News Feed")
|
.name("News Feed")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(8)
|
||||||
.panel(feedPanel)
|
.panel(feedPanel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Seth <https://github.com/sethtroll>
|
* Copyright (c) 2018, Seth <https://github.com/sethtroll>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -32,14 +33,17 @@ import java.awt.event.MouseAdapter;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.border.CompoundBorder;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.border.LineBorder;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.game.AsyncBufferedImage;
|
import net.runelite.client.game.AsyncBufferedImage;
|
||||||
import net.runelite.client.util.LinkBrowser;
|
import net.runelite.client.util.LinkBrowser;
|
||||||
import net.runelite.client.util.StackFormatter;
|
import net.runelite.client.util.StackFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This panel displays an individual item result in the
|
||||||
|
* Grand Exchange search plugin.
|
||||||
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class GrandExchangeItemPanel extends JPanel
|
class GrandExchangeItemPanel extends JPanel
|
||||||
{
|
{
|
||||||
@@ -52,7 +56,8 @@ class GrandExchangeItemPanel extends JPanel
|
|||||||
layout.setHgap(5);
|
layout.setHgap(5);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
setToolTipText(name);
|
setToolTipText(name);
|
||||||
|
setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||||
|
|
||||||
Color background = getBackground();
|
Color background = getBackground();
|
||||||
|
|
||||||
addMouseListener(new MouseAdapter()
|
addMouseListener(new MouseAdapter()
|
||||||
@@ -60,7 +65,7 @@ class GrandExchangeItemPanel extends JPanel
|
|||||||
@Override
|
@Override
|
||||||
public void mouseEntered(MouseEvent e)
|
public void mouseEntered(MouseEvent e)
|
||||||
{
|
{
|
||||||
setBackground(getBackground().darker().darker());
|
setBackground(getBackground().brighter());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,11 +81,7 @@ class GrandExchangeItemPanel extends JPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setBorder(new CompoundBorder
|
setBorder(new EmptyBorder(5, 5, 5, 0));
|
||||||
(
|
|
||||||
new LineBorder(getBackground().brighter(), 1),
|
|
||||||
new EmptyBorder(5, 5, 5, 5)
|
|
||||||
));
|
|
||||||
|
|
||||||
// Icon
|
// Icon
|
||||||
JLabel itemIcon = new JLabel();
|
JLabel itemIcon = new JLabel();
|
||||||
@@ -97,6 +98,9 @@ class GrandExchangeItemPanel extends JPanel
|
|||||||
|
|
||||||
// Item name
|
// Item name
|
||||||
JLabel itemName = new JLabel();
|
JLabel itemName = new JLabel();
|
||||||
|
itemName.setForeground(Color.WHITE);
|
||||||
|
itemName.setMaximumSize(new Dimension(0, 0)); // to limit the label's size for
|
||||||
|
itemName.setPreferredSize(new Dimension(0, 0)); // items with longer names
|
||||||
itemName.setText(name);
|
itemName.setText(name);
|
||||||
rightPanel.add(itemName);
|
rightPanel.add(itemName);
|
||||||
|
|
||||||
@@ -110,13 +114,13 @@ class GrandExchangeItemPanel extends JPanel
|
|||||||
{
|
{
|
||||||
gePriceLabel.setText("N/A");
|
gePriceLabel.setText("N/A");
|
||||||
}
|
}
|
||||||
gePriceLabel.setForeground(Color.GREEN);
|
gePriceLabel.setForeground(ColorScheme.GRAND_EXCHANGE_PRICE);
|
||||||
rightPanel.add(gePriceLabel);
|
rightPanel.add(gePriceLabel);
|
||||||
|
|
||||||
// Alch price
|
// Alch price
|
||||||
JLabel haPriceLabel = new JLabel();
|
JLabel haPriceLabel = new JLabel();
|
||||||
haPriceLabel.setText(StackFormatter.formatNumber(haPrice.intValue()) + " alch");
|
haPriceLabel.setText(StackFormatter.formatNumber(haPrice.intValue()) + " alch");
|
||||||
haPriceLabel.setForeground(Color.orange);
|
haPriceLabel.setForeground(ColorScheme.GRAND_EXCHANGE_ALCH);
|
||||||
rightPanel.add(haPriceLabel);
|
rightPanel.add(haPriceLabel);
|
||||||
|
|
||||||
add(rightPanel, BorderLayout.CENTER);
|
add(rightPanel, BorderLayout.CENTER);
|
||||||
@@ -131,4 +135,4 @@ class GrandExchangeItemPanel extends JPanel
|
|||||||
|
|
||||||
LinkBrowser.browse(url);
|
LinkBrowser.browse(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, SomeoneWithAnInternetConnection
|
* Copyright (c) 2018, SomeoneWithAnInternetConnection
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -28,38 +29,73 @@ package net.runelite.client.plugins.grandexchange;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.CardLayout;
|
import java.awt.CardLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridLayout;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.swing.BorderFactory;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.Box;
|
|
||||||
import javax.swing.BoxLayout;
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.border.TitledBorder;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.GrandExchangeOffer;
|
import net.runelite.api.GrandExchangeOffer;
|
||||||
import net.runelite.api.GrandExchangeOfferState;
|
import net.runelite.api.GrandExchangeOfferState;
|
||||||
|
import static net.runelite.api.GrandExchangeOfferState.CANCELLED_BUY;
|
||||||
|
import static net.runelite.api.GrandExchangeOfferState.CANCELLED_SELL;
|
||||||
import static net.runelite.api.GrandExchangeOfferState.EMPTY;
|
import static net.runelite.api.GrandExchangeOfferState.EMPTY;
|
||||||
import net.runelite.api.ItemComposition;
|
import net.runelite.api.ItemComposition;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
|
import net.runelite.client.ui.components.ThinProgressBar;
|
||||||
import net.runelite.client.util.StackFormatter;
|
import net.runelite.client.util.StackFormatter;
|
||||||
|
import net.runelite.client.util.SwingUtil;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class GrandExchangeOfferSlot extends JPanel
|
public class GrandExchangeOfferSlot extends JPanel
|
||||||
{
|
{
|
||||||
private static final Color GE_INPROGRESS_ORANGE = new Color(0xd8, 0x80, 0x20).brighter();
|
private static final String FACE_CARD = "FACE_CARD";
|
||||||
private static final Color GE_FINISHED_GREEN = new Color(0, 0x5f, 0);
|
private static final String DETAILS_CARD = "DETAILS_CARD";
|
||||||
private static final Color GE_CANCELLED_RED = new Color(0x8f, 0, 0);
|
|
||||||
|
|
||||||
private static final String INFO_CARD = "INFO_CARD";
|
private static final ImageIcon RIGHT_ARROW_ICON;
|
||||||
private static final String EMPTY_CARD = "EMPTY_CARD";
|
private static final ImageIcon LEFT_ARROW_ICON;
|
||||||
|
|
||||||
|
private final JPanel container = new JPanel();
|
||||||
private final CardLayout cardLayout = new CardLayout();
|
private final CardLayout cardLayout = new CardLayout();
|
||||||
|
|
||||||
private final JLabel itemIcon = new JLabel();
|
private final JLabel itemIcon = new JLabel();
|
||||||
private final TitledBorder itemName = BorderFactory.createTitledBorder("Nothing");
|
private final JLabel itemName = new JLabel();
|
||||||
private final JLabel offerState = new JLabel("Text so the label has height");
|
private final JLabel offerInfo = new JLabel();
|
||||||
private final JProgressBar progressBar = new JProgressBar();
|
private final JLabel switchFaceViewIcon = new JLabel();
|
||||||
|
|
||||||
|
private final JLabel itemPrice = new JLabel();
|
||||||
|
private final JLabel offerSpent = new JLabel();
|
||||||
|
private final JLabel switchDetailsViewIcon = new JLabel();
|
||||||
|
|
||||||
|
private final ThinProgressBar progressBar = new ThinProgressBar();
|
||||||
|
|
||||||
|
private boolean showingFace = true;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (ImageIO.class)
|
||||||
|
{
|
||||||
|
RIGHT_ARROW_ICON = new ImageIcon(ImageIO.read(GrandExchangeOfferSlot.class.getResourceAsStream("arrow_right.png")));
|
||||||
|
LEFT_ARROW_ICON = new ImageIcon(ImageIO.read(GrandExchangeOfferSlot.class.getResourceAsStream("arrow_left.png")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This (sub)panel is used for each GE slot displayed
|
* This (sub)panel is used for each GE slot displayed
|
||||||
@@ -72,123 +108,188 @@ public class GrandExchangeOfferSlot extends JPanel
|
|||||||
|
|
||||||
private void buildPanel()
|
private void buildPanel()
|
||||||
{
|
{
|
||||||
setBorder(BorderFactory.createCompoundBorder(
|
setLayout(new BorderLayout());
|
||||||
// Add a margin underneath each slot panel to space them out
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
BorderFactory.createEmptyBorder(0, 0, 3, 0),
|
setBorder(new EmptyBorder(7, 0, 0, 0));
|
||||||
itemName
|
|
||||||
));
|
|
||||||
|
|
||||||
// The default border color is kind of dark, so we change it to something lighter
|
final MouseListener ml = new MouseAdapter()
|
||||||
itemName.setBorder(BorderFactory.createLineBorder(getBackground().brighter()));
|
{
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
super.mousePressed(mouseEvent);
|
||||||
|
switchPanel();
|
||||||
|
}
|
||||||
|
|
||||||
progressBar.setStringPainted(true);
|
@Override
|
||||||
|
public void mouseEntered(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
super.mouseEntered(mouseEvent);
|
||||||
|
container.setBackground(ColorScheme.MEDIUM_GRAY_COLOR.brighter());
|
||||||
|
}
|
||||||
|
|
||||||
setLayout(cardLayout);
|
@Override
|
||||||
|
public void mouseExited(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
super.mouseExited(mouseEvent);
|
||||||
|
container.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Card for when the slot has an offer in it
|
container.setLayout(cardLayout);
|
||||||
JPanel infoCard = new JPanel();
|
container.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||||
add(infoCard, INFO_CARD);
|
|
||||||
// Add padding to give the icon and progress bar room to breathe
|
|
||||||
infoCard.setBorder(BorderFactory.createEmptyBorder(0, 2, 2, 2));
|
|
||||||
|
|
||||||
infoCard.setLayout(new BoxLayout(infoCard, BoxLayout.X_AXIS));
|
JPanel faceCard = new JPanel();
|
||||||
// Icon on the left
|
faceCard.setOpaque(false);
|
||||||
infoCard.add(itemIcon);
|
faceCard.setLayout(new BorderLayout());
|
||||||
|
faceCard.addMouseListener(ml);
|
||||||
|
|
||||||
// Info on the right
|
itemIcon.setVerticalAlignment(JLabel.CENTER);
|
||||||
JPanel offerStatePanel = new JPanel();
|
itemIcon.setHorizontalAlignment(JLabel.CENTER);
|
||||||
offerStatePanel.setLayout(new BoxLayout(offerStatePanel, BoxLayout.Y_AXIS));
|
itemIcon.setPreferredSize(new Dimension(45, 45));
|
||||||
offerStatePanel.add(offerState);
|
|
||||||
offerStatePanel.add(progressBar);
|
|
||||||
infoCard.add(offerStatePanel);
|
|
||||||
|
|
||||||
// Card for when the slot is empty
|
itemName.setForeground(Color.WHITE);
|
||||||
JPanel emptySlotCard = new JPanel();
|
itemName.setVerticalAlignment(JLabel.BOTTOM);
|
||||||
add(emptySlotCard, EMPTY_CARD);
|
itemName.setFont(FontManager.getRunescapeSmallFont());
|
||||||
// Counteract the height lost to the text at the top of the TitledBorder
|
|
||||||
int itemNameBorderHeight = itemName.getBorderInsets(this).top;
|
|
||||||
emptySlotCard.setBorder(BorderFactory.createEmptyBorder(0, 0, (itemNameBorderHeight - 1) / 2, 0));
|
|
||||||
// Center the "Empty" label horizontally
|
|
||||||
emptySlotCard.setLayout( new BoxLayout(emptySlotCard, BoxLayout.X_AXIS));
|
|
||||||
emptySlotCard.add(Box.createHorizontalGlue());
|
|
||||||
emptySlotCard.add(new JLabel(getNameForState(EMPTY)), BorderLayout.CENTER);
|
|
||||||
emptySlotCard.add(Box.createHorizontalGlue());
|
|
||||||
|
|
||||||
cardLayout.show(this, EMPTY_CARD);
|
offerInfo.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||||
|
offerInfo.setVerticalAlignment(JLabel.TOP);
|
||||||
|
offerInfo.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
switchFaceViewIcon.setIcon(RIGHT_ARROW_ICON);
|
||||||
|
switchFaceViewIcon.setVerticalAlignment(JLabel.CENTER);
|
||||||
|
switchFaceViewIcon.setHorizontalAlignment(JLabel.CENTER);
|
||||||
|
switchFaceViewIcon.setPreferredSize(new Dimension(30, 45));
|
||||||
|
|
||||||
|
JPanel offerFaceDetails = new JPanel();
|
||||||
|
offerFaceDetails.setOpaque(false);
|
||||||
|
offerFaceDetails.setLayout(new GridLayout(2, 1, 0, 2));
|
||||||
|
|
||||||
|
offerFaceDetails.add(itemName);
|
||||||
|
offerFaceDetails.add(offerInfo);
|
||||||
|
|
||||||
|
faceCard.add(offerFaceDetails, BorderLayout.CENTER);
|
||||||
|
faceCard.add(itemIcon, BorderLayout.WEST);
|
||||||
|
faceCard.add(switchFaceViewIcon, BorderLayout.EAST);
|
||||||
|
|
||||||
|
JPanel detailsCard = new JPanel();
|
||||||
|
detailsCard.setOpaque(false);
|
||||||
|
detailsCard.setLayout(new BorderLayout());
|
||||||
|
detailsCard.setBorder(new EmptyBorder(0, 15, 0, 0));
|
||||||
|
detailsCard.addMouseListener(ml);
|
||||||
|
|
||||||
|
itemPrice.setForeground(Color.WHITE);
|
||||||
|
itemPrice.setVerticalAlignment(JLabel.BOTTOM);
|
||||||
|
itemPrice.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
offerSpent.setForeground(Color.WHITE);
|
||||||
|
offerSpent.setVerticalAlignment(JLabel.TOP);
|
||||||
|
offerSpent.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
switchDetailsViewIcon.setIcon(LEFT_ARROW_ICON);
|
||||||
|
switchDetailsViewIcon.setVerticalAlignment(JLabel.CENTER);
|
||||||
|
switchDetailsViewIcon.setHorizontalAlignment(JLabel.CENTER);
|
||||||
|
switchDetailsViewIcon.setPreferredSize(new Dimension(30, 45));
|
||||||
|
|
||||||
|
JPanel offerDetails = new JPanel();
|
||||||
|
offerDetails.setOpaque(false);
|
||||||
|
offerDetails.setLayout(new GridLayout(2, 1));
|
||||||
|
|
||||||
|
offerDetails.add(itemPrice);
|
||||||
|
offerDetails.add(offerSpent);
|
||||||
|
|
||||||
|
detailsCard.add(offerDetails, BorderLayout.CENTER);
|
||||||
|
detailsCard.add(switchDetailsViewIcon, BorderLayout.EAST);
|
||||||
|
|
||||||
|
container.add(faceCard, FACE_CARD);
|
||||||
|
container.add(detailsCard, DETAILS_CARD);
|
||||||
|
|
||||||
|
cardLayout.show(container, FACE_CARD);
|
||||||
|
|
||||||
|
add(container, BorderLayout.CENTER);
|
||||||
|
add(progressBar, BorderLayout.SOUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateOffer(ItemComposition offerItem, BufferedImage itemImage, @Nullable GrandExchangeOffer newOffer)
|
void updateOffer(ItemComposition offerItem, BufferedImage itemImage, @Nullable GrandExchangeOffer newOffer)
|
||||||
{
|
{
|
||||||
if (newOffer == null || newOffer.getState() == EMPTY)
|
if (newOffer == null || newOffer.getState() == EMPTY)
|
||||||
{
|
{
|
||||||
cardLayout.show(this, EMPTY_CARD);
|
return;
|
||||||
itemName.setTitle("Nothing");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cardLayout.show(this, INFO_CARD);
|
cardLayout.show(container, FACE_CARD);
|
||||||
|
|
||||||
itemName.setTitle(offerItem.getName());
|
itemName.setText(offerItem.getName());
|
||||||
|
itemIcon.setIcon(new ImageIcon(itemImage));
|
||||||
|
|
||||||
boolean shouldStack = offerItem.isStackable() || newOffer.getTotalQuantity() > 1;
|
boolean buying = newOffer.getState() == GrandExchangeOfferState.BOUGHT
|
||||||
ImageIcon newItemIcon = new ImageIcon(itemImage);
|
|| newOffer.getState() == GrandExchangeOfferState.BUYING
|
||||||
itemIcon.setIcon(newItemIcon);
|
|| newOffer.getState() == GrandExchangeOfferState.CANCELLED_BUY;
|
||||||
|
|
||||||
offerState.setText(getNameForState(newOffer.getState())
|
String offerState = (buying ? "Bought " : "Sold ")
|
||||||
+ " at "
|
+ StackFormatter.quantityToRSDecimalStack(newOffer.getQuantitySold()) + " / "
|
||||||
+ StackFormatter.formatNumber(newOffer.getState() == GrandExchangeOfferState.BOUGHT ? (newOffer.getSpent() / newOffer.getTotalQuantity()) : newOffer.getPrice())
|
+ StackFormatter.quantityToRSDecimalStack(newOffer.getTotalQuantity());
|
||||||
+ (newOffer.getTotalQuantity() > 1 ? " gp ea" : " gp"));
|
|
||||||
|
|
||||||
progressBar.setMaximum(newOffer.getTotalQuantity());
|
offerInfo.setText(offerState);
|
||||||
|
|
||||||
|
itemPrice.setText(htmlLabel("Price each: ", newOffer.getPrice() + ""));
|
||||||
|
|
||||||
|
String action = buying ? "Spent: " : "Received: ";
|
||||||
|
|
||||||
|
offerSpent.setText(htmlLabel(action, StackFormatter.formatNumber(newOffer.getSpent()) + " / "
|
||||||
|
+ StackFormatter.formatNumber(newOffer.getPrice() * newOffer.getTotalQuantity())));
|
||||||
|
|
||||||
|
progressBar.setForeground(getProgressColor(newOffer));
|
||||||
|
progressBar.setMaximumValue(newOffer.getTotalQuantity());
|
||||||
progressBar.setValue(newOffer.getQuantitySold());
|
progressBar.setValue(newOffer.getQuantitySold());
|
||||||
progressBar.setBackground(getColorForState(newOffer.getState()));
|
progressBar.update();
|
||||||
progressBar.setString(newOffer.getQuantitySold() + "/" + newOffer.getTotalQuantity());
|
|
||||||
|
/* Couldn't set the tooltip for the container panel as the children override it, so I'm setting
|
||||||
|
* the tooltips on the children instead. */
|
||||||
|
for (Component c : container.getComponents())
|
||||||
|
{
|
||||||
|
if (c instanceof JPanel)
|
||||||
|
{
|
||||||
|
JPanel panel = (JPanel) c;
|
||||||
|
panel.setToolTipText(htmlTooltip(((int) progressBar.getPercentage()) + "%"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revalidate();
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNameForState(GrandExchangeOfferState state)
|
private String htmlTooltip(String value)
|
||||||
{
|
{
|
||||||
switch (state)
|
return "<html><body style = 'color:" + SwingUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR) + "'>Progress: <span style = 'color:white'>" + value + "</span></body></html>";
|
||||||
{
|
|
||||||
case CANCELLED_BUY:
|
|
||||||
return "Buying cancelled";
|
|
||||||
case CANCELLED_SELL:
|
|
||||||
return "Selling cancelled";
|
|
||||||
case BUYING:
|
|
||||||
return "Buying";
|
|
||||||
case BOUGHT:
|
|
||||||
return "Bought";
|
|
||||||
case SELLING:
|
|
||||||
return "Selling";
|
|
||||||
case SOLD:
|
|
||||||
return "Sold";
|
|
||||||
case EMPTY:
|
|
||||||
default:
|
|
||||||
return "Empty";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color getColorForState(GrandExchangeOfferState state)
|
private String htmlLabel(String key, String value)
|
||||||
{
|
{
|
||||||
switch (state)
|
return "<html><body style = 'color:white'>" + key + "<span style = 'color:" + SwingUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR) + "'>" + value + "</span></body></html>";
|
||||||
{
|
|
||||||
case CANCELLED_BUY:
|
|
||||||
case CANCELLED_SELL:
|
|
||||||
return GE_CANCELLED_RED;
|
|
||||||
case BUYING:
|
|
||||||
case SELLING:
|
|
||||||
return GE_INPROGRESS_ORANGE;
|
|
||||||
case BOUGHT:
|
|
||||||
case SOLD:
|
|
||||||
return GE_FINISHED_GREEN;
|
|
||||||
case EMPTY:
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void switchPanel()
|
||||||
|
{
|
||||||
|
this.showingFace = !this.showingFace;
|
||||||
|
cardLayout.show(container, showingFace ? FACE_CARD : DETAILS_CARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color getProgressColor(GrandExchangeOffer offer)
|
||||||
|
{
|
||||||
|
if (offer.getState() == CANCELLED_BUY || offer.getState() == CANCELLED_SELL)
|
||||||
|
{
|
||||||
|
return ColorScheme.PROGRESS_ERROR_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offer.getQuantitySold() == offer.getTotalQuantity())
|
||||||
|
{
|
||||||
|
return ColorScheme.PROGRESS_COMPLETE_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ColorScheme.PROGRESS_INPROGRESS_COLOR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, SomeoneWithAnInternetConnection
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.grandexchange;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.CardLayout;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.GrandExchangeOffer;
|
||||||
|
import net.runelite.api.GrandExchangeOfferState;
|
||||||
|
import net.runelite.api.ItemComposition;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.components.PluginErrorPanel;
|
||||||
|
|
||||||
|
public class GrandExchangeOffersPanel extends JPanel
|
||||||
|
{
|
||||||
|
private static final String ERROR_PANEL = "ERROR_PANEL";
|
||||||
|
private static final String OFFERS_PANEL = "OFFERS_PANEL";
|
||||||
|
|
||||||
|
private static final int MAX_OFFERS = 8;
|
||||||
|
|
||||||
|
private final GridBagConstraints constraints = new GridBagConstraints();
|
||||||
|
private final CardLayout cardLayout = new CardLayout();
|
||||||
|
|
||||||
|
/* The offers container, this will hold all the individual ge offers panels */
|
||||||
|
private final JPanel offerPanel = new JPanel();
|
||||||
|
|
||||||
|
/* The error panel, this displays an error message */
|
||||||
|
private final PluginErrorPanel errorPanel = new PluginErrorPanel();
|
||||||
|
|
||||||
|
/* The center panel, this holds either the error panel or the offers container */
|
||||||
|
private final JPanel container = new JPanel(cardLayout);
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
private final ItemManager itemManager;
|
||||||
|
private final ScheduledExecutorService executor;
|
||||||
|
|
||||||
|
private GrandExchangeOfferSlot[] offerSlotPanels = new GrandExchangeOfferSlot[MAX_OFFERS];
|
||||||
|
|
||||||
|
public GrandExchangeOffersPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
this.itemManager = itemManager;
|
||||||
|
this.executor = executor;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
constraints.weightx = 1;
|
||||||
|
constraints.gridx = 0;
|
||||||
|
constraints.gridy = 0;
|
||||||
|
|
||||||
|
/* This panel wraps the offers panel and limits its height */
|
||||||
|
JPanel offersWrapper = new JPanel(new BorderLayout());
|
||||||
|
offersWrapper.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
offersWrapper.add(offerPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
offerPanel.setLayout(new GridBagLayout());
|
||||||
|
offerPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
offerPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
/* This panel wraps the error panel and limits its height */
|
||||||
|
JPanel errorWrapper = new JPanel(new BorderLayout());
|
||||||
|
errorWrapper.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
errorWrapper.add(errorPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
errorPanel.setBorder(new EmptyBorder(50, 20, 20, 20));
|
||||||
|
errorPanel.setContent("No offers detected", "No grand exchange offers were found on your account.");
|
||||||
|
|
||||||
|
container.add(offersWrapper, OFFERS_PANEL);
|
||||||
|
container.add(errorWrapper, ERROR_PANEL);
|
||||||
|
|
||||||
|
add(container, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
resetOffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetOffers()
|
||||||
|
{
|
||||||
|
offerPanel.removeAll();
|
||||||
|
for (int i = 0; i < offerSlotPanels.length; i++)
|
||||||
|
{
|
||||||
|
offerSlotPanels[i] = null;
|
||||||
|
}
|
||||||
|
updateEmptyOffersPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateOffer(ItemComposition item, BufferedImage itemImage, GrandExchangeOffer newOffer, int slot)
|
||||||
|
{
|
||||||
|
/* If slot was previously filled, and is now empty, remove it from the list */
|
||||||
|
if (newOffer == null || newOffer.getState() == GrandExchangeOfferState.EMPTY)
|
||||||
|
{
|
||||||
|
if (offerSlotPanels[slot] != null)
|
||||||
|
{
|
||||||
|
offerPanel.remove(offerSlotPanels[slot]);
|
||||||
|
offerSlotPanels[slot] = null;
|
||||||
|
revalidate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeTopMargin();
|
||||||
|
updateEmptyOffersPanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If slot was empty, and is now filled, add it to the list */
|
||||||
|
if (offerSlotPanels[slot] == null)
|
||||||
|
{
|
||||||
|
GrandExchangeOfferSlot newSlot = new GrandExchangeOfferSlot();
|
||||||
|
offerSlotPanels[slot] = newSlot;
|
||||||
|
offerPanel.add(newSlot, constraints);
|
||||||
|
constraints.gridy++;
|
||||||
|
}
|
||||||
|
|
||||||
|
offerSlotPanels[slot].updateOffer(item, itemImage, newOffer);
|
||||||
|
|
||||||
|
removeTopMargin();
|
||||||
|
|
||||||
|
revalidate();
|
||||||
|
repaint();
|
||||||
|
|
||||||
|
updateEmptyOffersPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the border for the first offer slot.
|
||||||
|
*/
|
||||||
|
private void removeTopMargin()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (offerPanel.getComponentCount() <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JPanel firstItem = (JPanel) offerPanel.getComponent(0);
|
||||||
|
firstItem.setBorder(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method calculates the amount of empty ge offer slots, if all slots are empty,
|
||||||
|
* it shows the error panel.
|
||||||
|
*/
|
||||||
|
private void updateEmptyOffersPanel()
|
||||||
|
{
|
||||||
|
int nullCount = 0;
|
||||||
|
for (GrandExchangeOfferSlot slot : offerSlotPanels)
|
||||||
|
{
|
||||||
|
if (slot == null)
|
||||||
|
{
|
||||||
|
nullCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullCount == MAX_OFFERS)
|
||||||
|
{
|
||||||
|
offerPanel.removeAll();
|
||||||
|
cardLayout.show(container, ERROR_PANEL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cardLayout.show(container, OFFERS_PANEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, SomeoneWithAnInternetConnection
|
* Copyright (c) 2018, SomeoneWithAnInternetConnection
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,58 +27,58 @@
|
|||||||
package net.runelite.client.plugins.grandexchange;
|
package net.runelite.client.plugins.grandexchange;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.swing.BoxLayout;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GrandExchangeOffer;
|
|
||||||
import net.runelite.api.ItemComposition;
|
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
||||||
|
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class GrandExchangePanel extends PluginPanel
|
class GrandExchangePanel extends PluginPanel
|
||||||
{
|
{
|
||||||
private static final int MAX_OFFERS = 8;
|
|
||||||
|
// this panel will hold either the ge search panel or the ge offers panel
|
||||||
|
private final JPanel display = new JPanel();
|
||||||
|
|
||||||
|
private final MaterialTabGroup tabGroup = new MaterialTabGroup(display);
|
||||||
|
private final MaterialTab searchTab;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private GrandExchangeSearchPanel searchPanel;
|
private GrandExchangeSearchPanel searchPanel;
|
||||||
|
@Getter
|
||||||
private GrandExchangeOfferSlot[] offerSlotPanels = new GrandExchangeOfferSlot[MAX_OFFERS];
|
private GrandExchangeOffersPanel offersPanel;
|
||||||
|
|
||||||
private JPanel offerPanel = new JPanel();
|
|
||||||
|
|
||||||
private JTabbedPane tabbedPane = new JTabbedPane();
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GrandExchangePanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
GrandExchangePanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
||||||
{
|
{
|
||||||
setLayout(new BorderLayout());
|
super(false);
|
||||||
add(tabbedPane, BorderLayout.NORTH);
|
|
||||||
|
|
||||||
// Offer Panel
|
setLayout(new BorderLayout());
|
||||||
offerPanel.setLayout(new BoxLayout(offerPanel, BoxLayout.Y_AXIS));
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
for (int i = 0; i < offerSlotPanels.length; ++i)
|
|
||||||
{
|
|
||||||
offerSlotPanels[i] = new GrandExchangeOfferSlot();
|
|
||||||
offerPanel.add(offerSlotPanels[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search Panel
|
// Search Panel
|
||||||
searchPanel = new GrandExchangeSearchPanel(client, itemManager, executor);
|
searchPanel = new GrandExchangeSearchPanel(client, itemManager, executor);
|
||||||
|
|
||||||
tabbedPane.addTab("Offers", offerPanel);
|
//Offers Panel
|
||||||
tabbedPane.addTab("Search", searchPanel);
|
offersPanel = new GrandExchangeOffersPanel(client, itemManager, executor);
|
||||||
}
|
|
||||||
|
|
||||||
void updateOffer(ItemComposition item, BufferedImage itemImage, GrandExchangeOffer newOffer, int slot)
|
MaterialTab offersTab = new MaterialTab("Offers", tabGroup, offersPanel);
|
||||||
{
|
searchTab = new MaterialTab("Search", tabGroup, searchPanel);
|
||||||
offerSlotPanels[slot].updateOffer(item, itemImage, newOffer);
|
|
||||||
|
tabGroup.setBorder(new EmptyBorder(5, 0, 0, 0));
|
||||||
|
tabGroup.addTab(offersTab);
|
||||||
|
tabGroup.addTab(searchTab);
|
||||||
|
tabGroup.select(offersTab); // selects the default selected tab
|
||||||
|
|
||||||
|
add(tabGroup, BorderLayout.NORTH);
|
||||||
|
add(display, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showSearch()
|
void showSearch()
|
||||||
@@ -87,7 +88,7 @@ class GrandExchangePanel extends PluginPanel
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tabbedPane.setSelectedComponent(searchPanel);
|
tabGroup.select(searchTab);
|
||||||
revalidate();
|
revalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,7 @@ import net.runelite.api.ItemComposition;
|
|||||||
import net.runelite.api.MenuEntry;
|
import net.runelite.api.MenuEntry;
|
||||||
import net.runelite.api.events.ConfigChanged;
|
import net.runelite.api.events.ConfigChanged;
|
||||||
import net.runelite.api.events.FocusChanged;
|
import net.runelite.api.events.FocusChanged;
|
||||||
|
import net.runelite.api.events.GameStateChanged;
|
||||||
import net.runelite.api.events.GrandExchangeOfferChanged;
|
import net.runelite.api.events.GrandExchangeOfferChanged;
|
||||||
import net.runelite.api.events.MenuEntryAdded;
|
import net.runelite.api.events.MenuEntryAdded;
|
||||||
import net.runelite.api.widgets.WidgetID;
|
import net.runelite.api.widgets.WidgetID;
|
||||||
@@ -113,6 +114,7 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
button = NavigationButton.builder()
|
button = NavigationButton.builder()
|
||||||
.name("GE Offers")
|
.name("GE Offers")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(3)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -161,7 +163,16 @@ public class GrandExchangePlugin extends Plugin
|
|||||||
ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId());
|
ItemComposition offerItem = itemManager.getItemComposition(offer.getItemId());
|
||||||
boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1;
|
boolean shouldStack = offerItem.isStackable() || offer.getTotalQuantity() > 1;
|
||||||
BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack);
|
BufferedImage itemImage = itemManager.getImage(offer.getItemId(), offer.getTotalQuantity(), shouldStack);
|
||||||
SwingUtilities.invokeLater(() -> panel.updateOffer(offerItem, itemImage, offerEvent.getOffer(), offerEvent.getSlot()));
|
SwingUtilities.invokeLater(() -> panel.getOffersPanel().updateOffer(offerItem, itemImage, offerEvent.getOffer(), offerEvent.getSlot()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||||
|
{
|
||||||
|
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN)
|
||||||
|
{
|
||||||
|
panel.getOffersPanel().resetOffers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Seth <https://github.com/sethtroll>
|
* Copyright (c) 2018, Seth <https://github.com/sethtroll>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,19 +27,19 @@ package net.runelite.client.plugins.grandexchange;
|
|||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.CardLayout;
|
||||||
import java.awt.GridLayout;
|
import java.awt.Dimension;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.Icon;
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -46,26 +47,69 @@ import net.runelite.api.Client;
|
|||||||
import net.runelite.api.ItemComposition;
|
import net.runelite.api.ItemComposition;
|
||||||
import net.runelite.client.game.AsyncBufferedImage;
|
import net.runelite.client.game.AsyncBufferedImage;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
import net.runelite.client.plugins.hiscore.IconTextField;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.components.IconTextField;
|
||||||
|
import net.runelite.client.ui.components.PluginErrorPanel;
|
||||||
import net.runelite.http.api.item.Item;
|
import net.runelite.http.api.item.Item;
|
||||||
import net.runelite.http.api.item.ItemPrice;
|
import net.runelite.http.api.item.ItemPrice;
|
||||||
import net.runelite.http.api.item.SearchResult;
|
import net.runelite.http.api.item.SearchResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This panel holds the search section of the Grand Exchange Plugin.
|
||||||
|
* It should display a search bar and either item results or a error panel.
|
||||||
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class GrandExchangeSearchPanel extends JPanel
|
class GrandExchangeSearchPanel extends JPanel
|
||||||
{
|
{
|
||||||
private static final List<GrandExchangeItems> ITEMS_LIST = new ArrayList<>();
|
private static final String ERROR_PANEL = "ERROR_PANEL";
|
||||||
|
private static final String RESULTS_PANEL = "RESULTS_PANEL";
|
||||||
|
|
||||||
|
private static final ImageIcon SEARCH_ICON;
|
||||||
|
private static final ImageIcon LOADING_ICON;
|
||||||
|
private static final ImageIcon ERROR_ICON;
|
||||||
|
|
||||||
|
private final GridBagConstraints constraints = new GridBagConstraints();
|
||||||
|
private final CardLayout cardLayout = new CardLayout();
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final ItemManager itemManager;
|
private final ItemManager itemManager;
|
||||||
private final ScheduledExecutorService executor;
|
private final ScheduledExecutorService executor;
|
||||||
|
|
||||||
private Icon search;
|
private final IconTextField searchBox = new IconTextField();
|
||||||
|
|
||||||
private IconTextField searchBox = new IconTextField();
|
/* The main container, this holds the search bar and the center panel */
|
||||||
private JPanel container = new JPanel();
|
private final JPanel container = new JPanel();
|
||||||
private JPanel searchItemsPanel = new JPanel();
|
|
||||||
private JLabel searchingLabel = new JLabel();
|
/* The results container, this will hold all the individual ge item panels */
|
||||||
|
private final JPanel searchItemsPanel = new JPanel();
|
||||||
|
|
||||||
|
/* The center panel, this holds either the error panel or the results container */
|
||||||
|
private final JPanel centerPanel = new JPanel(cardLayout);
|
||||||
|
|
||||||
|
/* The error panel, this displays an error message */
|
||||||
|
private final PluginErrorPanel errorPanel = new PluginErrorPanel();
|
||||||
|
|
||||||
|
/* The results wrapper, this scrolling panel wraps the results container */
|
||||||
|
private JScrollPane resultsWrapper;
|
||||||
|
|
||||||
|
private List<GrandExchangeItems> itemsList = new ArrayList<>();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (ImageIO.class)
|
||||||
|
{
|
||||||
|
SEARCH_ICON = new ImageIcon(ImageIO.read(IconTextField.class.getResourceAsStream("search_darker.png")));
|
||||||
|
LOADING_ICON = new ImageIcon(IconTextField.class.getResource("loading_spinner.gif"));
|
||||||
|
ERROR_ICON = new ImageIcon(ImageIO.read(IconTextField.class.getResourceAsStream("error.png")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GrandExchangeSearchPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
GrandExchangeSearchPanel(Client client, ItemManager itemManager, ScheduledExecutorService executor)
|
||||||
{
|
{
|
||||||
@@ -78,38 +122,54 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
container.setLayout(new BorderLayout());
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
// Search Box
|
container.setLayout(new BorderLayout(5, 5));
|
||||||
try
|
container.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
{
|
container.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
BufferedImage icon;
|
|
||||||
synchronized (ImageIO.class)
|
|
||||||
{
|
|
||||||
icon = ImageIO.read(GrandExchangePlugin.class.getResourceAsStream("search.png"));
|
|
||||||
}
|
|
||||||
search = new ImageIcon(icon);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
log.warn("Failed to read icon", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
searchBox.setIcon(search);
|
searchBox.setPreferredSize(new Dimension(100, 30));
|
||||||
|
searchBox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||||
|
searchBox.setHoverBackgroundColor(ColorScheme.MEDIUM_GRAY_COLOR.brighter());
|
||||||
|
searchBox.setIcon(SEARCH_ICON);
|
||||||
searchBox.addActionListener(e -> executor.execute(() -> priceLookup(false)));
|
searchBox.addActionListener(e -> executor.execute(() -> priceLookup(false)));
|
||||||
|
|
||||||
|
searchItemsPanel.setLayout(new GridBagLayout());
|
||||||
|
searchItemsPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
|
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
constraints.weightx = 1;
|
||||||
|
constraints.gridx = 0;
|
||||||
|
constraints.gridy = 0;
|
||||||
|
|
||||||
|
/* This panel wraps the results panel and guarantees the scrolling behaviour */
|
||||||
|
JPanel wrapper = new JPanel(new BorderLayout());
|
||||||
|
wrapper.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
wrapper.add(searchItemsPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
resultsWrapper = new JScrollPane(wrapper);
|
||||||
|
resultsWrapper.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
resultsWrapper.getVerticalScrollBar().setPreferredSize(new Dimension(12, 0));
|
||||||
|
resultsWrapper.getVerticalScrollBar().setBorder(new EmptyBorder(0, 5, 0, 0));
|
||||||
|
resultsWrapper.setVisible(false);
|
||||||
|
|
||||||
|
/* This panel wraps the error panel and limits its height */
|
||||||
|
JPanel errorWrapper = new JPanel(new BorderLayout());
|
||||||
|
errorWrapper.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
errorWrapper.add(errorPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
errorPanel.setContent("Grand Exchange Search",
|
||||||
|
"Here you can search for an item by its name to find price information.");
|
||||||
|
|
||||||
|
centerPanel.add(resultsWrapper, RESULTS_PANEL);
|
||||||
|
centerPanel.add(errorWrapper, ERROR_PANEL);
|
||||||
|
|
||||||
|
cardLayout.show(centerPanel, ERROR_PANEL);
|
||||||
|
|
||||||
container.add(searchBox, BorderLayout.NORTH);
|
container.add(searchBox, BorderLayout.NORTH);
|
||||||
|
container.add(centerPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
// Searching label
|
add(container, BorderLayout.CENTER);
|
||||||
searchingLabel.setHorizontalAlignment(JLabel.CENTER);
|
|
||||||
searchingLabel.setForeground(Color.YELLOW);
|
|
||||||
|
|
||||||
// Items Panel
|
|
||||||
searchItemsPanel.setLayout(new GridLayout(0, 1, 0, 3));
|
|
||||||
searchItemsPanel.setBorder(new EmptyBorder(3, 0, 0, 0));
|
|
||||||
|
|
||||||
container.add(searchItemsPanel, BorderLayout.SOUTH);
|
|
||||||
add(container, BorderLayout.NORTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void priceLookup(String item)
|
void priceLookup(String item)
|
||||||
@@ -130,7 +190,9 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
|
|
||||||
// Input is not empty, add searching label
|
// Input is not empty, add searching label
|
||||||
searchItemsPanel.removeAll();
|
searchItemsPanel.removeAll();
|
||||||
showSearchString("Searching...");
|
searchBox.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||||
|
searchBox.setEditable(false);
|
||||||
|
searchBox.setIcon(LOADING_ICON);
|
||||||
|
|
||||||
SearchResult result;
|
SearchResult result;
|
||||||
|
|
||||||
@@ -141,13 +203,19 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
catch (ExecutionException ex)
|
catch (ExecutionException ex)
|
||||||
{
|
{
|
||||||
log.warn("Unable to search for item {}", lookup, ex);
|
log.warn("Unable to search for item {}", lookup, ex);
|
||||||
showSearchString("Error performing search");
|
searchBox.setIcon(ERROR_ICON);
|
||||||
|
searchBox.setEditable(true);
|
||||||
|
errorPanel.setContent("Error fetching results", "An error occured why trying to fetch item data, please try again later.");
|
||||||
|
cardLayout.show(centerPanel, ERROR_PANEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itemsList.clear();
|
||||||
|
|
||||||
if (result != null && !result.getItems().isEmpty())
|
if (result != null && !result.getItems().isEmpty())
|
||||||
{
|
{
|
||||||
|
cardLayout.show(centerPanel, RESULTS_PANEL);
|
||||||
|
|
||||||
for (Item item : result.getItems())
|
for (Item item : result.getItems())
|
||||||
{
|
{
|
||||||
int itemId = item.getId();
|
int itemId = item.getId();
|
||||||
@@ -170,7 +238,7 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
|
|
||||||
AsyncBufferedImage itemImage = itemManager.getImage(itemId);
|
AsyncBufferedImage itemImage = itemManager.getImage(itemId);
|
||||||
|
|
||||||
ITEMS_LIST.add(new GrandExchangeItems(itemImage, item.getName(), itemId, itemPrice != null ? itemPrice.getPrice() : 0, itemComp.getPrice() * 0.6));
|
itemsList.add(new GrandExchangeItems(itemImage, item.getName(), itemId, itemPrice != null ? itemPrice.getPrice() : 0, itemComp.getPrice() * 0.6));
|
||||||
|
|
||||||
// If using hotkey to lookup item, stop after finding match.
|
// If using hotkey to lookup item, stop after finding match.
|
||||||
if (exactMatch && item.getName().equalsIgnoreCase(lookup))
|
if (exactMatch && item.getName().equalsIgnoreCase(lookup))
|
||||||
@@ -179,44 +247,51 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
searchBox.setIcon(ERROR_ICON);
|
||||||
|
errorPanel.setContent("No results found.", "No items were found with that name, please try again.");
|
||||||
|
cardLayout.show(centerPanel, ERROR_PANEL);
|
||||||
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() ->
|
SwingUtilities.invokeLater(() ->
|
||||||
{
|
{
|
||||||
if (ITEMS_LIST.isEmpty())
|
int index = 0;
|
||||||
|
for (GrandExchangeItems item : itemsList)
|
||||||
{
|
{
|
||||||
showSearchString("No results found.");
|
GrandExchangeItemPanel panel = new GrandExchangeItemPanel(item.getIcon(), item.getName(),
|
||||||
}
|
item.getItemId(), item.getGePrice(), item.getHaPrice());
|
||||||
else
|
|
||||||
{
|
/*
|
||||||
for (GrandExchangeItems item : ITEMS_LIST)
|
Add the first item directly, wrap the rest with margin. This margin hack is because
|
||||||
|
gridbaglayout does not support inter-element margins.
|
||||||
|
*/
|
||||||
|
if (index++ > 0)
|
||||||
{
|
{
|
||||||
GrandExchangeItemPanel panel = new GrandExchangeItemPanel(item.getIcon(), item.getName(),
|
JPanel marginWrapper = new JPanel(new BorderLayout());
|
||||||
item.getItemId(), item.getGePrice(), item.getHaPrice());
|
marginWrapper.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
marginWrapper.setBorder(new EmptyBorder(5, 0, 0, 0));
|
||||||
searchItemsPanel.add(panel);
|
marginWrapper.add(panel, BorderLayout.NORTH);
|
||||||
|
searchItemsPanel.add(marginWrapper, constraints);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
searchItemsPanel.add(panel, constraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints.gridy++;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove searching label after search is complete
|
// remove focus from the search bar
|
||||||
showSearchString(null);
|
searchItemsPanel.requestFocusInWindow();
|
||||||
ITEMS_LIST.clear();
|
searchBox.setEditable(true);
|
||||||
|
|
||||||
|
// Remove searching label after search is complete
|
||||||
|
if (!itemsList.isEmpty())
|
||||||
|
{
|
||||||
|
searchBox.setIcon(SEARCH_ICON);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSearchString(String str)
|
}
|
||||||
{
|
|
||||||
if (str != null)
|
|
||||||
{
|
|
||||||
remove(searchingLabel);
|
|
||||||
searchingLabel.setText(str);
|
|
||||||
add(searchingLabel, BorderLayout.CENTER);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
remove(searchingLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
revalidate();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -25,10 +26,8 @@
|
|||||||
package net.runelite.client.plugins.hiscore;
|
package net.runelite.client.plugins.hiscore;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import java.awt.BorderLayout;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
@@ -39,31 +38,24 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.swing.BorderFactory;
|
|
||||||
import javax.swing.ButtonGroup;
|
|
||||||
import javax.swing.Icon;
|
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.border.MatteBorder;
|
||||||
import javax.swing.JToggleButton;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.Border;
|
|
||||||
import javax.swing.event.MouseInputAdapter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Experience;
|
import net.runelite.api.Experience;
|
||||||
import net.runelite.api.Player;
|
import net.runelite.api.Player;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.ui.components.IconTextField;
|
||||||
import net.runelite.client.util.StackFormatter;
|
import net.runelite.client.util.StackFormatter;
|
||||||
import net.runelite.http.api.hiscore.HiscoreClient;
|
import net.runelite.http.api.hiscore.HiscoreClient;
|
||||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||||
@@ -102,13 +94,17 @@ import net.runelite.http.api.hiscore.Skill;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class HiscorePanel extends PluginPanel
|
public class HiscorePanel extends PluginPanel
|
||||||
{
|
{
|
||||||
private static final String SKILL_NAME = "SKILL_NAME";
|
/* The maximum allowed username length in runescape accounts */
|
||||||
private static final String SKILL = "SKILL";
|
private static final int MAX_USERNAME_LENGTH = 12;
|
||||||
|
|
||||||
|
private static final ImageIcon SEARCH_ICON;
|
||||||
|
private static final ImageIcon LOADING_ICON;
|
||||||
|
private static final ImageIcon ERROR_ICON;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Real skills, ordered in the way they should be displayed in the panel.
|
* Real skills, ordered in the way they should be displayed in the panel.
|
||||||
*/
|
*/
|
||||||
private static final Set<HiscoreSkill> SKILLS = new LinkedHashSet<>(Arrays.asList(
|
private static final List<HiscoreSkill> SKILLS = ImmutableList.of(
|
||||||
ATTACK, HITPOINTS, MINING,
|
ATTACK, HITPOINTS, MINING,
|
||||||
STRENGTH, AGILITY, SMITHING,
|
STRENGTH, AGILITY, SMITHING,
|
||||||
DEFENCE, HERBLORE, FISHING,
|
DEFENCE, HERBLORE, FISHING,
|
||||||
@@ -117,7 +113,7 @@ public class HiscorePanel extends PluginPanel
|
|||||||
MAGIC, FLETCHING, WOODCUTTING,
|
MAGIC, FLETCHING, WOODCUTTING,
|
||||||
RUNECRAFT, SLAYER, FARMING,
|
RUNECRAFT, SLAYER, FARMING,
|
||||||
CONSTRUCTION, HUNTER
|
CONSTRUCTION, HUNTER
|
||||||
));
|
);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ScheduledExecutorService executor;
|
ScheduledExecutorService executor;
|
||||||
@@ -132,24 +128,45 @@ public class HiscorePanel extends PluginPanel
|
|||||||
private final List<JLabel> skillLabels = new ArrayList<>();
|
private final List<JLabel> skillLabels = new ArrayList<>();
|
||||||
|
|
||||||
private final JPanel statsPanel = new JPanel();
|
private final JPanel statsPanel = new JPanel();
|
||||||
private final ButtonGroup endpointButtonGroup = new ButtonGroup();
|
|
||||||
private final JTextArea details = new JTextArea();
|
|
||||||
private final JProgressBar progressBar;
|
|
||||||
|
|
||||||
private List<JToggleButton> endpointButtons;
|
/* A list of all the selectable endpoints (ironman, deadman, etc) */
|
||||||
|
private final List<JPanel> endPoints = new ArrayList<>();
|
||||||
|
|
||||||
private final HiscoreClient hiscoreClient = new HiscoreClient();
|
private final HiscoreClient hiscoreClient = new HiscoreClient();
|
||||||
|
|
||||||
private HiscoreResult result;
|
private HiscoreResult result;
|
||||||
|
|
||||||
|
/* The currently selected endpoint */
|
||||||
|
private HiscoreEndpoint selectedEndPoint;
|
||||||
|
|
||||||
|
/* Used to prevent users from switching endpoint tabs while the results are loading */
|
||||||
|
private boolean loading = false;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (ImageIO.class)
|
||||||
|
{
|
||||||
|
SEARCH_ICON = new ImageIcon(ImageIO.read(IconTextField.class.getResourceAsStream("search.png")));
|
||||||
|
LOADING_ICON = new ImageIcon(IconTextField.class.getResource("loading_spinner_darker.gif"));
|
||||||
|
ERROR_ICON = new ImageIcon(ImageIO.read(IconTextField.class.getResourceAsStream("error.png")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HiscorePanel(HiscoreConfig config)
|
public HiscorePanel(HiscoreConfig config)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
// Panel "constants"
|
setBorder(new EmptyBorder(10, 10, 0, 10));
|
||||||
// This was an EtchedBorder, but the style would change when the window was maximized.
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
Border subPanelBorder = BorderFactory.createLineBorder(this.getBackground().brighter(), 2);
|
|
||||||
|
|
||||||
// Create GBL to arrange sub items
|
// Create GBL to arrange sub items
|
||||||
GridBagLayout gridBag = new GridBagLayout();
|
GridBagLayout gridBag = new GridBagLayout();
|
||||||
@@ -160,28 +177,11 @@ public class HiscorePanel extends PluginPanel
|
|||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
c.anchor = GridBagConstraints.NORTH;
|
c.anchor = GridBagConstraints.NORTH;
|
||||||
|
|
||||||
// Search box
|
|
||||||
JPanel inputPanel = new JPanel();
|
|
||||||
inputPanel.setLayout(new BorderLayout(7, 7));
|
|
||||||
inputPanel.setBorder(subPanelBorder);
|
|
||||||
|
|
||||||
Icon search;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
BufferedImage icon;
|
|
||||||
synchronized (ImageIO.class)
|
|
||||||
{
|
|
||||||
icon = ImageIO.read(HiscorePanel.class.getResourceAsStream("search.png"));
|
|
||||||
}
|
|
||||||
search = new ImageIcon(icon);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
input = new IconTextField();
|
input = new IconTextField();
|
||||||
input.setIcon(search);
|
input.setPreferredSize(new Dimension(100, 30));
|
||||||
|
input.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
input.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR);
|
||||||
|
input.setIcon(SEARCH_ICON);
|
||||||
input.addActionListener(e -> executor.execute(this::lookup));
|
input.addActionListener(e -> executor.execute(this::lookup));
|
||||||
input.addMouseListener(new MouseAdapter()
|
input.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
@@ -192,7 +192,6 @@ public class HiscorePanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client == null)
|
if (client == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -206,97 +205,20 @@ public class HiscorePanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
inputPanel.add(input, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
c.gridx = 0;
|
c.gridx = 0;
|
||||||
c.gridy = 0;
|
c.gridy = 0;
|
||||||
c.weightx = 1;
|
c.weightx = 1;
|
||||||
c.weighty = 0;
|
c.weighty = 0;
|
||||||
c.insets = new Insets(0, 0, 3, 0);
|
c.insets = new Insets(0, 0, 10, 0);
|
||||||
gridBag.setConstraints(inputPanel, c);
|
gridBag.setConstraints(input, c);
|
||||||
add(inputPanel);
|
add(input);
|
||||||
|
|
||||||
// Panel that holds skill icons
|
|
||||||
GridLayout stats = new GridLayout(8, 3);
|
|
||||||
statsPanel.setLayout(stats);
|
|
||||||
statsPanel.setBorder(subPanelBorder);
|
|
||||||
|
|
||||||
// For each skill on the ingame skill panel, create a Label and add it to the UI
|
|
||||||
for (HiscoreSkill skill : SKILLS)
|
|
||||||
{
|
|
||||||
JPanel panel = makeSkillPanel(skill.getName(), skill);
|
|
||||||
statsPanel.add(panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 1;
|
|
||||||
gridBag.setConstraints(statsPanel, c);
|
|
||||||
add(statsPanel);
|
|
||||||
|
|
||||||
JPanel totalPanel = new JPanel();
|
|
||||||
totalPanel.setBorder(subPanelBorder);
|
|
||||||
totalPanel.setLayout(new GridLayout(1, 2));
|
|
||||||
|
|
||||||
totalPanel.add(makeSkillPanel(OVERALL.getName(), OVERALL));
|
|
||||||
totalPanel.add(makeSkillPanel("Combat", null));
|
|
||||||
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 2;
|
|
||||||
gridBag.setConstraints(totalPanel, c);
|
|
||||||
add(totalPanel);
|
|
||||||
|
|
||||||
JPanel minigamePanel = new JPanel();
|
|
||||||
minigamePanel.setBorder(subPanelBorder);
|
|
||||||
// These aren't all on one row because when there's a label with four or more digits it causes the details
|
|
||||||
// panel to change its size for some reason...
|
|
||||||
minigamePanel.setLayout(new GridLayout(2, 3));
|
|
||||||
|
|
||||||
minigamePanel.add(makeSkillPanel(CLUE_SCROLL_ALL.getName(), CLUE_SCROLL_ALL));
|
|
||||||
minigamePanel.add(makeSkillPanel(LAST_MAN_STANDING.getName(), LAST_MAN_STANDING));
|
|
||||||
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_ROGUE.getName(), BOUNTY_HUNTER_ROGUE));
|
|
||||||
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_HUNTER.getName(), BOUNTY_HUNTER_HUNTER));
|
|
||||||
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 3;
|
|
||||||
gridBag.setConstraints(minigamePanel, c);
|
|
||||||
add(minigamePanel);
|
|
||||||
|
|
||||||
JPanel detailsPanel = new JPanel();
|
|
||||||
detailsPanel.setBorder(subPanelBorder);
|
|
||||||
detailsPanel.setLayout(new BorderLayout());
|
|
||||||
|
|
||||||
// Rather than using one JLabel for each line, make a JTextArea look and act like a JLabel
|
|
||||||
details.setEditable(false);
|
|
||||||
details.setCursor(null);
|
|
||||||
details.setOpaque(false);
|
|
||||||
details.setFocusable(false);
|
|
||||||
details.setWrapStyleWord(true);
|
|
||||||
details.setLineWrap(true);
|
|
||||||
details.setMargin(new Insets(2, 4, 4, 4));
|
|
||||||
details.setRows(6);
|
|
||||||
details.setText("");
|
|
||||||
|
|
||||||
detailsPanel.add(details, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
progressBar = new JProgressBar();
|
|
||||||
progressBar.setStringPainted(true);
|
|
||||||
progressBar.setValue(0);
|
|
||||||
progressBar.setMinimum(0);
|
|
||||||
progressBar.setMaximum(100);
|
|
||||||
progressBar.setBackground(Color.RED);
|
|
||||||
progressBar.setVisible(false);
|
|
||||||
|
|
||||||
detailsPanel.add(progressBar, BorderLayout.SOUTH);
|
|
||||||
|
|
||||||
c.gridx = 0;
|
|
||||||
c.gridy = 4;
|
|
||||||
gridBag.setConstraints(detailsPanel, c);
|
|
||||||
add(detailsPanel);
|
|
||||||
|
|
||||||
|
/* The container for all the endpoint selectors */
|
||||||
JPanel endpointPanel = new JPanel();
|
JPanel endpointPanel = new JPanel();
|
||||||
endpointPanel.setBorder(subPanelBorder);
|
endpointPanel.setOpaque(false);
|
||||||
|
endpointPanel.setLayout(new GridLayout(1, 5, 7, 1));
|
||||||
|
|
||||||
endpointButtons = new ArrayList<>();
|
|
||||||
for (HiscoreEndpoint endpoint : HiscoreEndpoint.values())
|
for (HiscoreEndpoint endpoint : HiscoreEndpoint.values())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -307,25 +229,32 @@ public class HiscorePanel extends PluginPanel
|
|||||||
iconImage = ImageIO.read(HiscorePanel.class.getResourceAsStream(
|
iconImage = ImageIO.read(HiscorePanel.class.getResourceAsStream(
|
||||||
endpoint.name().toLowerCase() + ".png"));
|
endpoint.name().toLowerCase() + ".png"));
|
||||||
}
|
}
|
||||||
JToggleButton button = new JToggleButton();
|
|
||||||
button.setIcon(new ImageIcon(iconImage));
|
JPanel panel = new JPanel();
|
||||||
button.setPreferredSize(new Dimension(24, 24));
|
JLabel label = new JLabel();
|
||||||
button.setBackground(Color.WHITE);
|
|
||||||
button.setFocusPainted(false);
|
label.setIcon(new ImageIcon(iconImage));
|
||||||
button.setActionCommand(endpoint.name());
|
|
||||||
button.setToolTipText(endpoint.getName() + " Hiscores");
|
panel.add(label);
|
||||||
button.addActionListener((e -> executor.execute(this::lookup)));
|
panel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
button.addMouseListener(new MouseAdapter()
|
panel.setToolTipText(endpoint.getName() + " Hiscores");
|
||||||
|
panel.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased(MouseEvent e)
|
public void mouseClicked(MouseEvent e)
|
||||||
{
|
{
|
||||||
|
if (loading)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
executor.execute(HiscorePanel.this::lookup);
|
||||||
|
selectedEndPoint = endpoint;
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
endpointButtons.add(button);
|
|
||||||
endpointButtonGroup.add(button);
|
endPoints.add(panel);
|
||||||
endpointPanel.add(button);
|
endpointPanel.add(panel);
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
@@ -333,156 +262,61 @@ public class HiscorePanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointButtons.get(0).setSelected(true);
|
/* Default endpoint is the general (normal) endpoint */
|
||||||
endpointButtons.get(0).setBackground(Color.CYAN);
|
selectedEndPoint = HiscoreEndpoint.NORMAL;
|
||||||
|
updateButtons();
|
||||||
|
|
||||||
c.gridx = 0;
|
c.gridx = 0;
|
||||||
c.gridy = 5;
|
c.gridy = 1;
|
||||||
// Last item has a nonzero weighty so it will expand to fill vertical space
|
|
||||||
c.weighty = 1;
|
|
||||||
gridBag.setConstraints(endpointPanel, c);
|
gridBag.setConstraints(endpointPanel, c);
|
||||||
add(endpointPanel);
|
add(endpointPanel);
|
||||||
}
|
|
||||||
|
|
||||||
void addInputKeyListener(KeyListener l)
|
// Panel that holds skill icons
|
||||||
{
|
GridLayout stats = new GridLayout(8, 3);
|
||||||
this.input.addKeyListener(l);
|
statsPanel.setLayout(stats);
|
||||||
}
|
statsPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
statsPanel.setBorder(new EmptyBorder(5, 0, 5, 0));
|
||||||
|
|
||||||
void removeInputKeyListener(KeyListener l)
|
// For each skill on the ingame skill panel, create a Label and add it to the UI
|
||||||
{
|
for (HiscoreSkill skill : SKILLS)
|
||||||
this.input.removeKeyListener(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void changeDetail(String skillName, HiscoreSkill skill)
|
|
||||||
{
|
|
||||||
if (result == null || result.getPlayer() == null)
|
|
||||||
{
|
{
|
||||||
return;
|
JPanel panel = makeSkillPanel(skill);
|
||||||
|
panel.setOpaque(false);
|
||||||
|
statsPanel.add(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
String text;
|
c.gridx = 0;
|
||||||
int progress = -1;
|
c.gridy = 2;
|
||||||
switch (skillName)
|
gridBag.setConstraints(statsPanel, c);
|
||||||
{
|
add(statsPanel);
|
||||||
case "Combat":
|
|
||||||
{
|
|
||||||
double combatLevel = Experience.getCombatLevelPrecise(
|
|
||||||
result.getAttack().getLevel(),
|
|
||||||
result.getStrength().getLevel(),
|
|
||||||
result.getDefence().getLevel(),
|
|
||||||
result.getHitpoints().getLevel(),
|
|
||||||
result.getMagic().getLevel(),
|
|
||||||
result.getRanged().getLevel(),
|
|
||||||
result.getPrayer().getLevel()
|
|
||||||
);
|
|
||||||
text = "Skill: Combat" + System.lineSeparator()
|
|
||||||
+ "Exact Combat Level: " + StackFormatter.formatNumber(combatLevel) + System.lineSeparator()
|
|
||||||
+ "Experience: " + StackFormatter.formatNumber(result.getAttack().getExperience()
|
|
||||||
+ result.getStrength().getExperience() + result.getDefence().getExperience()
|
|
||||||
+ result.getHitpoints().getExperience() + result.getMagic().getExperience()
|
|
||||||
+ result.getRanged().getExperience() + result.getPrayer().getExperience());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Clue Scrolls (all)":
|
|
||||||
{
|
|
||||||
String allRank = (result.getClueScrollAll().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollAll().getRank());
|
|
||||||
String easyRank = (result.getClueScrollEasy().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollEasy().getRank());
|
|
||||||
String mediumRank = (result.getClueScrollMedium().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollMedium().getRank());
|
|
||||||
String hardRank = (result.getClueScrollHard().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollHard().getRank());
|
|
||||||
String eliteRank = (result.getClueScrollElite().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollElite().getRank());
|
|
||||||
String masterRank = (result.getClueScrollMaster().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollMaster().getRank());
|
|
||||||
String all = (result.getClueScrollAll().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollAll().getLevel()));
|
|
||||||
String easy = (result.getClueScrollEasy().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollEasy().getLevel()));
|
|
||||||
String medium = (result.getClueScrollMedium().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollMedium().getLevel()));
|
|
||||||
String hard = (result.getClueScrollHard().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollHard().getLevel()));
|
|
||||||
String elite = (result.getClueScrollElite().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollElite().getLevel()));
|
|
||||||
String master = (result.getClueScrollMaster().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollMaster().getLevel()));
|
|
||||||
text = "All clues: " + all + " | Rank: " + allRank + System.lineSeparator()
|
|
||||||
+ "Easy: " + easy + " | Rank: " + easyRank + System.lineSeparator()
|
|
||||||
+ "Medium: " + medium + " | Rank: " + mediumRank + System.lineSeparator()
|
|
||||||
+ "Hard: " + hard + " | Rank: " + hardRank + System.lineSeparator()
|
|
||||||
+ "Elite: " + elite + " | Rank: " + eliteRank + System.lineSeparator()
|
|
||||||
+ "Master: " + master + " | Rank: " + masterRank;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Bounty Hunter - Rogue":
|
|
||||||
{
|
|
||||||
String rank = (result.getBountyHunterRogue().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getBountyHunterRogue().getRank());
|
|
||||||
text = "Bounty Hunter - Rogue Kills" + System.lineSeparator()
|
|
||||||
+ "Rank: " + rank;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Bounty Hunter - Hunter":
|
|
||||||
{
|
|
||||||
String rank = (result.getBountyHunterHunter().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getBountyHunterHunter().getRank());
|
|
||||||
text = "Bounty Hunter - Hunter Kills" + System.lineSeparator()
|
|
||||||
+ "Rank: " + rank;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Last Man Standing":
|
|
||||||
{
|
|
||||||
String rank = (result.getLastManStanding().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getLastManStanding().getRank());
|
|
||||||
text = "Last Man Standing" + System.lineSeparator()
|
|
||||||
+ "Rank: " + rank;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "Overall":
|
|
||||||
{
|
|
||||||
Skill requestedSkill = result.getSkill(skill);
|
|
||||||
String rank = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getRank());
|
|
||||||
String exp = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getExperience());
|
|
||||||
text = "Skill: " + skillName + System.lineSeparator()
|
|
||||||
+ "Rank: " + rank + System.lineSeparator()
|
|
||||||
+ "Experience: " + exp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Skill requestedSkill = result.getSkill(skill);
|
|
||||||
String rank = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getRank());
|
|
||||||
String exp = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getExperience());
|
|
||||||
String remainingXp;
|
|
||||||
if (requestedSkill.getRank() == -1)
|
|
||||||
{
|
|
||||||
remainingXp = "Unranked";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int currentLevel = Experience.getLevelForXp((int) requestedSkill.getExperience());
|
|
||||||
int currentXp = (int) requestedSkill.getExperience();
|
|
||||||
int xpForCurrentLevel = Experience.getXpForLevel(currentLevel);
|
|
||||||
int xpForNextLevel = currentLevel + 1 <= Experience.MAX_VIRT_LEVEL ? Experience.getXpForLevel(currentLevel + 1) : -1;
|
|
||||||
|
|
||||||
remainingXp = xpForNextLevel != -1 ? StackFormatter.formatNumber(xpForNextLevel - currentXp) : "0";
|
JPanel totalPanel = new JPanel();
|
||||||
|
totalPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
totalPanel.setLayout(new GridLayout(1, 2));
|
||||||
|
|
||||||
double xpGained = currentXp - xpForCurrentLevel;
|
totalPanel.add(makeSkillPanel(null)); //combat has no hiscore skill, refered to as null
|
||||||
double xpGoal = xpForNextLevel != -1 ? xpForNextLevel - xpForCurrentLevel : 100;
|
totalPanel.add(makeSkillPanel(OVERALL));
|
||||||
progress = (int) ((xpGained / xpGoal) * 100f);
|
|
||||||
|
|
||||||
}
|
c.gridx = 0;
|
||||||
text = "Skill: " + skillName + System.lineSeparator()
|
c.gridy = 3;
|
||||||
+ "Rank: " + rank + System.lineSeparator()
|
gridBag.setConstraints(totalPanel, c);
|
||||||
+ "Experience: " + exp + System.lineSeparator()
|
add(totalPanel);
|
||||||
+ "Remaining XP: " + remainingXp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
details.setFont(UIManager.getFont("Label.font"));
|
JPanel minigamePanel = new JPanel();
|
||||||
details.setText(text);
|
// These aren't all on one row because when there's a label with four or more digits it causes the details
|
||||||
|
// panel to change its size for some reason...
|
||||||
|
minigamePanel.setLayout(new GridLayout(2, 3));
|
||||||
|
minigamePanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
|
||||||
if (progress >= 0)
|
minigamePanel.add(makeSkillPanel(CLUE_SCROLL_ALL));
|
||||||
{
|
minigamePanel.add(makeSkillPanel(LAST_MAN_STANDING));
|
||||||
progressBar.setVisible(true);
|
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_ROGUE));
|
||||||
progressBar.setValue(progress);
|
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_HUNTER));
|
||||||
progressBar.setBackground(Color.getHSBColor((progress / 100.f) * (120.f / 360.f), 1, 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
progressBar.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 4;
|
||||||
|
gridBag.setConstraints(minigamePanel, c);
|
||||||
|
add(minigamePanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -492,16 +326,14 @@ public class HiscorePanel extends PluginPanel
|
|||||||
input.requestFocusInWindow();
|
input.requestFocusInWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private JPanel makeSkillPanel(String skillName, HiscoreSkill skill)
|
/* Builds a JPanel displaying an icon and level/number associated with it */
|
||||||
|
private JPanel makeSkillPanel(HiscoreSkill skill)
|
||||||
{
|
{
|
||||||
JLabel label = new JLabel();
|
JLabel label = new JLabel();
|
||||||
|
label.setFont(FontManager.getRunescapeSmallFont());
|
||||||
label.setText("--");
|
label.setText("--");
|
||||||
|
|
||||||
// Store the skill that the label displays so we can tell them apart
|
String skillIcon = "skill_icons_small/" + (skill == null ? "combat" : skill.getName().toLowerCase()) + ".png";
|
||||||
label.putClientProperty(SKILL_NAME, skillName);
|
|
||||||
label.putClientProperty(SKILL, skill);
|
|
||||||
|
|
||||||
String skillIcon = "skill_icons_small/" + skillName.toLowerCase() + ".png";
|
|
||||||
log.debug("Loading skill icon from {}", skillIcon);
|
log.debug("Loading skill icon from {}", skillIcon);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -518,36 +350,31 @@ public class HiscorePanel extends PluginPanel
|
|||||||
log.warn(null, ex);
|
log.warn(null, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show skill details on hover
|
boolean totalLabel = skill == HiscoreSkill.OVERALL || skill == null; //overall or combat
|
||||||
label.addMouseListener(new MouseInputAdapter()
|
label.setIconTextGap(totalLabel ? 10 : 4);
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void mouseEntered(MouseEvent e)
|
|
||||||
{
|
|
||||||
JLabel source = (JLabel) e.getSource();
|
|
||||||
String skillName = (String) source.getClientProperty(SKILL_NAME);
|
|
||||||
HiscoreSkill skill = (HiscoreSkill) label.getClientProperty(SKILL);
|
|
||||||
changeDetail(skillName, skill);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
skillLabels.add(label);
|
|
||||||
|
|
||||||
JPanel skillPanel = new JPanel();
|
JPanel skillPanel = new JPanel();
|
||||||
|
skillPanel.setOpaque(false);
|
||||||
|
skillPanel.setBorder(new EmptyBorder(2, 0, 2, 0));
|
||||||
|
skillLabels.add(label);
|
||||||
skillPanel.add(skillLabels.get(skillLabels.size() - 1));
|
skillPanel.add(skillLabels.get(skillLabels.size() - 1));
|
||||||
|
|
||||||
return skillPanel;
|
return skillPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lookup(String username)
|
public void lookup(String username)
|
||||||
{
|
{
|
||||||
input.setText(username);
|
input.setText(username);
|
||||||
|
|
||||||
|
selectedEndPoint = HiscoreEndpoint.NORMAL; //reset the endpoint to regular player
|
||||||
|
updateButtons();
|
||||||
|
|
||||||
lookup();
|
lookup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lookup()
|
private void lookup()
|
||||||
{
|
{
|
||||||
String lookup = input.getText();
|
String lookup = input.getText();
|
||||||
details.setText("Loading...");
|
|
||||||
progressBar.setVisible(false);
|
|
||||||
|
|
||||||
lookup = sanitize(lookup);
|
lookup = sanitize(lookup);
|
||||||
|
|
||||||
@@ -556,43 +383,77 @@ public class HiscorePanel extends PluginPanel
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Runescape usernames can't be longer than 12 characters long */
|
||||||
|
if (lookup.length() > MAX_USERNAME_LENGTH)
|
||||||
|
{
|
||||||
|
input.setIcon(ERROR_ICON);
|
||||||
|
loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.setEditable(false);
|
||||||
|
input.setIcon(LOADING_ICON);
|
||||||
|
loading = true;
|
||||||
|
|
||||||
for (JLabel label : skillLabels)
|
for (JLabel label : skillLabels)
|
||||||
{
|
{
|
||||||
label.setText("--");
|
label.setText("--");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if for some reason no endpoint was selected, default to normal
|
||||||
|
if (selectedEndPoint == null)
|
||||||
|
{
|
||||||
|
selectedEndPoint = HiscoreEndpoint.NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HiscoreEndpoint endpoint = HiscoreEndpoint.valueOf(endpointButtonGroup.getSelection().getActionCommand());
|
log.debug("Hiscore endpoint " + selectedEndPoint.name() + " selected");
|
||||||
log.debug("Hiscore endpoint " + endpoint.name() + " selected");
|
result = hiscoreClient.lookup(lookup, selectedEndPoint);
|
||||||
|
|
||||||
result = hiscoreClient.lookup(lookup, endpoint);
|
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
log.warn("Error fetching Hiscore data " + ex.getMessage());
|
log.warn("Error fetching Hiscore data " + ex.getMessage());
|
||||||
details.setText("Error fetching Hiscore data");
|
input.setIcon(ERROR_ICON);
|
||||||
progressBar.setVisible(false);
|
input.setEditable(true);
|
||||||
|
loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
For some reason, the fetch results would sometimes return a not null object
|
||||||
|
with all null attributes, to check for that, i'll just null check one of the attributes.
|
||||||
|
*/
|
||||||
|
if (result.getAttack() == null)
|
||||||
|
{
|
||||||
|
input.setIcon(ERROR_ICON);
|
||||||
|
input.setEditable(true);
|
||||||
|
loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//successful player search
|
||||||
|
input.setIcon(SEARCH_ICON);
|
||||||
|
input.setEditable(true);
|
||||||
|
loading = false;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
for (JLabel label : skillLabels)
|
for (JLabel label : skillLabels)
|
||||||
{
|
{
|
||||||
String skillName = (String) label.getClientProperty(SKILL_NAME);
|
HiscoreSkill skill = find(index);
|
||||||
HiscoreSkill skill = (HiscoreSkill) label.getClientProperty(SKILL);
|
|
||||||
|
|
||||||
if (skillName.equals("Combat"))
|
if (skill == null)
|
||||||
{
|
{
|
||||||
if (result.getPlayer() != null)
|
if (result.getPlayer() != null)
|
||||||
{
|
{
|
||||||
int combatLevel = Experience.getCombatLevel(
|
int combatLevel = Experience.getCombatLevel(
|
||||||
result.getAttack().getLevel(),
|
result.getAttack().getLevel(),
|
||||||
result.getStrength().getLevel(),
|
result.getStrength().getLevel(),
|
||||||
result.getDefence().getLevel(),
|
result.getDefence().getLevel(),
|
||||||
result.getHitpoints().getLevel(),
|
result.getHitpoints().getLevel(),
|
||||||
result.getMagic().getLevel(),
|
result.getMagic().getLevel(),
|
||||||
result.getRanged().getLevel(),
|
result.getRanged().getLevel(),
|
||||||
result.getPrayer().getLevel()
|
result.getPrayer().getLevel()
|
||||||
);
|
);
|
||||||
label.setText(Integer.toString(combatLevel));
|
label.setText(Integer.toString(combatLevel));
|
||||||
}
|
}
|
||||||
@@ -600,7 +461,6 @@ public class HiscorePanel extends PluginPanel
|
|||||||
else if (result.getSkill(skill) != null && result.getSkill(skill).getRank() != -1)
|
else if (result.getSkill(skill) != null && result.getSkill(skill).getRank() != -1)
|
||||||
{
|
{
|
||||||
Skill s = result.getSkill(skill);
|
Skill s = result.getSkill(skill);
|
||||||
|
|
||||||
int level;
|
int level;
|
||||||
if (config.virtualLevels() && SKILLS.contains(skill))
|
if (config.virtualLevels() && SKILLS.contains(skill))
|
||||||
{
|
{
|
||||||
@@ -613,12 +473,191 @@ public class HiscorePanel extends PluginPanel
|
|||||||
|
|
||||||
label.setText(Integer.toString(level));
|
label.setText(Integer.toString(level));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.setToolTipText(detailsHtml(skill));
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addInputKeyListener(KeyListener l)
|
||||||
|
{
|
||||||
|
this.input.addInputKeyListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeInputKeyListener(KeyListener l)
|
||||||
|
{
|
||||||
|
this.input.removeInputKeyListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns a hiscore skill based on it's display order.
|
||||||
|
*/
|
||||||
|
private HiscoreSkill find(int index)
|
||||||
|
{
|
||||||
|
if (index < SKILLS.size())
|
||||||
|
{
|
||||||
|
return SKILLS.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear details panel
|
switch (index - SKILLS.size())
|
||||||
details.setFont(UIManager.getFont("Label.font").deriveFont(Font.ITALIC));
|
{
|
||||||
details.setText("Hover over a skill for details");
|
case 0:
|
||||||
progressBar.setVisible(false);
|
return null;
|
||||||
|
case 1:
|
||||||
|
return HiscoreSkill.OVERALL;
|
||||||
|
case 2:
|
||||||
|
return HiscoreSkill.CLUE_SCROLL_ALL;
|
||||||
|
case 3:
|
||||||
|
return HiscoreSkill.LAST_MAN_STANDING;
|
||||||
|
case 4:
|
||||||
|
return HiscoreSkill.BOUNTY_HUNTER_ROGUE;
|
||||||
|
case 5:
|
||||||
|
return HiscoreSkill.BOUNTY_HUNTER_HUNTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Builds a html string to display on tooltip (when hovering a skill).
|
||||||
|
*/
|
||||||
|
private String detailsHtml(HiscoreSkill skill)
|
||||||
|
{
|
||||||
|
String openingTags = "<html><body style = 'padding: 5px;color:#989898'>";
|
||||||
|
String closingTags = "</html><body>";
|
||||||
|
|
||||||
|
String content = "";
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
if (skill == null)
|
||||||
|
{
|
||||||
|
double combatLevel = Experience.getCombatLevelPrecise(
|
||||||
|
result.getAttack().getLevel(),
|
||||||
|
result.getStrength().getLevel(),
|
||||||
|
result.getDefence().getLevel(),
|
||||||
|
result.getHitpoints().getLevel(),
|
||||||
|
result.getMagic().getLevel(),
|
||||||
|
result.getRanged().getLevel(),
|
||||||
|
result.getPrayer().getLevel()
|
||||||
|
);
|
||||||
|
|
||||||
|
double combatExperience = result.getAttack().getExperience()
|
||||||
|
+ result.getStrength().getExperience() + result.getDefence().getExperience()
|
||||||
|
+ result.getHitpoints().getExperience() + result.getMagic().getExperience()
|
||||||
|
+ result.getRanged().getExperience() + result.getPrayer().getExperience();
|
||||||
|
|
||||||
|
content += "<p><span style = 'color:white'>Skill:</span> Combat</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Exact Combat Level:</span> " + StackFormatter.formatNumber(combatLevel) + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Experience:</span> " + StackFormatter.formatNumber(combatExperience) + "</p>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (skill)
|
||||||
|
{
|
||||||
|
case CLUE_SCROLL_ALL:
|
||||||
|
{
|
||||||
|
String rank = (result.getClueScrollAll().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollAll().getRank());
|
||||||
|
String allRank = (result.getClueScrollAll().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollAll().getRank());
|
||||||
|
String easyRank = (result.getClueScrollEasy().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollEasy().getRank());
|
||||||
|
String mediumRank = (result.getClueScrollMedium().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollMedium().getRank());
|
||||||
|
String hardRank = (result.getClueScrollHard().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollHard().getRank());
|
||||||
|
String eliteRank = (result.getClueScrollElite().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollElite().getRank());
|
||||||
|
String masterRank = (result.getClueScrollMaster().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getClueScrollMaster().getRank());
|
||||||
|
String all = (result.getClueScrollAll().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollAll().getLevel()));
|
||||||
|
String easy = (result.getClueScrollEasy().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollEasy().getLevel()));
|
||||||
|
String medium = (result.getClueScrollMedium().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollMedium().getLevel()));
|
||||||
|
String hard = (result.getClueScrollHard().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollHard().getLevel()));
|
||||||
|
String elite = (result.getClueScrollElite().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollElite().getLevel()));
|
||||||
|
String master = (result.getClueScrollMaster().getLevel() == -1 ? "0" : StackFormatter.formatNumber(result.getClueScrollMaster().getLevel()));
|
||||||
|
content += "<p><span style = 'color:white'>All:</span> " + all + " <span style = 'color:white'>Rank:</span> " + allRank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Easy:</span> " + easy + " <span style = 'color:white'>Rank:</span> " + easyRank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Medium:</span> " + medium + " <span style = 'color:white'>Rank:</span> " + mediumRank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Hard:</span> " + hard + " <span style = 'color:white'>Rank:</span> " + hardRank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Elite:</span> " + elite + " <span style = 'color:white'>Rank:</span> " + eliteRank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Master:</span> " + master + " <span style = 'color:white'>Rank:</span> " + masterRank + "</p>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BOUNTY_HUNTER_ROGUE:
|
||||||
|
{
|
||||||
|
String rank = (result.getBountyHunterRogue().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getBountyHunterRogue().getRank());
|
||||||
|
content += "<p><span style = 'color:white'>Rank:</span> " + rank + "</p>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BOUNTY_HUNTER_HUNTER:
|
||||||
|
{
|
||||||
|
String rank = (result.getBountyHunterHunter().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getBountyHunterHunter().getRank());
|
||||||
|
content += "<p><span style = 'color:white'>Rank:</span> " + rank + "</p>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAST_MAN_STANDING:
|
||||||
|
{
|
||||||
|
String rank = (result.getLastManStanding().getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(result.getLastManStanding().getRank());
|
||||||
|
content += "<p><span style = 'color:white'>Rank:</span> " + rank + "</p>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OVERALL:
|
||||||
|
{
|
||||||
|
Skill requestedSkill = result.getSkill(skill);
|
||||||
|
String rank = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getRank());
|
||||||
|
String exp = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getExperience());
|
||||||
|
content += "<p><span style = 'color:white'>Skill:</span> " + skill.getName() + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Rank:</span> " + rank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Experience:</span> " + exp + "</p>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Skill requestedSkill = result.getSkill(skill);
|
||||||
|
|
||||||
|
String rank = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getRank());
|
||||||
|
String exp = (requestedSkill.getRank() == -1) ? "Unranked" : StackFormatter.formatNumber(requestedSkill.getExperience());
|
||||||
|
String remainingXp;
|
||||||
|
if (requestedSkill.getRank() == -1)
|
||||||
|
{
|
||||||
|
remainingXp = "Unranked";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int currentLevel = Experience.getLevelForXp((int) requestedSkill.getExperience());
|
||||||
|
remainingXp = (currentLevel + 1 <= Experience.MAX_VIRT_LEVEL) ? StackFormatter.formatNumber(Experience.getXpForLevel(currentLevel + 1) - requestedSkill.getExperience()) : "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
content += "<p><span style = 'color:white'>Skill:</span> " + skill.getName() + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Rank:</span> " + rank + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Experience:</span> " + exp + "</p>";
|
||||||
|
content += "<p><span style = 'color:white'>Remaining XP:</span> " + remainingXp + "</p>";
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a html progress bar to the hover information
|
||||||
|
*/
|
||||||
|
if (SKILLS.contains(skill))
|
||||||
|
{
|
||||||
|
int currentLevel = Experience.getLevelForXp((int) result.getSkill(skill).getExperience());
|
||||||
|
int currentXp = (int) result.getSkill(skill).getExperience();
|
||||||
|
int xpForCurrentLevel = Experience.getXpForLevel(currentLevel);
|
||||||
|
int xpForNextLevel = currentLevel + 1 <= Experience.MAX_VIRT_LEVEL ? Experience.getXpForLevel(currentLevel + 1) : -1;
|
||||||
|
|
||||||
|
double xpGained = currentXp - xpForCurrentLevel;
|
||||||
|
double xpGoal = xpForNextLevel != -1 ? xpForNextLevel - xpForCurrentLevel : 100;
|
||||||
|
int progress = (int) ((xpGained / xpGoal) * 100f);
|
||||||
|
|
||||||
|
// had to wrap the bar with an empty div, if i added the margin directly to the bar, it would mess up
|
||||||
|
content += "<div style = 'margin-top:3px'>"
|
||||||
|
+ "<div style = 'background: #070707; border: 1px solid #070707; height: 6px; width: 100%;'>"
|
||||||
|
+ "<div style = 'height: 6px; width: " + progress + "%; background: #dc8a00;'>"
|
||||||
|
+ "</div>"
|
||||||
|
+ "</div>"
|
||||||
|
+ "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return openingTags + content + closingTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String sanitize(String lookup)
|
private static String sanitize(String lookup)
|
||||||
@@ -626,20 +665,18 @@ public class HiscorePanel extends PluginPanel
|
|||||||
return lookup.replace('\u00A0', ' ');
|
return lookup.replace('\u00A0', ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
When an endpoint gets selected, this method will correctly display the selected one
|
||||||
|
with an orange underline.
|
||||||
|
*/
|
||||||
private void updateButtons()
|
private void updateButtons()
|
||||||
{
|
{
|
||||||
for (JToggleButton button : endpointButtons)
|
for (JPanel panel : endPoints)
|
||||||
{
|
{
|
||||||
Color color;
|
panel.setBorder(new EmptyBorder(0, 0, 1, 0));
|
||||||
if (button.isSelected())
|
|
||||||
{
|
|
||||||
color = Color.CYAN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color = Color.WHITE;
|
|
||||||
}
|
|
||||||
button.setBackground(color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int selectedIndex = selectedEndPoint.ordinal();
|
||||||
|
endPoints.get(selectedIndex).setBorder(new MatteBorder(0, 0, 1, 0, ColorScheme.BRAND_ORANGE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,12 +98,13 @@ public class HiscorePlugin extends Plugin
|
|||||||
BufferedImage icon;
|
BufferedImage icon;
|
||||||
synchronized (ImageIO.class)
|
synchronized (ImageIO.class)
|
||||||
{
|
{
|
||||||
icon = ImageIO.read(getClass().getResourceAsStream("hiscore.gif"));
|
icon = ImageIO.read(getClass().getResourceAsStream("normal.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("Hiscore")
|
.name("Hiscore")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(5)
|
||||||
.panel(hiscorePanel)
|
.panel(hiscorePanel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Abex
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -27,14 +28,22 @@ package net.runelite.client.plugins.info;
|
|||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.awt.GridLayout;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.Box;
|
||||||
import javax.swing.GroupLayout;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.LayoutStyle;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.HyperlinkEvent;
|
import javax.swing.event.HyperlinkEvent;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
@@ -42,8 +51,10 @@ import net.runelite.api.events.SessionClose;
|
|||||||
import net.runelite.api.events.SessionOpen;
|
import net.runelite.api.events.SessionOpen;
|
||||||
import net.runelite.client.RuneLiteProperties;
|
import net.runelite.client.RuneLiteProperties;
|
||||||
import net.runelite.client.account.SessionManager;
|
import net.runelite.client.account.SessionManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.util.LinkBrowser;
|
||||||
import net.runelite.client.util.RunnableExceptionLogger;
|
import net.runelite.client.util.RunnableExceptionLogger;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -52,6 +63,14 @@ public class InfoPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
private static final String RUNELITE_LOGIN = "https://runelite_login/";
|
private static final String RUNELITE_LOGIN = "https://runelite_login/";
|
||||||
|
|
||||||
|
private static final ImageIcon ARROW_RIGHT_ICON;
|
||||||
|
private static final ImageIcon GITHUB_ICON;
|
||||||
|
private static final ImageIcon DISCORD_ICON;
|
||||||
|
private static final ImageIcon PATREON_ICON;
|
||||||
|
|
||||||
|
private final JLabel loggedLabel = new JLabel();
|
||||||
|
private final JRichTextPane emailLabel = new JRichTextPane();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Nullable
|
@Nullable
|
||||||
private Client client;
|
private Client client;
|
||||||
@@ -68,33 +87,58 @@ public class InfoPanel extends PluginPanel
|
|||||||
@Inject
|
@Inject
|
||||||
private ScheduledExecutorService executor;
|
private ScheduledExecutorService executor;
|
||||||
|
|
||||||
private final GroupLayout layout = new GroupLayout(this);
|
static
|
||||||
private final JLabel usernameHeader = new JLabel();
|
{
|
||||||
private final JRichTextPane username = new JRichTextPane();
|
try
|
||||||
|
{
|
||||||
|
synchronized (ImageIO.class)
|
||||||
|
{
|
||||||
|
ARROW_RIGHT_ICON = new ImageIcon(ImageIO.read(InfoPanel.class.getResourceAsStream("arrow_right.png")));
|
||||||
|
GITHUB_ICON = new ImageIcon(ImageIO.read(InfoPanel.class.getResourceAsStream("github_icon.png")));
|
||||||
|
DISCORD_ICON = new ImageIcon(ImageIO.read(InfoPanel.class.getResourceAsStream("discord_icon.png")));
|
||||||
|
PATREON_ICON = new ImageIcon(ImageIO.read(InfoPanel.class.getResourceAsStream("patreon_icon.png")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
setLayout(layout);
|
setLayout(new BorderLayout());
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
JPanel versionPanel = new JPanel();
|
||||||
|
versionPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
versionPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
versionPanel.setLayout(new GridLayout(0, 1));
|
||||||
|
|
||||||
final Font smallFont = FontManager.getRunescapeSmallFont();
|
final Font smallFont = FontManager.getRunescapeSmallFont();
|
||||||
|
|
||||||
final JLabel runeliteVersionHeader = new JLabel("RuneLite version");
|
JLabel version = new JLabel(htmlLabel("RuneLite version: ", runeLiteProperties.getVersion()));
|
||||||
runeliteVersionHeader.setFont(smallFont);
|
version.setFont(smallFont);
|
||||||
final JLabel runeliteVersion = new JLabel(runeLiteProperties.getVersion());
|
|
||||||
|
|
||||||
final JLabel runescapeVersionHeader = new JLabel("OldSchool Engine");
|
JLabel revision = new JLabel();
|
||||||
runescapeVersionHeader.setFont(smallFont);
|
revision.setFont(smallFont);
|
||||||
|
|
||||||
String engineVer = "Unknown";
|
String engineVer = "Unknown";
|
||||||
if (client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
engineVer = String.format("Rev %s", runeLiteProperties.getRunescapeVersion());
|
engineVer = String.format("Rev %s", runeLiteProperties.getRunescapeVersion());
|
||||||
}
|
}
|
||||||
final JLabel runescapeVersion = new JLabel(engineVer);
|
|
||||||
|
|
||||||
usernameHeader.setFont(smallFont);
|
revision.setText(htmlLabel("Oldschool revision: ", engineVer));
|
||||||
username.enableAutoLinkHandler(false);
|
|
||||||
username.addHyperlinkListener(e ->
|
loggedLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||||
|
loggedLabel.setFont(smallFont);
|
||||||
|
|
||||||
|
emailLabel.setForeground(Color.WHITE);
|
||||||
|
emailLabel.setFont(smallFont);
|
||||||
|
emailLabel.enableAutoLinkHandler(false);
|
||||||
|
emailLabel.addHyperlinkListener(e ->
|
||||||
{
|
{
|
||||||
if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null)
|
if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType()) && e.getURL() != null)
|
||||||
{
|
{
|
||||||
@@ -105,51 +149,74 @@ public class InfoPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
versionPanel.add(version);
|
||||||
|
versionPanel.add(revision);
|
||||||
|
versionPanel.add(Box.createGlue());
|
||||||
|
versionPanel.add(loggedLabel);
|
||||||
|
versionPanel.add(emailLabel);
|
||||||
|
|
||||||
updateLoggedIn();
|
updateLoggedIn();
|
||||||
|
|
||||||
final JRichTextPane issueLink = new JRichTextPane("text/html",
|
JPanel actionsContainer = new JPanel();
|
||||||
"RuneLite is open source!<br>"
|
actionsContainer.setBorder(new EmptyBorder(10, 0, 0, 0));
|
||||||
+ "Found an issue? Want a feature?<br>"
|
actionsContainer.setOpaque(false);
|
||||||
+ "<a href=\"https://github.com/runelite/runelite/issues\">"
|
actionsContainer.setLayout(new GridLayout(3, 1, 0, 10));
|
||||||
+ "Open an issue on GitHub!"
|
|
||||||
+ "</a>"
|
|
||||||
);
|
|
||||||
|
|
||||||
setBorder(BorderFactory.createEmptyBorder(2, 6, 6, 6));
|
actionsContainer.add(buildLinkPanel(GITHUB_ICON, "Report an issue or", "make a suggestion", runeLiteProperties.getGithubLink()));
|
||||||
|
actionsContainer.add(buildLinkPanel(DISCORD_ICON, "Talk to us on our", "discord server", runeLiteProperties.getDiscordInvite()));
|
||||||
|
actionsContainer.add(buildLinkPanel(PATREON_ICON, "Become a patron to", "help support RuneLite", runeLiteProperties.getPatreonLink()));
|
||||||
|
|
||||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
add(versionPanel, BorderLayout.NORTH);
|
||||||
.addGroup(layout.createParallelGroup()
|
add(actionsContainer, BorderLayout.CENTER);
|
||||||
.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);
|
eventBus.register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a link panel with a given icon, text and url to redirect to.
|
||||||
|
*/
|
||||||
|
private static JPanel buildLinkPanel(ImageIcon icon, String topText, String bottomText, String url)
|
||||||
|
{
|
||||||
|
JPanel container = new JPanel();
|
||||||
|
container.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
container.setLayout(new BorderLayout());
|
||||||
|
container.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
container.addMouseListener(new MouseAdapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
LinkBrowser.browse(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JLabel iconLabel = new JLabel(icon);
|
||||||
|
container.add(iconLabel, BorderLayout.WEST);
|
||||||
|
|
||||||
|
JPanel textContainer = new JPanel();
|
||||||
|
textContainer.setOpaque(false);
|
||||||
|
textContainer.setLayout(new GridLayout(2, 1));
|
||||||
|
textContainer.setBorder(new EmptyBorder(5, 10, 5, 10));
|
||||||
|
|
||||||
|
JLabel topLine = new JLabel(topText);
|
||||||
|
topLine.setForeground(Color.WHITE);
|
||||||
|
topLine.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
JLabel bottomLine = new JLabel(bottomText);
|
||||||
|
bottomLine.setForeground(Color.WHITE);
|
||||||
|
bottomLine.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
textContainer.add(topLine);
|
||||||
|
textContainer.add(bottomLine);
|
||||||
|
|
||||||
|
container.add(textContainer, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JLabel arrowLabel = new JLabel(ARROW_RIGHT_ICON);
|
||||||
|
container.add(arrowLabel, BorderLayout.EAST);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateLoggedIn()
|
private void updateLoggedIn()
|
||||||
{
|
{
|
||||||
final String name = sessionManager.getAccountSession() != null
|
final String name = sessionManager.getAccountSession() != null
|
||||||
@@ -158,18 +225,23 @@ public class InfoPanel extends PluginPanel
|
|||||||
|
|
||||||
if (name != null)
|
if (name != null)
|
||||||
{
|
{
|
||||||
username.setContentType("text/plain");
|
emailLabel.setContentType("text/plain");
|
||||||
username.setText(name);
|
emailLabel.setText(name);
|
||||||
usernameHeader.setText("Logged in as");
|
loggedLabel.setText("Logged in as");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
username.setContentType("text/html");
|
emailLabel.setContentType("text/html");
|
||||||
username.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud.");
|
emailLabel.setText("<a href=\"" + RUNELITE_LOGIN + "\">Login</a> to sync settings to the cloud.");
|
||||||
usernameHeader.setText("Not logged in");
|
loggedLabel.setText("Not logged in");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String htmlLabel(String key, String value)
|
||||||
|
{
|
||||||
|
return "<html><body style = 'color:#a5a5a5'>" + key + "<span style = 'color:white'>" + value + "</span></body></html>";
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onSessionOpen(SessionOpen sessionOpen)
|
public void onSessionOpen(SessionOpen sessionOpen)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public class InfoPlugin extends Plugin
|
|||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("Info")
|
.name("Info")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(9)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.awt.Color;
|
|||||||
import javax.swing.GroupLayout;
|
import javax.swing.GroupLayout;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
|
|
||||||
class BookPanel extends JPanel
|
class BookPanel extends JPanel
|
||||||
@@ -36,6 +37,9 @@ class BookPanel extends JPanel
|
|||||||
|
|
||||||
BookPanel(Book b)
|
BookPanel(Book b)
|
||||||
{
|
{
|
||||||
|
setBorder(new EmptyBorder(3, 3, 3, 3));
|
||||||
|
setOpaque(false);
|
||||||
|
|
||||||
GroupLayout layout = new GroupLayout(this);
|
GroupLayout layout = new GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
|
|
||||||
@@ -74,4 +78,4 @@ class BookPanel extends JPanel
|
|||||||
{
|
{
|
||||||
location.setForeground(target ? Color.GREEN : Color.WHITE);
|
location.setForeground(target ? Color.GREEN : Color.WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Abex
|
* Copyright (c) 2018 Abex
|
||||||
|
* Copyright (c) 2018 Psikoi
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -25,35 +26,71 @@
|
|||||||
package net.runelite.client.plugins.kourendlibrary;
|
package net.runelite.client.plugins.kourendlibrary;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.GroupLayout;
|
import javax.swing.GroupLayout;
|
||||||
import javax.swing.JButton;
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.border.CompoundBorder;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.util.SwingUtil;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class KourendLibraryPanel extends PluginPanel
|
public class KourendLibraryPanel extends PluginPanel
|
||||||
{
|
{
|
||||||
|
private static final ImageIcon RESET_ICON;
|
||||||
|
private static final ImageIcon RESET_CLICK_ICON;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Library library;
|
private Library library;
|
||||||
|
|
||||||
private final HashMap<Book, BookPanel> bookPanels = new HashMap<>();
|
private final HashMap<Book, BookPanel> bookPanels = new HashMap<>();
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
synchronized (ImageIO.class)
|
||||||
|
{
|
||||||
|
BufferedImage resetIcon = ImageIO.read(KourendLibraryPanel.class.getResourceAsStream("reset.png"));
|
||||||
|
RESET_ICON = new ImageIcon(resetIcon);
|
||||||
|
RESET_CLICK_ICON = new ImageIcon(SwingUtil.grayscaleOffset(resetIcon, -100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
GroupLayout layout = new GroupLayout(this);
|
GroupLayout layout = new GroupLayout(this);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
JPanel books = new JPanel(new GridBagLayout());
|
JPanel books = new JPanel(new GridBagLayout());
|
||||||
|
books.setOpaque(false);
|
||||||
GridBagConstraints c = new GridBagConstraints();
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
c.fill = GridBagConstraints.HORIZONTAL;
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
c.weightx = 1;
|
c.weightx = 1;
|
||||||
@@ -70,21 +107,45 @@ public class KourendLibraryPanel extends PluginPanel
|
|||||||
c.gridy++;
|
c.gridy++;
|
||||||
});
|
});
|
||||||
|
|
||||||
JButton reset = new JButton("Reset");
|
JLabel reset = new JLabel(RESET_ICON);
|
||||||
reset.addActionListener(e ->
|
reset.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
library.reset();
|
@Override
|
||||||
update();
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
reset.setIcon(RESET_CLICK_ICON);
|
||||||
|
library.reset();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
reset.setIcon(RESET_ICON);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
JPanel header = new JPanel();
|
||||||
|
header.setOpaque(false);
|
||||||
|
header.setLayout(new BorderLayout());
|
||||||
|
header.setBorder(new CompoundBorder(
|
||||||
|
BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(58, 58, 58)),
|
||||||
|
BorderFactory.createEmptyBorder(0, 0, 10, 0)));
|
||||||
|
|
||||||
|
JLabel pluginName = new JLabel("Kourend Library Plugin");
|
||||||
|
pluginName.setForeground(Color.WHITE);
|
||||||
|
|
||||||
|
header.add(reset, BorderLayout.EAST);
|
||||||
|
header.add(pluginName, BorderLayout.CENTER);
|
||||||
|
|
||||||
layout.setHorizontalGroup(layout.createParallelGroup()
|
layout.setHorizontalGroup(layout.createParallelGroup()
|
||||||
.addComponent(books)
|
.addComponent(books)
|
||||||
.addComponent(reset)
|
.addComponent(header)
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(layout.createSequentialGroup()
|
layout.setVerticalGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(header)
|
||||||
|
.addGap(10)
|
||||||
.addComponent(books)
|
.addComponent(books)
|
||||||
.addGap(4)
|
|
||||||
.addComponent(reset)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
update();
|
update();
|
||||||
@@ -134,4 +195,4 @@ public class KourendLibraryPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +94,7 @@ public class KourendLibraryPlugin extends Plugin
|
|||||||
|
|
||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("Kourend Library")
|
.name("Kourend Library")
|
||||||
|
.priority(6)
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Charlie Waters
|
* Copyright (c) 2018 Charlie Waters
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,13 +25,17 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.notes;
|
package net.runelite.client.plugins.notes;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
@@ -50,14 +55,24 @@ public class NotesPanel extends PluginPanel
|
|||||||
getParent().add(this, BorderLayout.CENTER);
|
getParent().add(this, BorderLayout.CENTER);
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
setBorder(BorderFactory.createEmptyBorder(2, 6, 6, 6));
|
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
final JLabel notesHeader = new JLabel("Notes");
|
final JLabel notesHeader = new JLabel("Notes");
|
||||||
|
notesHeader.setForeground(Color.WHITE);
|
||||||
|
notesHeader.setBorder(new EmptyBorder(1, 0, 10, 0));
|
||||||
|
|
||||||
add(notesHeader, BorderLayout.NORTH);
|
add(notesHeader, BorderLayout.NORTH);
|
||||||
|
|
||||||
notesEditor.setLineWrap(true);
|
notesEditor.setLineWrap(true);
|
||||||
notesEditor.setWrapStyleWord(true);
|
notesEditor.setWrapStyleWord(true);
|
||||||
|
|
||||||
|
JPanel notesContainer = new JPanel();
|
||||||
|
notesContainer.setLayout(new BorderLayout());
|
||||||
|
notesContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
|
||||||
|
notesEditor.setOpaque(false);
|
||||||
|
|
||||||
// load note text
|
// load note text
|
||||||
String data = config.notesData();
|
String data = config.notesData();
|
||||||
notesEditor.setText(data);
|
notesEditor.setText(data);
|
||||||
@@ -90,7 +105,10 @@ public class NotesPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(notesEditor, BorderLayout.CENTER);
|
notesContainer.add(notesEditor, BorderLayout.CENTER);
|
||||||
|
notesContainer.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
add(notesContainer, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNotes(String data)
|
void setNotes(String data)
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public class NotesPlugin extends Plugin
|
|||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("Notes")
|
.name("Notes")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(7)
|
||||||
.panel(panel)
|
.panel(panel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import javax.swing.JButton;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.client.game.SkillIconManager;
|
import net.runelite.client.game.SkillIconManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
|
||||||
class SkillCalculatorPanel extends PluginPanel
|
class SkillCalculatorPanel extends PluginPanel
|
||||||
@@ -64,10 +65,13 @@ class SkillCalculatorPanel extends PluginPanel
|
|||||||
uiButtonGridConstraints.insets = new Insets(2, 2, 2, 2);
|
uiButtonGridConstraints.insets = new Insets(2, 2, 2, 2);
|
||||||
|
|
||||||
uiButtonGrid.setLayout(uiButtonGridLayout);
|
uiButtonGrid.setLayout(uiButtonGridLayout);
|
||||||
|
uiButtonGrid.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
uiButtonGrid.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
|
uiButtonGrid.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
|
||||||
addCalculatorButtons();
|
addCalculatorButtons();
|
||||||
|
|
||||||
final UICalculatorInputArea uiInput = new UICalculatorInputArea();
|
final UICalculatorInputArea uiInput = new UICalculatorInputArea();
|
||||||
|
uiInput.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
uiCalculator = new SkillCalculator(client, uiInput);
|
uiCalculator = new SkillCalculator(client, uiInput);
|
||||||
|
|
||||||
add(uiButtonGrid);
|
add(uiButtonGrid);
|
||||||
|
|||||||
@@ -75,7 +75,12 @@ public class SkillCalculatorPlugin extends Plugin
|
|||||||
SkillCalculator.itemManager = itemManager;
|
SkillCalculator.itemManager = itemManager;
|
||||||
|
|
||||||
uiPanel = new SkillCalculatorPanel(skillIconManager, client);
|
uiPanel = new SkillCalculatorPanel(skillIconManager, client);
|
||||||
uiNavigationButton = NavigationButton.builder().name("Skill Calculator").icon(icon).panel(uiPanel).build();
|
uiNavigationButton = NavigationButton.builder()
|
||||||
|
.name("Skill Calculator")
|
||||||
|
.icon(icon)
|
||||||
|
.priority(6)
|
||||||
|
.panel(uiPanel)
|
||||||
|
.build();
|
||||||
pluginToolbar.addNavigation(uiNavigationButton);
|
pluginToolbar.addNavigation(uiNavigationButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry;
|
import net.runelite.client.plugins.skillcalculator.beans.SkillDataEntry;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.JShadowedLabel;
|
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
|
||||||
|
|
||||||
class UIActionSlot extends JPanel
|
class UIActionSlot extends JPanel
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import javax.swing.BorderFactory;
|
|||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import net.runelite.client.ui.FontManager;
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.JShadowedLabel;
|
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
|
||||||
|
|
||||||
class UICombinedActionSlot extends JPanel
|
class UICombinedActionSlot extends JPanel
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.xptracker;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public enum SkillColor
|
||||||
|
{
|
||||||
|
ATTACK(105, 32, 7),
|
||||||
|
DEFENCE(98, 119, 190),
|
||||||
|
STRENGTH(4, 149, 90),
|
||||||
|
HITPOINTS(131, 126, 126),
|
||||||
|
RANGED(109, 144, 23),
|
||||||
|
PRAYER(159, 147, 35),
|
||||||
|
MAGIC(50, 80, 193),
|
||||||
|
COOKING(112, 35, 134),
|
||||||
|
WOODCUTTING(52, 140, 37),
|
||||||
|
FLETCHING(3, 141, 125),
|
||||||
|
FISHING(106, 132, 164),
|
||||||
|
FIREMAKING(189, 120, 25),
|
||||||
|
CRAFTING(151, 110, 77),
|
||||||
|
SMITHING(108, 107, 82),
|
||||||
|
MINING(93, 143, 167),
|
||||||
|
HERBLORE(7, 133, 9),
|
||||||
|
AGILITY(58, 60, 137),
|
||||||
|
THIEVING(108, 52, 87),
|
||||||
|
SLAYER(100, 100, 100),
|
||||||
|
FARMING(101, 152, 63),
|
||||||
|
RUNECRAFT(170, 141, 26),
|
||||||
|
HUNTER(92, 89, 65),
|
||||||
|
CONSTRUCTION(130, 116, 95);
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final Color color;
|
||||||
|
|
||||||
|
SkillColor(int red, int green, int blue)
|
||||||
|
{
|
||||||
|
this.color = new Color(red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -26,54 +27,54 @@ package net.runelite.client.plugins.xptracker;
|
|||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.GridLayout;
|
import java.awt.GridLayout;
|
||||||
import java.awt.Rectangle;
|
|
||||||
import java.awt.RenderingHints;
|
|
||||||
import java.awt.event.MouseAdapter;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.awt.event.MouseListener;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.awt.image.LookupOp;
|
|
||||||
import java.awt.image.LookupTable;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JLayeredPane;
|
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JProgressBar;
|
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.border.CompoundBorder;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.border.LineBorder;
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Skill;
|
import net.runelite.api.Skill;
|
||||||
import net.runelite.client.game.SkillIconManager;
|
import net.runelite.client.game.SkillIconManager;
|
||||||
import net.runelite.client.ui.JShadowedLabel;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
|
import net.runelite.client.ui.components.ProgressBar;
|
||||||
import net.runelite.client.util.LinkBrowser;
|
import net.runelite.client.util.LinkBrowser;
|
||||||
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
import net.runelite.client.util.StackFormatter;
|
||||||
|
import net.runelite.client.util.SwingUtil;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class XpInfoBox extends JPanel
|
class XpInfoBox extends JPanel
|
||||||
{
|
{
|
||||||
private static final Rectangle ICON_BOUNDS = new Rectangle(0, 0, 26, 26);
|
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final JPanel panel;
|
private final JPanel panel;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
private final Skill skill;
|
private final Skill skill;
|
||||||
|
|
||||||
|
/* The tracker's wrapping container */
|
||||||
private final JPanel container = new JPanel();
|
private final JPanel container = new JPanel();
|
||||||
|
|
||||||
|
/* Contains the skill icon and the stats panel */
|
||||||
|
private final JPanel headerPanel = new JPanel();
|
||||||
|
|
||||||
|
/* Contains all the skill information (exp gained, per hour, etc) */
|
||||||
private final JPanel statsPanel = new JPanel();
|
private final JPanel statsPanel = new JPanel();
|
||||||
private final JProgressBar progressBar = new JProgressBar();
|
|
||||||
private final JLabel xpHr = new JLabel();
|
private final ProgressBar progressBar = new ProgressBar();
|
||||||
private final JLabel xpGained = new JLabel();
|
|
||||||
private final JLabel xpLeft = new JLabel();
|
private final JLabel expGained = new JLabel();
|
||||||
|
private final JLabel expHour = new JLabel();
|
||||||
|
private final JLabel expLeft = new JLabel();
|
||||||
private final JLabel actionsLeft = new JLabel();
|
private final JLabel actionsLeft = new JLabel();
|
||||||
private final JLabel levelLabel = new JShadowedLabel();
|
|
||||||
|
|
||||||
XpInfoBox(XpTrackerPlugin xpTrackerPlugin, Client client, JPanel panel, Skill skill, SkillIconManager iconManager) throws IOException
|
XpInfoBox(XpTrackerPlugin xpTrackerPlugin, Client client, JPanel panel, Skill skill, SkillIconManager iconManager) throws IOException
|
||||||
{
|
{
|
||||||
@@ -82,121 +83,81 @@ class XpInfoBox extends JPanel
|
|||||||
this.skill = skill;
|
this.skill = skill;
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
setBorder(new CompoundBorder
|
setBorder(new EmptyBorder(10, 0, 0, 0));
|
||||||
(
|
setOpaque(false);
|
||||||
new EmptyBorder(2, 0, 2, 0),
|
|
||||||
new LineBorder(getBackground().brighter(), 1)
|
|
||||||
));
|
|
||||||
|
|
||||||
// Expand stats panel on click
|
|
||||||
Color backgroundColor = getBackground();
|
|
||||||
|
|
||||||
MouseListener panelMouseListener = new MouseAdapter()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void mouseEntered(MouseEvent e)
|
|
||||||
{
|
|
||||||
container.setBackground(backgroundColor.darker().darker());
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void mouseExited(MouseEvent e)
|
|
||||||
{
|
|
||||||
container.setBackground(backgroundColor);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void mouseReleased(MouseEvent e)
|
|
||||||
{
|
|
||||||
if (SwingUtilities.isLeftMouseButton(e))
|
|
||||||
{
|
|
||||||
showStatsPanel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
container.setLayout(new BorderLayout());
|
container.setLayout(new BorderLayout());
|
||||||
container.setBorder(new EmptyBorder(5, 5, 5, 5));
|
container.setOpaque(true);
|
||||||
container.addMouseListener(panelMouseListener);
|
container.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
|
|
||||||
// Create open xp tracker menu
|
// Create open xp tracker menu
|
||||||
final JMenuItem openXpTracker = new JMenuItem("Open XP tracker");
|
final JMenuItem openXpTracker = new JMenuItem("Open online tracker");
|
||||||
openXpTracker.addActionListener(e -> LinkBrowser.browse(XpPanel.buildXpTrackerUrl(client.getLocalPlayer(), skill)));
|
openXpTracker.addActionListener(e -> LinkBrowser.browse(XpPanel.buildXpTrackerUrl(client.getLocalPlayer(), skill)));
|
||||||
|
|
||||||
|
// Create reset menu
|
||||||
|
final JMenuItem reset = new JMenuItem("Reset");
|
||||||
|
reset.addActionListener(e -> reset());
|
||||||
|
|
||||||
// Create popup menu
|
// Create popup menu
|
||||||
final JPopupMenu popupMenu = new JPopupMenu();
|
final JPopupMenu popupMenu = new JPopupMenu();
|
||||||
|
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
popupMenu.add(openXpTracker);
|
popupMenu.add(openXpTracker);
|
||||||
|
popupMenu.add(reset);
|
||||||
container.setComponentPopupMenu(popupMenu);
|
container.setComponentPopupMenu(popupMenu);
|
||||||
|
|
||||||
// Create icon panel
|
JLabel skillIcon = new JLabel(new ImageIcon(iconManager.getSkillImage(skill)));
|
||||||
final JPanel iconBarPanel = new JPanel();
|
skillIcon.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
iconBarPanel.setLayout(new BorderLayout(5, 0));
|
skillIcon.setVerticalAlignment(SwingConstants.CENTER);
|
||||||
iconBarPanel.setOpaque(false);
|
skillIcon.setPreferredSize(new Dimension(35, 35));
|
||||||
|
|
||||||
// Create skill/reset icon
|
headerPanel.setOpaque(false);
|
||||||
final BufferedImage skillImage = iconManager.getSkillImage(skill);
|
headerPanel.setLayout(new BorderLayout());
|
||||||
final JButton skillIcon = new JButton();
|
|
||||||
|
|
||||||
skillIcon.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE);
|
statsPanel.setLayout(new BorderLayout());
|
||||||
skillIcon.putClientProperty(SubstanceSynapse.BUTTON_NEVER_PAINT_BACKGROUND, Boolean.TRUE);
|
statsPanel.setBorder(new EmptyBorder(9, 5, 9, 10));
|
||||||
skillIcon.setIcon(new ImageIcon(skillImage));
|
|
||||||
skillIcon.setRolloverIcon(new ImageIcon(createHoverImage(skillImage)));
|
|
||||||
|
|
||||||
skillIcon.setToolTipText("Reset " + skill.getName() + " tracker");
|
|
||||||
skillIcon.addActionListener(e -> xpTrackerPlugin.resetSkillState(skill));
|
|
||||||
skillIcon.setBounds(ICON_BOUNDS);
|
|
||||||
skillIcon.setOpaque(false);
|
|
||||||
skillIcon.setFocusPainted(false);
|
|
||||||
|
|
||||||
// Create level label
|
|
||||||
levelLabel.setHorizontalAlignment(JLabel.CENTER);
|
|
||||||
levelLabel.setForeground(Color.YELLOW);
|
|
||||||
levelLabel.setBounds(ICON_BOUNDS);
|
|
||||||
levelLabel.setOpaque(false);
|
|
||||||
|
|
||||||
// Create pane for grouping skill icon and level label
|
|
||||||
final JLayeredPane layeredPane = new JLayeredPane();
|
|
||||||
layeredPane.add(skillIcon, new Integer(1));
|
|
||||||
layeredPane.add(levelLabel, new Integer(2));
|
|
||||||
layeredPane.setPreferredSize(ICON_BOUNDS.getSize());
|
|
||||||
iconBarPanel.add(layeredPane, BorderLayout.LINE_START);
|
|
||||||
|
|
||||||
// Create progress bar
|
|
||||||
progressBar.setStringPainted(true);
|
|
||||||
progressBar.setValue(0);
|
|
||||||
progressBar.setMinimum(0);
|
|
||||||
progressBar.setMaximum(100);
|
|
||||||
progressBar.setBackground(Color.RED);
|
|
||||||
progressBar.addMouseListener(panelMouseListener);
|
|
||||||
iconBarPanel.add(progressBar, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
container.add(iconBarPanel, BorderLayout.NORTH);
|
|
||||||
|
|
||||||
// Stats panel
|
|
||||||
statsPanel.setLayout(new GridLayout(2, 2));
|
|
||||||
statsPanel.setBorder(new EmptyBorder(3, 0, 0, 0));
|
|
||||||
statsPanel.setOpaque(false);
|
statsPanel.setOpaque(false);
|
||||||
|
|
||||||
statsPanel.add(xpGained);
|
JPanel leftPanel = new JPanel();
|
||||||
xpHr.setHorizontalAlignment(SwingConstants.RIGHT);
|
leftPanel.setOpaque(false);
|
||||||
statsPanel.add(xpHr);
|
leftPanel.setLayout(new GridLayout(2, 1));
|
||||||
statsPanel.add(xpLeft);
|
|
||||||
actionsLeft.setHorizontalAlignment(SwingConstants.RIGHT);
|
|
||||||
statsPanel.add(actionsLeft);
|
|
||||||
|
|
||||||
add(container, BorderLayout.CENTER);
|
expGained.setFont(FontManager.getRunescapeSmallFont());
|
||||||
}
|
expHour.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
private void showStatsPanel()
|
leftPanel.add(expGained);
|
||||||
{
|
leftPanel.add(expHour);
|
||||||
if (statsPanel.isShowing())
|
|
||||||
{
|
JPanel rightPanel = new JPanel();
|
||||||
container.remove(statsPanel);
|
rightPanel.setOpaque(false);
|
||||||
revalidate();
|
rightPanel.setLayout(new GridLayout(2, 1));
|
||||||
}
|
|
||||||
else
|
expLeft.setFont(FontManager.getRunescapeSmallFont());
|
||||||
{
|
actionsLeft.setFont(FontManager.getRunescapeSmallFont());
|
||||||
container.add(statsPanel, BorderLayout.SOUTH);
|
|
||||||
revalidate();
|
rightPanel.add(expLeft);
|
||||||
}
|
rightPanel.add(actionsLeft);
|
||||||
|
|
||||||
|
statsPanel.add(leftPanel, BorderLayout.WEST);
|
||||||
|
statsPanel.add(rightPanel, BorderLayout.EAST);
|
||||||
|
|
||||||
|
headerPanel.add(skillIcon, BorderLayout.WEST);
|
||||||
|
headerPanel.add(statsPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel progressWrapper = new JPanel();
|
||||||
|
progressWrapper.setOpaque(false);
|
||||||
|
progressWrapper.setLayout(new BorderLayout());
|
||||||
|
progressWrapper.setBorder(new EmptyBorder(0, 7, 7, 7));
|
||||||
|
|
||||||
|
progressBar.setMaximumValue(100);
|
||||||
|
progressBar.setBackground(new Color(61, 56, 49));
|
||||||
|
progressBar.setForeground(SkillColor.values()[skill.ordinal()].getColor());
|
||||||
|
|
||||||
|
progressWrapper.add(progressBar, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
container.add(headerPanel, BorderLayout.NORTH);
|
||||||
|
container.add(progressWrapper, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
add(container, BorderLayout.NORTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
@@ -221,46 +182,46 @@ class XpInfoBox extends JPanel
|
|||||||
panel.revalidate();
|
panel.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
levelLabel.setText(String.valueOf(xpSnapshotSingle.getCurrentLevel()));
|
// Update information labels
|
||||||
xpGained.setText(XpPanel.formatLine(xpSnapshotSingle.getXpGainedInSession(), "xp gained"));
|
expGained.setText(htmlLabel("XP Gained: ", xpSnapshotSingle.getXpGainedInSession()));
|
||||||
xpLeft.setText(XpPanel.formatLine(xpSnapshotSingle.getXpRemainingToGoal(), "xp left"));
|
expLeft.setText(htmlLabel("XP Left: ", xpSnapshotSingle.getXpRemainingToGoal()));
|
||||||
actionsLeft.setText(XpPanel.formatLine(xpSnapshotSingle.getActionsRemainingToGoal(), "actions left"));
|
actionsLeft.setText(htmlLabel("Actions: ", xpSnapshotSingle.getActionsRemainingToGoal()));
|
||||||
|
|
||||||
final int progress = xpSnapshotSingle.getSkillProgressToGoal();
|
// Update progress bar
|
||||||
|
progressBar.setValue(xpSnapshotSingle.getSkillProgressToGoal());
|
||||||
progressBar.setValue(progress);
|
progressBar.setCenterLabel(xpSnapshotSingle.getSkillProgressToGoal() + "%");
|
||||||
progressBar.setBackground(Color.getHSBColor((progress / 100.f) * (120.f / 360.f), 1, 1));
|
progressBar.setLeftLabel("Lvl. " + xpSnapshotSingle.getCurrentLevel());
|
||||||
|
progressBar.setRightLabel("Lvl. " + (xpSnapshotSingle.getCurrentLevel() + 1));
|
||||||
|
|
||||||
progressBar.setToolTipText("<html>"
|
progressBar.setToolTipText("<html>"
|
||||||
+ XpPanel.formatLine(xpSnapshotSingle.getActionsInSession(), "actions")
|
+ xpSnapshotSingle.getActionsInSession() + " actions done"
|
||||||
+ "<br/>"
|
+ "<br/>"
|
||||||
+ XpPanel.formatLine(xpSnapshotSingle.getActionsPerHour(), "actions/hr")
|
+ xpSnapshotSingle.getActionsPerHour() + " actions/hr"
|
||||||
+ "<br/>"
|
+ "<br/>"
|
||||||
+ xpSnapshotSingle.getTimeTillGoal() + " till next lvl"
|
+ xpSnapshotSingle.getTimeTillGoal() + " till next lvl"
|
||||||
+ "</html>");
|
+ "</html>");
|
||||||
|
|
||||||
|
progressBar.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always update xp/hr as time always changes
|
// Update exp per hour seperately, everytime (not only when there's an update)
|
||||||
xpHr.setText(XpPanel.formatLine(xpSnapshotSingle.getXpPerHour(), "xp/hr"));
|
expHour.setText(htmlLabel("XP/Hour: ", xpSnapshotSingle.getXpPerHour()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BufferedImage createHoverImage(BufferedImage image)
|
public static String htmlLabel(String key, int value)
|
||||||
{
|
{
|
||||||
LookupTable lookup = new LookupTable(0, 4)
|
String valueStr = value + "";
|
||||||
|
|
||||||
|
if (value > 9999999 || value < -9999999)
|
||||||
{
|
{
|
||||||
@Override
|
valueStr = "Lots!";
|
||||||
public int[] lookupPixel(int[] src, int[] dest)
|
}
|
||||||
{
|
else
|
||||||
if (dest[3] != 0)
|
{
|
||||||
{
|
valueStr = StackFormatter.quantityToRSDecimalStack(value);
|
||||||
dest[3] = 60;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
return "<html><body style = 'color:" + SwingUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR) + "'>" + key + "<span style = 'color:white'>" + valueStr + "</span></body></html>";
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
LookupOp op = new LookupOp(lookup, new RenderingHints(null));
|
|
||||||
return op.filter(image, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Cameron <moberg@tuta.io>
|
* Copyright (c) 2017, Cameron <moberg@tuta.io>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -29,64 +30,93 @@ import java.awt.GridLayout;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.BorderFactory;
|
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JButton;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Actor;
|
import net.runelite.api.Actor;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.Skill;
|
import net.runelite.api.Skill;
|
||||||
import net.runelite.client.game.SkillIconManager;
|
import net.runelite.client.game.SkillIconManager;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
|
import net.runelite.client.ui.components.PluginErrorPanel;
|
||||||
import net.runelite.client.util.LinkBrowser;
|
import net.runelite.client.util.LinkBrowser;
|
||||||
import net.runelite.client.util.StackFormatter;
|
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
class XpPanel extends PluginPanel
|
class XpPanel extends PluginPanel
|
||||||
{
|
{
|
||||||
private final Map<Skill, XpInfoBox> infoBoxes = new HashMap<>();
|
private final Map<Skill, XpInfoBox> infoBoxes = new HashMap<>();
|
||||||
private final JLabel totalXpGained = new JLabel();
|
|
||||||
private final JLabel totalXpHr = new JLabel();
|
private final JLabel overallExpGained = new JLabel(XpInfoBox.htmlLabel("Gained: ", 0));
|
||||||
|
private final JLabel overallExpHour = new JLabel(XpInfoBox.htmlLabel("Per hour: ", 0));
|
||||||
|
|
||||||
|
private final JPanel overallPanel = new JPanel();
|
||||||
|
|
||||||
|
/* This displays the "No exp gained" text */
|
||||||
|
private final PluginErrorPanel errorPanel = new PluginErrorPanel();
|
||||||
|
|
||||||
XpPanel(XpTrackerPlugin xpTrackerPlugin, Client client, SkillIconManager iconManager)
|
XpPanel(XpTrackerPlugin xpTrackerPlugin, Client client, SkillIconManager iconManager)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
final JPanel layoutPanel = new JPanel();
|
final JPanel layoutPanel = new JPanel();
|
||||||
layoutPanel.setLayout(new BorderLayout(0, 3));
|
layoutPanel.setOpaque(false);
|
||||||
|
layoutPanel.setLayout(new BorderLayout());
|
||||||
add(layoutPanel);
|
add(layoutPanel);
|
||||||
|
|
||||||
final JPanel totalPanel = new JPanel();
|
overallPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
totalPanel.setLayout(new BorderLayout());
|
overallPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
totalPanel.setBorder(BorderFactory.createLineBorder(getBackground().brighter(), 1, true));
|
overallPanel.setLayout(new BorderLayout());
|
||||||
|
overallPanel.setVisible(false); // this will only become visible when the player gets exp
|
||||||
|
|
||||||
final JPanel infoPanel = new JPanel();
|
// Create open xp tracker menu
|
||||||
infoPanel.setLayout(new GridLayout(4, 1));
|
final JMenuItem openXpTracker = new JMenuItem("Open online tracker");
|
||||||
infoPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
|
openXpTracker.addActionListener(e -> LinkBrowser.browse(XpPanel.buildXpTrackerUrl(client.getLocalPlayer(), Skill.OVERALL)));
|
||||||
|
|
||||||
final JButton resetButton = new JButton("Reset All");
|
// Create reset all menu
|
||||||
resetButton.addActionListener(e -> xpTrackerPlugin.resetAndInitState());
|
final JMenuItem reset = new JMenuItem("Reset All");
|
||||||
|
reset.addActionListener(e -> xpTrackerPlugin.resetAndInitState());
|
||||||
|
|
||||||
final JButton openTrackerButton = new JButton("Open XP tracker");
|
// Create popup menu
|
||||||
openTrackerButton.addActionListener(e -> LinkBrowser.browse(buildXpTrackerUrl(client.getLocalPlayer(), Skill.OVERALL)));
|
final JPopupMenu popupMenu = new JPopupMenu();
|
||||||
|
popupMenu.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
|
popupMenu.add(openXpTracker);
|
||||||
|
popupMenu.add(reset);
|
||||||
|
overallPanel.setComponentPopupMenu(popupMenu);
|
||||||
|
|
||||||
totalXpGained.setText(formatLine(0, "total xp gained"));
|
final JLabel overallIcon = new JLabel(new ImageIcon(iconManager.getSkillImage(Skill.OVERALL)));
|
||||||
totalXpHr.setText(formatLine(0, "total xp/hr"));
|
|
||||||
|
final JPanel overallInfo = new JPanel();
|
||||||
|
overallInfo.setOpaque(false);
|
||||||
|
overallInfo.setLayout(new GridLayout(2, 1));
|
||||||
|
overallInfo.setBorder(new EmptyBorder(0, 10, 0, 0));
|
||||||
|
|
||||||
|
overallExpGained.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
overallExpHour.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
|
||||||
|
overallInfo.add(overallExpGained);
|
||||||
|
overallInfo.add(overallExpHour);
|
||||||
|
|
||||||
|
overallPanel.add(overallIcon, BorderLayout.WEST);
|
||||||
|
overallPanel.add(overallInfo, BorderLayout.CENTER);
|
||||||
|
|
||||||
infoPanel.add(totalXpGained);
|
|
||||||
infoPanel.add(totalXpHr);
|
|
||||||
infoPanel.add(resetButton);
|
|
||||||
infoPanel.add(openTrackerButton);
|
|
||||||
totalPanel.add(infoPanel, BorderLayout.CENTER);
|
|
||||||
layoutPanel.add(totalPanel, BorderLayout.NORTH);
|
|
||||||
|
|
||||||
final JPanel infoBoxPanel = new JPanel();
|
final JPanel infoBoxPanel = new JPanel();
|
||||||
|
infoBoxPanel.setOpaque(false);
|
||||||
infoBoxPanel.setLayout(new BoxLayout(infoBoxPanel, BoxLayout.Y_AXIS));
|
infoBoxPanel.setLayout(new BoxLayout(infoBoxPanel, BoxLayout.Y_AXIS));
|
||||||
layoutPanel.add(infoBoxPanel, BorderLayout.CENTER);
|
layoutPanel.add(infoBoxPanel, BorderLayout.CENTER);
|
||||||
|
layoutPanel.add(overallPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -96,7 +126,6 @@ class XpPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
infoBoxes.put(skill, new XpInfoBox(xpTrackerPlugin, client, infoBoxPanel, skill, iconManager));
|
infoBoxes.put(skill, new XpInfoBox(xpTrackerPlugin, client, infoBoxPanel, skill, iconManager));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,6 +133,10 @@ class XpPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
log.warn(null, e);
|
log.warn(null, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorPanel.setContent("Exp trackers", "You have not gained experience yet.");
|
||||||
|
errorPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||||
|
add(errorPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String buildXpTrackerUrl(final Actor player, final Skill skill)
|
static String buildXpTrackerUrl(final Actor player, final Skill skill)
|
||||||
@@ -150,30 +183,23 @@ class XpPanel extends PluginPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTotal(XpSnapshotTotal xpSnapshotTotal)
|
|
||||||
|
public void updateTotal(XpSnapshotTotal xpSnapshotTotal)
|
||||||
{
|
{
|
||||||
|
// if player has gained exp and hasn't switched displays yet, hide error panel and show overall info
|
||||||
|
if (xpSnapshotTotal.getXpGainedInSession() > 0 && !overallPanel.isVisible())
|
||||||
|
{
|
||||||
|
overallPanel.setVisible(true);
|
||||||
|
remove(errorPanel);
|
||||||
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> rebuildAsync(xpSnapshotTotal));
|
SwingUtilities.invokeLater(() -> rebuildAsync(xpSnapshotTotal));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rebuildAsync(XpSnapshotTotal xpSnapshotTotal)
|
private void rebuildAsync(XpSnapshotTotal xpSnapshotTotal)
|
||||||
{
|
{
|
||||||
totalXpGained.setText(formatLine(xpSnapshotTotal.getXpGainedInSession(), "total xp gained"));
|
overallExpGained.setText(XpInfoBox.htmlLabel("Gained: ", xpSnapshotTotal.getXpGainedInSession()));
|
||||||
totalXpHr.setText(formatLine(xpSnapshotTotal.getXpPerHour(), "total xp/hr"));
|
overallExpHour.setText(XpInfoBox.htmlLabel("Per hour: ", xpSnapshotTotal.getXpPerHour()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static String formatLine(double number, String description)
|
|
||||||
{
|
|
||||||
String numberStr;
|
|
||||||
if (number < 100000)
|
|
||||||
{
|
|
||||||
numberStr = StackFormatter.formatNumber(number);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int num = (int) (Math.log(number) / Math.log(1000));
|
|
||||||
numberStr = String.format("%.1f%c", number / Math.pow(1000, num), "KMB".charAt(num - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return numberStr + " " + description;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ public class XpTrackerPlugin extends Plugin
|
|||||||
navButton = NavigationButton.builder()
|
navButton = NavigationButton.builder()
|
||||||
.name("XP Tracker")
|
.name("XP Tracker")
|
||||||
.icon(icon)
|
.icon(icon)
|
||||||
|
.priority(2)
|
||||||
.panel(xpPanel)
|
.panel(xpPanel)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
@@ -67,11 +67,12 @@ import net.runelite.client.events.PluginToolbarButtonAdded;
|
|||||||
import net.runelite.client.events.PluginToolbarButtonRemoved;
|
import net.runelite.client.events.PluginToolbarButtonRemoved;
|
||||||
import net.runelite.client.events.TitleToolbarButtonAdded;
|
import net.runelite.client.events.TitleToolbarButtonAdded;
|
||||||
import net.runelite.client.events.TitleToolbarButtonRemoved;
|
import net.runelite.client.events.TitleToolbarButtonRemoved;
|
||||||
|
import net.runelite.client.ui.skin.SubstanceRuneLiteLookAndFeel;
|
||||||
import net.runelite.client.input.KeyManager;
|
import net.runelite.client.input.KeyManager;
|
||||||
import net.runelite.client.util.OSType;
|
import net.runelite.client.util.OSType;
|
||||||
import net.runelite.client.util.OSXUtil;
|
import net.runelite.client.util.OSXUtil;
|
||||||
import net.runelite.client.util.SwingUtil;
|
import net.runelite.client.util.SwingUtil;
|
||||||
import org.pushingpixels.substance.api.skin.SubstanceGraphiteLookAndFeel;
|
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
||||||
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
||||||
import org.pushingpixels.substance.internal.utils.SubstanceTitlePaneUtilities;
|
import org.pushingpixels.substance.internal.utils.SubstanceTitlePaneUtilities;
|
||||||
|
|
||||||
@@ -327,7 +328,7 @@ public class ClientUI
|
|||||||
SwingUtil.setupDefaults();
|
SwingUtil.setupDefaults();
|
||||||
|
|
||||||
// Use substance look and feel
|
// Use substance look and feel
|
||||||
SwingUtil.setTheme(new SubstanceGraphiteLookAndFeel());
|
SwingUtil.setTheme(new SubstanceRuneLiteLookAndFeel());
|
||||||
|
|
||||||
// Use custom UI font
|
// Use custom UI font
|
||||||
SwingUtil.setFont(FontManager.getRunescapeFont());
|
SwingUtil.setFont(FontManager.getRunescapeFont());
|
||||||
@@ -362,6 +363,8 @@ public class ClientUI
|
|||||||
navContainer.setLayout(new BorderLayout(0, 0));
|
navContainer.setLayout(new BorderLayout(0, 0));
|
||||||
navContainer.setMinimumSize(new Dimension(0, 0));
|
navContainer.setMinimumSize(new Dimension(0, 0));
|
||||||
navContainer.setMaximumSize(new Dimension(0, Integer.MAX_VALUE));
|
navContainer.setMaximumSize(new Dimension(0, Integer.MAX_VALUE));
|
||||||
|
// To reduce substance's colorization (tinting)
|
||||||
|
navContainer.putClientProperty(SubstanceSynapse.COLORIZATION_FACTOR, 1.0);
|
||||||
container.add(navContainer);
|
container.add(navContainer);
|
||||||
|
|
||||||
pluginToolbar = new ClientPluginToolbar();
|
pluginToolbar = new ClientPluginToolbar();
|
||||||
@@ -565,6 +568,7 @@ public class ClientUI
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get offset of game canvas in game window
|
* Get offset of game canvas in game window
|
||||||
|
*
|
||||||
* @return game canvas offset
|
* @return game canvas offset
|
||||||
*/
|
*/
|
||||||
public Point getCanvasOffset()
|
public Point getCanvasOffset()
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class serves to hold commonly used UI colors.
|
||||||
|
*/
|
||||||
|
public class ColorScheme
|
||||||
|
{
|
||||||
|
/* The orange color used for the branding's accents */
|
||||||
|
public static final Color BRAND_ORANGE = new Color(220, 138, 0);
|
||||||
|
|
||||||
|
/* The orange color used for the branding's accents, with lowered opacity */
|
||||||
|
public static final Color BRAND_ORANGE_TRANSPARENT = new Color(220, 138, 0, 120);
|
||||||
|
|
||||||
|
public static final Color DARKER_GRAY_COLOR = new Color(30, 30, 30);
|
||||||
|
public static final Color DARK_GRAY_COLOR = new Color(40, 40, 40);
|
||||||
|
public static final Color MEDIUM_GRAY_COLOR = new Color(77, 77, 77);
|
||||||
|
public static final Color LIGHT_GRAY_COLOR = new Color(165, 165, 165);
|
||||||
|
public static final Color DARK_GRAY_HOVER_COLOR = new Color(35, 35, 35);
|
||||||
|
|
||||||
|
/* The color for the green progress bar (used in ge offers, farming tracker, etc)*/
|
||||||
|
public static final Color PROGRESS_COMPLETE_COLOR = new Color(55, 240, 70);
|
||||||
|
|
||||||
|
/* The color for the red progress bar (used in ge offers, farming tracker, etc)*/
|
||||||
|
public static final Color PROGRESS_ERROR_COLOR = new Color(230, 30, 30);
|
||||||
|
|
||||||
|
/* The color for the orange progress bar (used in ge offers, farming tracker, etc)*/
|
||||||
|
public static final Color PROGRESS_INPROGRESS_COLOR = new Color(230, 150, 30);
|
||||||
|
|
||||||
|
/* The color for the price indicator in the ge search results */
|
||||||
|
public static final Color GRAND_EXCHANGE_PRICE = new Color(110, 225, 110);
|
||||||
|
|
||||||
|
/* The color for the high alch indicator in the ge search results */
|
||||||
|
public static final Color GRAND_EXCHANGE_ALCH = new Color(240, 207, 123);
|
||||||
|
|
||||||
|
/* The background color of the scrollbar's track */
|
||||||
|
public static final Color SCROLL_TRACK_COLOR = new Color(25, 25, 25);
|
||||||
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* 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.Container;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grid layout implementation with support for cells with unequal size.
|
||||||
|
*
|
||||||
|
* See https://www.javaworld.com/article/2077486/core-java/java-tip-121--flex-your-grid-layout.html
|
||||||
|
*/
|
||||||
|
public class DynamicGridLayout extends GridLayout
|
||||||
|
{
|
||||||
|
public DynamicGridLayout()
|
||||||
|
{
|
||||||
|
this(1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicGridLayout(int rows, int cols)
|
||||||
|
{
|
||||||
|
this(rows, cols, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicGridLayout(int rows, int cols, int hgap, int vgap)
|
||||||
|
{
|
||||||
|
super(rows, cols, hgap, vgap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension preferredLayoutSize(Container parent)
|
||||||
|
{
|
||||||
|
synchronized (parent.getTreeLock())
|
||||||
|
{
|
||||||
|
return calculateSize(parent, Component::getPreferredSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension minimumLayoutSize(Container parent)
|
||||||
|
{
|
||||||
|
synchronized (parent.getTreeLock())
|
||||||
|
{
|
||||||
|
return calculateSize(parent, Component::getMinimumSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void layoutContainer(Container parent)
|
||||||
|
{
|
||||||
|
synchronized (parent.getTreeLock())
|
||||||
|
{
|
||||||
|
final Insets insets = parent.getInsets();
|
||||||
|
final int ncomponents = parent.getComponentCount();
|
||||||
|
int nrows = getRows();
|
||||||
|
int ncols = getColumns();
|
||||||
|
|
||||||
|
if (ncomponents == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nrows > 0)
|
||||||
|
{
|
||||||
|
ncols = (ncomponents + nrows - 1) / nrows;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nrows = (ncomponents + ncols - 1) / ncols;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int hgap = getHgap();
|
||||||
|
final int vgap = getVgap();
|
||||||
|
|
||||||
|
// scaling factors
|
||||||
|
final Dimension pd = preferredLayoutSize(parent);
|
||||||
|
final double sw = (1.0 * parent.getWidth()) / pd.width;
|
||||||
|
final double sh = (1.0 * parent.getHeight()) / pd.height;
|
||||||
|
|
||||||
|
final int[] w = new int[ncols];
|
||||||
|
final int[] h = new int[nrows];
|
||||||
|
|
||||||
|
// calculate dimensions for all components + apply scaling
|
||||||
|
for (int i = 0; i < ncomponents; i++)
|
||||||
|
{
|
||||||
|
final int r = i / ncols;
|
||||||
|
final int c = i % ncols;
|
||||||
|
final Component comp = parent.getComponent(i);
|
||||||
|
final Dimension d = comp.getPreferredSize();
|
||||||
|
d.width = (int) (sw * d.width);
|
||||||
|
d.height = (int) (sh * d.height);
|
||||||
|
|
||||||
|
if (w[c] < d.width)
|
||||||
|
{
|
||||||
|
w[c] = d.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h[r] < d.height)
|
||||||
|
{
|
||||||
|
h[r] = d.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply new bounds to all child components
|
||||||
|
for (int c = 0, x = insets.left; c < ncols; c++)
|
||||||
|
{
|
||||||
|
for (int r = 0, y = insets.top; r < nrows; r++)
|
||||||
|
{
|
||||||
|
int i = r * ncols + c;
|
||||||
|
|
||||||
|
if (i < ncomponents)
|
||||||
|
{
|
||||||
|
parent.getComponent(i).setBounds(x, y, w[c], h[r]);
|
||||||
|
}
|
||||||
|
|
||||||
|
y += h[r] + vgap;
|
||||||
|
}
|
||||||
|
|
||||||
|
x += w[c] + hgap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate outer size of the layout based on it's children and sizer
|
||||||
|
* @param parent parent component
|
||||||
|
* @param sizer functioning returning dimension of the child component
|
||||||
|
* @return outer size
|
||||||
|
*/
|
||||||
|
private Dimension calculateSize(final Container parent, final Function<Component, Dimension> sizer)
|
||||||
|
{
|
||||||
|
final int ncomponents = parent.getComponentCount();
|
||||||
|
int nrows = getRows();
|
||||||
|
int ncols = getColumns();
|
||||||
|
|
||||||
|
if (nrows > 0)
|
||||||
|
{
|
||||||
|
ncols = (ncomponents + nrows - 1) / nrows;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nrows = (ncomponents + ncols - 1) / ncols;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] w = new int[ncols];
|
||||||
|
final int[] h = new int[nrows];
|
||||||
|
|
||||||
|
// Calculate dimensions for all components
|
||||||
|
for (int i = 0; i < ncomponents; i++)
|
||||||
|
{
|
||||||
|
final int r = i / ncols;
|
||||||
|
final int c = i % ncols;
|
||||||
|
final Component comp = parent.getComponent(i);
|
||||||
|
final Dimension d = sizer.apply(comp);
|
||||||
|
|
||||||
|
if (w[c] < d.width)
|
||||||
|
{
|
||||||
|
w[c] = d.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h[r] < d.height)
|
||||||
|
{
|
||||||
|
h[r] = d.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate total width and height of the layout
|
||||||
|
int nw = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < ncols; j++)
|
||||||
|
{
|
||||||
|
nw += w[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
int nh = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < nrows; i++)
|
||||||
|
{
|
||||||
|
nh += h[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
final Insets insets = parent.getInsets();
|
||||||
|
|
||||||
|
// Apply insets and horizontal and vertical gap to layout
|
||||||
|
return new Dimension(
|
||||||
|
insets.left + insets.right + nw + (ncols - 1) * getHgap(),
|
||||||
|
insets.top + insets.bottom + nh + (nrows - 1) * getVgap());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,12 @@ public class NavigationButton
|
|||||||
*/
|
*/
|
||||||
private PluginPanel panel;
|
private PluginPanel panel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The order in which the button should be displayed in the side bar. (from lower to higher)
|
||||||
|
*/
|
||||||
|
private int priority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of key-value pairs for setting the popup menu
|
* Map of key-value pairs for setting the popup menu
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -60,13 +60,14 @@ public abstract class PluginPanel extends JPanel
|
|||||||
{
|
{
|
||||||
setBorder(BORDER_PADDING);
|
setBorder(BORDER_PADDING);
|
||||||
setLayout(new GridLayout(0, 1, 0, 3));
|
setLayout(new GridLayout(0, 1, 0, 3));
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
final JPanel northPanel = new JPanel();
|
final JPanel northPanel = new JPanel();
|
||||||
northPanel.setLayout(new BorderLayout());
|
northPanel.setLayout(new BorderLayout());
|
||||||
northPanel.add(this, BorderLayout.NORTH);
|
northPanel.add(this, BorderLayout.NORTH);
|
||||||
|
northPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
|
||||||
scrollPane = new JScrollPane(northPanel);
|
scrollPane = new JScrollPane(northPanel);
|
||||||
scrollPane.getVerticalScrollBar().setUnitIncrement(16); //Otherwise scrollspeed is really slow
|
|
||||||
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
|
||||||
wrappedPanel = new JPanel();
|
wrappedPanel = new JPanel();
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.ui;
|
package net.runelite.client.ui;
|
||||||
|
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
@@ -39,7 +39,11 @@ import net.runelite.client.events.PluginToolbarButtonRemoved;
|
|||||||
public class PluginToolbar
|
public class PluginToolbar
|
||||||
{
|
{
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final TreeSet<NavigationButton> buttons = new TreeSet<>(Comparator.comparing(NavigationButton::getName));
|
private final TreeSet<NavigationButton> buttons = new TreeSet<>((a, b) ->
|
||||||
|
ComparisonChain.start()
|
||||||
|
.compare(a.getPriority(), b.getPriority())
|
||||||
|
.compare(a.getName(), b.getName())
|
||||||
|
.result());
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PluginToolbar(final EventBus eventBus)
|
private PluginToolbar(final EventBus eventBus)
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.components;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.ListCellRenderer;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom list renderer to avoid substance's weird coloring.
|
||||||
|
* Substance was making selected items' foreground color black, this
|
||||||
|
* was very hard to see in the dark gray background, this makes the selected
|
||||||
|
* item white and adds some padding to the elements for more readable list.
|
||||||
|
*/
|
||||||
|
public final class ComboBoxListRenderer extends JLabel implements ListCellRenderer
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(JList list, Object o, int index, boolean isSelected, boolean cellHasFocus)
|
||||||
|
{
|
||||||
|
if (isSelected)
|
||||||
|
{
|
||||||
|
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
|
setForeground(Color.WHITE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setBackground(list.getBackground());
|
||||||
|
setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
setBorder(new EmptyBorder(5, 5, 5, 0));
|
||||||
|
|
||||||
|
String text = (String) o.toString();
|
||||||
|
setText(text);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.components;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JScrollBar;
|
||||||
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.basic.BasicScrollBarUI;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This scroll bar UI is to be used for the "RuneLite Obsidian" client theme.
|
||||||
|
* It is a part of the client's redesign as detailed on issue #1342
|
||||||
|
*/
|
||||||
|
public class CustomScrollBarUI extends BasicScrollBarUI
|
||||||
|
{
|
||||||
|
|
||||||
|
/* The background color of the bar's thumb */
|
||||||
|
@Setter
|
||||||
|
private Color thumbColor = ColorScheme.MEDIUM_GRAY_COLOR;
|
||||||
|
|
||||||
|
/* The background color of the bar's track */
|
||||||
|
@Setter
|
||||||
|
private Color trackColor = ColorScheme.SCROLL_TRACK_COLOR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the painting of the bar's track (the darker part underneath that extends
|
||||||
|
* the full page length).
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void paintTrack(Graphics graphics, JComponent jComponent, Rectangle rectangle)
|
||||||
|
{
|
||||||
|
graphics.setColor(trackColor);
|
||||||
|
graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the painting of the bar's thumb (the lighter part on top that users
|
||||||
|
* use to slide up and down the page).
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void paintThumb(Graphics graphics, JComponent jComponent, Rectangle rectangle)
|
||||||
|
{
|
||||||
|
graphics.setColor(thumbColor);
|
||||||
|
graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty JButton to be used as the scroll bar's arrows (to disable the arrows).
|
||||||
|
*/
|
||||||
|
protected JButton createEmptyButton()
|
||||||
|
{
|
||||||
|
JButton button = new JButton();
|
||||||
|
Dimension zeroDim = new Dimension(0, 0);
|
||||||
|
button.setPreferredSize(zeroDim);
|
||||||
|
button.setMinimumSize(zeroDim);
|
||||||
|
button.setMaximumSize(zeroDim);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ComponentUI createUI(JComponent c)
|
||||||
|
{
|
||||||
|
JScrollBar bar = (JScrollBar) c;
|
||||||
|
bar.setUnitIncrement(16);
|
||||||
|
bar.setPreferredSize(new Dimension(7, 0));
|
||||||
|
return new CustomScrollBarUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies an empty button to the decrease (down arrow) button.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected JButton createDecreaseButton(int orientation)
|
||||||
|
{
|
||||||
|
return createEmptyButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies an empty button to the increase (up arrow) button.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected JButton createIncreaseButton(int orientation)
|
||||||
|
{
|
||||||
|
return createEmptyButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||||
|
* Copyright (c) 2018, Psikoi <Adam@sigterm.info>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 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 HOLDER 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.components;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.KeyListener;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component is a JTextField with an icon on its left side.
|
||||||
|
*/
|
||||||
|
public class IconTextField extends JPanel
|
||||||
|
{
|
||||||
|
private final JTextField textField;
|
||||||
|
|
||||||
|
//to support gifs, the icon needs to be wrapped in a JLabel
|
||||||
|
private final JLabel iconWrapperLabel;
|
||||||
|
|
||||||
|
//the default background color, this needs to be stored for hover effects
|
||||||
|
private Color backgroundColor = ColorScheme.DARKER_GRAY_COLOR;
|
||||||
|
//the default hover background color, this needs to be stored for hover effects
|
||||||
|
private Color hoverBackgroundColor;
|
||||||
|
|
||||||
|
// the input can be blocked (no clicking, no editing, no hover effects)
|
||||||
|
private boolean blocked;
|
||||||
|
|
||||||
|
public IconTextField()
|
||||||
|
{
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
this.iconWrapperLabel = new JLabel();
|
||||||
|
this.iconWrapperLabel.setPreferredSize(new Dimension(30, 0));
|
||||||
|
this.iconWrapperLabel.setVerticalAlignment(JLabel.CENTER);
|
||||||
|
this.iconWrapperLabel.setHorizontalAlignment(JLabel.CENTER);
|
||||||
|
|
||||||
|
this.textField = new JTextField();
|
||||||
|
this.textField.setBorder(null);
|
||||||
|
this.textField.setOpaque(false);
|
||||||
|
this.textField.setSelectedTextColor(Color.WHITE);
|
||||||
|
this.textField.setSelectionColor(ColorScheme.BRAND_ORANGE_TRANSPARENT);
|
||||||
|
|
||||||
|
add(iconWrapperLabel, BorderLayout.WEST);
|
||||||
|
add(textField, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
textField.addMouseListener(new MouseAdapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mouseEntered(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
if (blocked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hoverBackgroundColor != null)
|
||||||
|
{
|
||||||
|
IconTextField.super.setBackground(hoverBackgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExited(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
IconTextField.super.setBackground(backgroundColor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addActionListener(ActionListener actionListener)
|
||||||
|
{
|
||||||
|
textField.addActionListener(actionListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIcon(ImageIcon icon)
|
||||||
|
{
|
||||||
|
iconWrapperLabel.setIcon(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText()
|
||||||
|
{
|
||||||
|
return textField.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text)
|
||||||
|
{
|
||||||
|
textField.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBackground(Color color)
|
||||||
|
{
|
||||||
|
if (color == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.setBackground(color);
|
||||||
|
this.backgroundColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addInputKeyListener(KeyListener l)
|
||||||
|
{
|
||||||
|
textField.addKeyListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeInputKeyListener(KeyListener l)
|
||||||
|
{
|
||||||
|
textField.removeKeyListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHoverBackgroundColor(Color hoverBackgroundColor)
|
||||||
|
{
|
||||||
|
if (hoverBackgroundColor == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.hoverBackgroundColor = hoverBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEditable(boolean editable)
|
||||||
|
{
|
||||||
|
this.blocked = !editable;
|
||||||
|
textField.setEditable(editable);
|
||||||
|
textField.setFocusable(editable);
|
||||||
|
if (!editable)
|
||||||
|
{
|
||||||
|
super.setBackground(backgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Document getDocument()
|
||||||
|
{
|
||||||
|
return textField.getDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 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 HOLDER 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.components;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
|
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component to display an error/info message (to be used on a plugin panel)
|
||||||
|
* Example uses are: no ge search results found, no ge offers found.
|
||||||
|
*/
|
||||||
|
public class PluginErrorPanel extends JPanel
|
||||||
|
{
|
||||||
|
private final JLabel noResultsTitle = new JShadowedLabel();
|
||||||
|
private final JLabel noResultsDescription = new JShadowedLabel();
|
||||||
|
|
||||||
|
public PluginErrorPanel()
|
||||||
|
{
|
||||||
|
setOpaque(false);
|
||||||
|
setBorder(new EmptyBorder(50, 10, 0, 10));
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
noResultsTitle.setForeground(Color.WHITE);
|
||||||
|
noResultsTitle.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
|
||||||
|
noResultsDescription.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
noResultsDescription.setForeground(Color.GRAY);
|
||||||
|
noResultsDescription.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
|
||||||
|
add(noResultsTitle, BorderLayout.NORTH);
|
||||||
|
add(noResultsDescription, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the content of the panel to the given parameters.
|
||||||
|
* The description has to be wrapped in html so that its text can be wrapped.
|
||||||
|
*/
|
||||||
|
public void setContent(String title, String description)
|
||||||
|
{
|
||||||
|
noResultsTitle.setText(title);
|
||||||
|
noResultsDescription.setText("<html><body style = 'text-align:center'>" + description + "</body></html>");
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.components;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.runelite.client.ui.FontManager;
|
||||||
|
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A progress bar to be displayed underneath the GE offer item panels
|
||||||
|
*/
|
||||||
|
public class ProgressBar extends JPanel
|
||||||
|
{
|
||||||
|
@Setter
|
||||||
|
private int maximumValue;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
private final JLabel leftLabel = new JShadowedLabel();
|
||||||
|
private final JLabel rightLabel = new JShadowedLabel();
|
||||||
|
private final JLabel centerLabel = new JShadowedLabel();
|
||||||
|
|
||||||
|
public ProgressBar()
|
||||||
|
{
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
setBackground(Color.GREEN.darker());
|
||||||
|
setPreferredSize(new Dimension(100, 16));
|
||||||
|
|
||||||
|
leftLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
leftLabel.setForeground(Color.WHITE);
|
||||||
|
leftLabel.setBorder(new EmptyBorder(2, 5, 0, 0));
|
||||||
|
|
||||||
|
rightLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
rightLabel.setForeground(Color.WHITE);
|
||||||
|
rightLabel.setBorder(new EmptyBorder(2, 0, 0, 5));
|
||||||
|
|
||||||
|
centerLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||||
|
centerLabel.setForeground(Color.WHITE);
|
||||||
|
centerLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
centerLabel.setBorder(new EmptyBorder(2, 0, 0, 0));
|
||||||
|
|
||||||
|
add(leftLabel, BorderLayout.WEST);
|
||||||
|
add(centerLabel, BorderLayout.CENTER);
|
||||||
|
add(rightLabel, BorderLayout.EAST);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g)
|
||||||
|
{
|
||||||
|
double percentage = getPercentage();
|
||||||
|
int topWidth = (int) (getSize().width * (percentage / 100));
|
||||||
|
|
||||||
|
super.paint(g);
|
||||||
|
g.setColor(getForeground());
|
||||||
|
g.fillRect(0, 0, topWidth, 16);
|
||||||
|
super.paintComponents(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLeftLabel(String txt)
|
||||||
|
{
|
||||||
|
this.leftLabel.setText(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRightLabel(String txt)
|
||||||
|
{
|
||||||
|
this.rightLabel.setText(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCenterLabel(String txt)
|
||||||
|
{
|
||||||
|
this.centerLabel.setText(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPercentage()
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (value * 100) / maximumValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -23,54 +23,71 @@
|
|||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* 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.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.hiscore;
|
package net.runelite.client.ui.components;
|
||||||
|
|
||||||
import java.awt.Graphics;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Insets;
|
import java.awt.Color;
|
||||||
import javax.swing.BorderFactory;
|
import java.awt.Dimension;
|
||||||
import javax.swing.Icon;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
import lombok.Setter;
|
||||||
import javax.swing.border.Border;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
public class IconTextField extends JTextField
|
/**
|
||||||
|
* A progress bar to be displayed underneath the GE offer item panels
|
||||||
|
*/
|
||||||
|
public class ThinProgressBar extends JPanel
|
||||||
{
|
{
|
||||||
private Border border;
|
@Setter
|
||||||
private Icon icon;
|
private int maximumValue;
|
||||||
|
|
||||||
@Override
|
@Setter
|
||||||
public void setBorder(Border border)
|
private int value;
|
||||||
|
|
||||||
|
private final JPanel topBar = new JPanel();
|
||||||
|
|
||||||
|
public ThinProgressBar()
|
||||||
{
|
{
|
||||||
this.border = border;
|
setLayout(new BorderLayout());
|
||||||
|
setBackground(Color.GREEN.darker());
|
||||||
|
|
||||||
if (icon == null)
|
topBar.setPreferredSize(new Dimension(100, 4));
|
||||||
|
topBar.setBackground(ColorScheme.PROGRESS_COMPLETE_COLOR);
|
||||||
|
|
||||||
|
add(topBar, BorderLayout.WEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the UI based on the percentage progress
|
||||||
|
*/
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
double percentage = getPercentage();
|
||||||
|
int topWidth = (int) (getSize().width * (percentage / 100));
|
||||||
|
|
||||||
|
topBar.setPreferredSize(new Dimension(topWidth, 4));
|
||||||
|
topBar.repaint();
|
||||||
|
|
||||||
|
revalidate();
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPercentage()
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
{
|
{
|
||||||
super.setBorder(border);
|
return 0;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Border margin = BorderFactory.createEmptyBorder(0, icon.getIconWidth() + 4, 0, 0);
|
|
||||||
Border compound = BorderFactory.createCompoundBorder(border, margin);
|
|
||||||
super.setBorder(compound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (value * 100) / maximumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintComponent(Graphics graphics)
|
public void setForeground(Color color)
|
||||||
{
|
{
|
||||||
super.paintComponent(graphics);
|
if (topBar != null)
|
||||||
|
{
|
||||||
Insets iconInsets = border.getBorderInsets(this);
|
topBar.setBackground(color);
|
||||||
icon.paintIcon(this, graphics, iconInsets.left, iconInsets.top);
|
}
|
||||||
|
setBackground(color.darker());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void setIcon(Icon icon)
|
|
||||||
{
|
|
||||||
this.icon = icon;
|
|
||||||
resetBorder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetBorder()
|
|
||||||
{
|
|
||||||
setBorder(border);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.components.materialtabs;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
import javax.swing.border.CompoundBorder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import net.runelite.client.ui.ColorScheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a Material Design inspired tab.
|
||||||
|
* <p>
|
||||||
|
* Each tab will communicate with it's containing group when it's clicked
|
||||||
|
* and that group will display the tab's content on it's own display.
|
||||||
|
*
|
||||||
|
* @author Psikoi
|
||||||
|
*/
|
||||||
|
public class MaterialTab extends JLabel
|
||||||
|
{
|
||||||
|
private static final Border SELECTED_BORDER = new CompoundBorder(
|
||||||
|
BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.BRAND_ORANGE),
|
||||||
|
BorderFactory.createEmptyBorder(5, 10, 5, 10));
|
||||||
|
|
||||||
|
private static final Border UNSELECTED_BORDER = BorderFactory
|
||||||
|
.createEmptyBorder(5, 10, 5, 10);
|
||||||
|
|
||||||
|
/* The tab's containing group */
|
||||||
|
private final MaterialTabGroup group;
|
||||||
|
|
||||||
|
/* The tab's associated content display */
|
||||||
|
@Getter
|
||||||
|
private final JComponent content;
|
||||||
|
|
||||||
|
/* To be execuded when the tab is selected */
|
||||||
|
@Setter
|
||||||
|
private Runnable onSelectEvent;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private boolean selected;
|
||||||
|
|
||||||
|
public MaterialTab(String string, MaterialTabGroup group, JComponent content)
|
||||||
|
{
|
||||||
|
super(string);
|
||||||
|
|
||||||
|
this.group = group;
|
||||||
|
this.content = content;
|
||||||
|
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
select();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
addMouseListener(new MouseAdapter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
group.select(MaterialTab.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void select()
|
||||||
|
{
|
||||||
|
setBorder(SELECTED_BORDER);
|
||||||
|
setForeground(Color.WHITE);
|
||||||
|
selected = true;
|
||||||
|
if (onSelectEvent != null)
|
||||||
|
{
|
||||||
|
onSelectEvent.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unselect()
|
||||||
|
{
|
||||||
|
setBorder(UNSELECTED_BORDER);
|
||||||
|
setForeground(Color.GRAY);
|
||||||
|
selected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.components.materialtabs;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class will be a container (group) for the new Material Tabs. It will
|
||||||
|
* contain a list of tabs and a display (JPanel). When a tab is selected, the
|
||||||
|
* JPanel "display" will display the content associated with that tab.
|
||||||
|
* <p>
|
||||||
|
* How to use these tabs:
|
||||||
|
* <ol>
|
||||||
|
* <li>1 - Create displays (JPanels) for each tab</li>
|
||||||
|
* <li>2 - Create an empty JPanel to serve as the group's display</li>
|
||||||
|
* <li>3 - Create a new MaterialGroup, passing the panel in step 2 as a param</li>
|
||||||
|
* <li>4 - Create new tabs, passing the group in step 3 and one of the panels in
|
||||||
|
* step 1 as params</li>
|
||||||
|
* <li>5 - Add the tabs to the group using the MaterialTabGroup#addTab method</li>
|
||||||
|
* <li>6 - Select one of the tabs using the MaterialTab#select method</li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @author Psikoi
|
||||||
|
*/
|
||||||
|
public class MaterialTabGroup extends JPanel
|
||||||
|
{
|
||||||
|
/* The panel on which the content tab's content will be displayed on. */
|
||||||
|
private final JPanel display;
|
||||||
|
/* A list of all the tabs contained in this group. */
|
||||||
|
private final List<MaterialTab> tabs = new ArrayList<>();
|
||||||
|
|
||||||
|
public MaterialTabGroup(JPanel display)
|
||||||
|
{
|
||||||
|
this.display = display;
|
||||||
|
this.display.setLayout(new BorderLayout());
|
||||||
|
setLayout(new FlowLayout(FlowLayout.CENTER, 8, 0));
|
||||||
|
setOpaque(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the tab on a certain index. */
|
||||||
|
public MaterialTab getTab(int index)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (tabs == null || tabs.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabs.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTab(MaterialTab tab)
|
||||||
|
{
|
||||||
|
tabs.add(tab);
|
||||||
|
add(tab, BorderLayout.NORTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Selects a tab from the group, and sets the display's content to the
|
||||||
|
* tab's associated content.
|
||||||
|
* @param selectedTab - The tab to select
|
||||||
|
*/
|
||||||
|
public boolean select(MaterialTab selectedTab)
|
||||||
|
{
|
||||||
|
if (!tabs.contains(selectedTab))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
display.removeAll();
|
||||||
|
|
||||||
|
for (MaterialTab tab : tabs)
|
||||||
|
{
|
||||||
|
if (tab.equals(selectedTab))
|
||||||
|
{
|
||||||
|
tab.select();
|
||||||
|
display.add(tab.getContent());
|
||||||
|
display.revalidate();
|
||||||
|
display.repaint();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tab.unselect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.ui;
|
package net.runelite.client.ui.components.shadowlabel;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
package net.runelite.client.ui;
|
package net.runelite.client.ui.components.shadowlabel;
|
||||||
|
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.skin;
|
||||||
|
|
||||||
|
import javax.swing.AbstractButton;
|
||||||
|
import org.pushingpixels.substance.api.ComponentState;
|
||||||
|
import org.pushingpixels.substance.api.SubstanceColorSchemeBundle;
|
||||||
|
import org.pushingpixels.substance.api.SubstanceSkin;
|
||||||
|
import org.pushingpixels.substance.api.SubstanceSlices.ColorSchemeAssociationKind;
|
||||||
|
import org.pushingpixels.substance.api.SubstanceSlices.DecorationAreaType;
|
||||||
|
import org.pushingpixels.substance.api.colorscheme.ColorSchemeSingleColorQuery;
|
||||||
|
import org.pushingpixels.substance.api.colorscheme.SubstanceColorScheme;
|
||||||
|
import org.pushingpixels.substance.api.painter.border.ClassicBorderPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.border.CompositeBorderPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.border.DelegateBorderPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.decoration.MatteDecorationPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.fill.FractionBasedFillPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.highlight.ClassicHighlightPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.overlay.BottomLineOverlayPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.overlay.BottomShadowOverlayPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.overlay.TopBezelOverlayPainter;
|
||||||
|
import org.pushingpixels.substance.api.painter.overlay.TopLineOverlayPainter;
|
||||||
|
import org.pushingpixels.substance.api.shaper.ClassicButtonShaper;
|
||||||
|
import org.pushingpixels.substance.internal.utils.SubstanceColorUtilities;
|
||||||
|
|
||||||
|
public class ObsidianSkin extends SubstanceSkin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display name for <code>this</code> skin.
|
||||||
|
*/
|
||||||
|
private static final String NAME = "RuneLite";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new <code>RuneLite</code> skin.
|
||||||
|
*/
|
||||||
|
ObsidianSkin()
|
||||||
|
{
|
||||||
|
final SubstanceSkin.ColorSchemes schemes = SubstanceSkin
|
||||||
|
.getColorSchemes(getClass().getResource(NAME + ".colorschemes"));
|
||||||
|
final SubstanceColorScheme activeScheme = schemes.get("RuneLite Active");
|
||||||
|
final SubstanceColorScheme enabledScheme = schemes.get("RuneLite Enabled");
|
||||||
|
|
||||||
|
final SubstanceColorSchemeBundle defaultSchemeBundle = new SubstanceColorSchemeBundle(
|
||||||
|
activeScheme, enabledScheme, enabledScheme);
|
||||||
|
defaultSchemeBundle.registerColorScheme(enabledScheme, 0.6f,
|
||||||
|
ComponentState.DISABLED_UNSELECTED);
|
||||||
|
defaultSchemeBundle.registerColorScheme(activeScheme, 0.6f,
|
||||||
|
ComponentState.DISABLED_SELECTED);
|
||||||
|
|
||||||
|
// borders
|
||||||
|
final SubstanceColorScheme borderDisabledSelectedScheme = schemes
|
||||||
|
.get("RuneLite Selected Disabled Border");
|
||||||
|
final SubstanceColorScheme borderScheme = schemes.get("RuneLite Border");
|
||||||
|
defaultSchemeBundle.registerColorScheme(borderDisabledSelectedScheme,
|
||||||
|
ColorSchemeAssociationKind.BORDER, ComponentState.DISABLED_SELECTED);
|
||||||
|
defaultSchemeBundle.registerColorScheme(borderScheme, ColorSchemeAssociationKind.BORDER);
|
||||||
|
|
||||||
|
// marks
|
||||||
|
final SubstanceColorScheme markActiveScheme = schemes.get("RuneLite Mark Active");
|
||||||
|
defaultSchemeBundle.registerColorScheme(markActiveScheme, ColorSchemeAssociationKind.MARK,
|
||||||
|
ComponentState.getActiveStates());
|
||||||
|
defaultSchemeBundle.registerColorScheme(markActiveScheme, 0.6f,
|
||||||
|
ColorSchemeAssociationKind.MARK, ComponentState.DISABLED_SELECTED,
|
||||||
|
ComponentState.DISABLED_UNSELECTED);
|
||||||
|
|
||||||
|
// separators
|
||||||
|
final SubstanceColorScheme separatorScheme = schemes.get("RuneLite Separator");
|
||||||
|
defaultSchemeBundle.registerColorScheme(separatorScheme,
|
||||||
|
ColorSchemeAssociationKind.SEPARATOR);
|
||||||
|
|
||||||
|
// tab borders
|
||||||
|
defaultSchemeBundle.registerColorScheme(schemes.get("RuneLite Tab Border"),
|
||||||
|
ColorSchemeAssociationKind.TAB_BORDER, ComponentState.getActiveStates());
|
||||||
|
|
||||||
|
final SubstanceColorScheme watermarkScheme = schemes.get("RuneLite Watermark");
|
||||||
|
|
||||||
|
this.registerDecorationAreaSchemeBundle(defaultSchemeBundle, watermarkScheme,
|
||||||
|
DecorationAreaType.NONE);
|
||||||
|
|
||||||
|
final SubstanceColorSchemeBundle decorationsSchemeBundle = new SubstanceColorSchemeBundle(
|
||||||
|
activeScheme, enabledScheme, enabledScheme);
|
||||||
|
decorationsSchemeBundle.registerColorScheme(enabledScheme, 0.5f,
|
||||||
|
ComponentState.DISABLED_UNSELECTED);
|
||||||
|
|
||||||
|
// borders
|
||||||
|
decorationsSchemeBundle.registerColorScheme(borderDisabledSelectedScheme,
|
||||||
|
ColorSchemeAssociationKind.BORDER, ComponentState.DISABLED_SELECTED);
|
||||||
|
decorationsSchemeBundle.registerColorScheme(borderScheme,
|
||||||
|
ColorSchemeAssociationKind.BORDER);
|
||||||
|
|
||||||
|
// marks
|
||||||
|
decorationsSchemeBundle.registerColorScheme(markActiveScheme,
|
||||||
|
ColorSchemeAssociationKind.MARK, ComponentState.getActiveStates());
|
||||||
|
|
||||||
|
// separators
|
||||||
|
final SubstanceColorScheme separatorDecorationsScheme = schemes
|
||||||
|
.get("RuneLite Decorations Separator");
|
||||||
|
decorationsSchemeBundle.registerColorScheme(separatorDecorationsScheme,
|
||||||
|
ColorSchemeAssociationKind.SEPARATOR);
|
||||||
|
|
||||||
|
final SubstanceColorScheme decorationsWatermarkScheme = schemes
|
||||||
|
.get("RuneLite Decorations Watermark");
|
||||||
|
|
||||||
|
this.registerDecorationAreaSchemeBundle(decorationsSchemeBundle, decorationsWatermarkScheme,
|
||||||
|
DecorationAreaType.TOOLBAR, DecorationAreaType.GENERAL, DecorationAreaType.FOOTER);
|
||||||
|
|
||||||
|
final SubstanceColorSchemeBundle headerSchemeBundle = new SubstanceColorSchemeBundle(activeScheme,
|
||||||
|
enabledScheme, enabledScheme);
|
||||||
|
headerSchemeBundle.registerColorScheme(enabledScheme, 0.5f,
|
||||||
|
ComponentState.DISABLED_UNSELECTED);
|
||||||
|
|
||||||
|
// borders
|
||||||
|
final SubstanceColorScheme headerBorderScheme = schemes.get("RuneLite Header Border");
|
||||||
|
headerSchemeBundle.registerColorScheme(borderDisabledSelectedScheme,
|
||||||
|
ColorSchemeAssociationKind.BORDER, ComponentState.DISABLED_SELECTED);
|
||||||
|
headerSchemeBundle.registerColorScheme(headerBorderScheme,
|
||||||
|
ColorSchemeAssociationKind.BORDER);
|
||||||
|
// marks
|
||||||
|
headerSchemeBundle.registerColorScheme(markActiveScheme, ColorSchemeAssociationKind.MARK,
|
||||||
|
ComponentState.getActiveStates());
|
||||||
|
|
||||||
|
headerSchemeBundle.registerHighlightColorScheme(activeScheme, 0.7f,
|
||||||
|
ComponentState.ROLLOVER_UNSELECTED, ComponentState.ROLLOVER_ARMED,
|
||||||
|
ComponentState.ARMED);
|
||||||
|
headerSchemeBundle.registerHighlightColorScheme(activeScheme, 0.8f,
|
||||||
|
ComponentState.SELECTED);
|
||||||
|
headerSchemeBundle.registerHighlightColorScheme(activeScheme, 1.0f,
|
||||||
|
ComponentState.ROLLOVER_SELECTED);
|
||||||
|
|
||||||
|
final SubstanceColorScheme headerWatermarkScheme = schemes.get("RuneLite Header Watermark");
|
||||||
|
|
||||||
|
this.registerDecorationAreaSchemeBundle(headerSchemeBundle, headerWatermarkScheme,
|
||||||
|
DecorationAreaType.PRIMARY_TITLE_PANE, DecorationAreaType.SECONDARY_TITLE_PANE,
|
||||||
|
DecorationAreaType.HEADER);
|
||||||
|
|
||||||
|
setTabFadeStart(0.2);
|
||||||
|
setTabFadeEnd(0.9);
|
||||||
|
|
||||||
|
// Add overlay painters to paint drop shadows along the bottom
|
||||||
|
// edges of toolbars and footers
|
||||||
|
this.addOverlayPainter(BottomShadowOverlayPainter.getInstance(),
|
||||||
|
DecorationAreaType.TOOLBAR);
|
||||||
|
this.addOverlayPainter(BottomShadowOverlayPainter.getInstance(), DecorationAreaType.FOOTER);
|
||||||
|
|
||||||
|
// add an overlay painter to paint a dark line along the bottom
|
||||||
|
// edge of toolbars
|
||||||
|
final BottomLineOverlayPainter toolbarBottomLineOverlayPainter = new BottomLineOverlayPainter(
|
||||||
|
(SubstanceColorScheme scheme) -> scheme.getUltraDarkColor().darker());
|
||||||
|
this.addOverlayPainter(toolbarBottomLineOverlayPainter, DecorationAreaType.TOOLBAR);
|
||||||
|
|
||||||
|
// add an overlay painter to paint a dark line along the bottom
|
||||||
|
// edge of toolbars
|
||||||
|
final TopLineOverlayPainter toolbarTopLineOverlayPainter = new TopLineOverlayPainter(
|
||||||
|
(SubstanceColorScheme scheme) -> SubstanceColorUtilities
|
||||||
|
.getAlphaColor(scheme.getForegroundColor(), 32));
|
||||||
|
this.addOverlayPainter(toolbarTopLineOverlayPainter, DecorationAreaType.TOOLBAR);
|
||||||
|
|
||||||
|
// add an overlay painter to paint a bezel line along the top
|
||||||
|
// edge of footer
|
||||||
|
final TopBezelOverlayPainter footerTopBezelOverlayPainter = new TopBezelOverlayPainter(
|
||||||
|
(SubstanceColorScheme scheme) -> scheme.getUltraDarkColor().darker(),
|
||||||
|
(SubstanceColorScheme scheme) -> SubstanceColorUtilities
|
||||||
|
.getAlphaColor(scheme.getForegroundColor(), 32));
|
||||||
|
this.addOverlayPainter(footerTopBezelOverlayPainter, DecorationAreaType.FOOTER);
|
||||||
|
|
||||||
|
this.setTabFadeStart(0.18);
|
||||||
|
this.setTabFadeEnd(0.18);
|
||||||
|
|
||||||
|
// Set button shaper to use "flat" design
|
||||||
|
this.buttonShaper = new ClassicButtonShaper()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public float getCornerRadius(AbstractButton button, float insets)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.watermark = null;
|
||||||
|
this.fillPainter = new FractionBasedFillPainter("RuneLite",
|
||||||
|
new float[]{0.0f, 0.5f, 1.0f},
|
||||||
|
new ColorSchemeSingleColorQuery[]{ColorSchemeSingleColorQuery.ULTRALIGHT,
|
||||||
|
ColorSchemeSingleColorQuery.LIGHT, ColorSchemeSingleColorQuery.LIGHT});
|
||||||
|
this.decorationPainter = new MatteDecorationPainter();
|
||||||
|
this.highlightPainter = new ClassicHighlightPainter();
|
||||||
|
this.borderPainter = new CompositeBorderPainter("RuneLite", new ClassicBorderPainter(),
|
||||||
|
new DelegateBorderPainter("RuneLite Inner", new ClassicBorderPainter(), 0x40FFFFFF,
|
||||||
|
0x20FFFFFF, 0x00FFFFFF,
|
||||||
|
(SubstanceColorScheme scheme) -> scheme.tint(0.2f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayName()
|
||||||
|
{
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
* 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.skin;
|
||||||
|
|
||||||
|
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
|
||||||
|
|
||||||
|
public class SubstanceRuneLiteLookAndFeel extends SubstanceLookAndFeel
|
||||||
|
{
|
||||||
|
public SubstanceRuneLiteLookAndFeel()
|
||||||
|
{
|
||||||
|
super(new ObsidianSkin());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -128,6 +128,61 @@ public class StackFormatter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a quantity to stack size as it would
|
||||||
|
* appear in RuneScape. (with decimals)
|
||||||
|
* <p>
|
||||||
|
* This differs from quantityToRSStack in that it displays
|
||||||
|
* decimals. Ex: 27100 is 27,1k (not 27k)
|
||||||
|
* <p>
|
||||||
|
* This uses the NumberFormat singleton instead of the
|
||||||
|
* NUMBER_FORMATTER variable to ensure the UK locale.
|
||||||
|
*
|
||||||
|
* @param quantity The quantity to convert.
|
||||||
|
* @return The stack size as it would appear in RS, with decimals,
|
||||||
|
* with K after 100,000 and M after 10,000,000
|
||||||
|
*/
|
||||||
|
public static String quantityToRSDecimalStack(int quantity)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (quantity < 10_000)
|
||||||
|
{
|
||||||
|
return Integer.toString(quantity);
|
||||||
|
}
|
||||||
|
else if (quantity < 1_000_000)
|
||||||
|
{
|
||||||
|
if (quantity % 1000 == 0)
|
||||||
|
{
|
||||||
|
return quantity / 1000 + "K";
|
||||||
|
}
|
||||||
|
return NUMBER_FORMATTER.format(quantity).substring(0, Integer.toString(quantity).length() - 1) + "K";
|
||||||
|
}
|
||||||
|
else if (quantity < 10_000_000)
|
||||||
|
{
|
||||||
|
if (quantity % 1_000_000 == 0)
|
||||||
|
{
|
||||||
|
return quantity / 1_000_000 + "M";
|
||||||
|
}
|
||||||
|
return NUMBER_FORMATTER.format(quantity).substring(0, Integer.toString(quantity).length() - 4) + "M";
|
||||||
|
}
|
||||||
|
else if (quantity < 1_000_000_000)
|
||||||
|
{
|
||||||
|
if (quantity % 1_000_000 == 0)
|
||||||
|
{
|
||||||
|
return quantity / 1_000_000 + "M";
|
||||||
|
}
|
||||||
|
return NUMBER_FORMATTER.format(quantity).substring(0, Integer.toString(quantity).length() - 4) + "M";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (quantity % 1_000_000_000 == 0)
|
||||||
|
{
|
||||||
|
return quantity / 1_000_000_000 + "B";
|
||||||
|
}
|
||||||
|
return NUMBER_FORMATTER.format(quantity).substring(0, Integer.toString(quantity).length() - 7) + "B";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string representation of a stack
|
* Converts a string representation of a stack
|
||||||
* back to (close to) it's original value.
|
* back to (close to) it's original value.
|
||||||
@@ -147,8 +202,8 @@ public class StackFormatter
|
|||||||
*
|
*
|
||||||
* @param number the long number to format
|
* @param number the long number to format
|
||||||
* @return the formatted String
|
* @return the formatted String
|
||||||
* @exception ArithmeticException if rounding is needed with rounding
|
* @throws ArithmeticException if rounding is needed with rounding
|
||||||
* mode being set to RoundingMode.UNNECESSARY
|
* mode being set to RoundingMode.UNNECESSARY
|
||||||
* @see java.text.Format#format
|
* @see java.text.Format#format
|
||||||
*/
|
*/
|
||||||
public static String formatNumber(final long number)
|
public static String formatNumber(final long number)
|
||||||
@@ -161,8 +216,8 @@ public class StackFormatter
|
|||||||
*
|
*
|
||||||
* @param number the double number to format
|
* @param number the double number to format
|
||||||
* @return the formatted String
|
* @return the formatted String
|
||||||
* @exception ArithmeticException if rounding is needed with rounding
|
* @throws ArithmeticException if rounding is needed with rounding
|
||||||
* mode being set to RoundingMode.UNNECESSARY
|
* mode being set to RoundingMode.UNNECESSARY
|
||||||
* @see java.text.Format#format
|
* @see java.text.Format#format
|
||||||
*/
|
*/
|
||||||
public static String formatNumber(double number)
|
public static String formatNumber(double number)
|
||||||
|
|||||||
@@ -25,12 +25,14 @@
|
|||||||
package net.runelite.client.util;
|
package net.runelite.client.util;
|
||||||
|
|
||||||
import java.awt.AWTException;
|
import java.awt.AWTException;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import java.awt.SystemTray;
|
import java.awt.SystemTray;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.TrayIcon;
|
import java.awt.TrayIcon;
|
||||||
@@ -40,6 +42,8 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.LookupOp;
|
||||||
|
import java.awt.image.LookupTable;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@@ -59,6 +63,7 @@ import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
|||||||
import javax.swing.plaf.FontUIResource;
|
import javax.swing.plaf.FontUIResource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.client.ui.NavigationButton;
|
import net.runelite.client.ui.NavigationButton;
|
||||||
|
import net.runelite.client.ui.components.CustomScrollBarUI;
|
||||||
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
import org.pushingpixels.substance.internal.SubstanceSynapse;
|
||||||
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
|
||||||
|
|
||||||
@@ -77,8 +82,13 @@ public class SwingUtil
|
|||||||
// Force heavy-weight popups/tooltips.
|
// Force heavy-weight popups/tooltips.
|
||||||
// Prevents them from being obscured by the game applet.
|
// Prevents them from being obscured by the game applet.
|
||||||
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
|
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
|
||||||
|
ToolTipManager.sharedInstance().setInitialDelay(300);
|
||||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||||
|
|
||||||
|
UIManager.put("Button.foreground", Color.WHITE);
|
||||||
|
UIManager.put("MenuItem.foreground", Color.WHITE);
|
||||||
|
UIManager.put("ScrollBarUI", CustomScrollBarUI.class.getName());
|
||||||
|
|
||||||
// Do not render shadows under popups/tooltips.
|
// Do not render shadows under popups/tooltips.
|
||||||
// Fixes black boxes under popups that are above the game applet.
|
// Fixes black boxes under popups that are above the game applet.
|
||||||
System.setProperty("jgoodies.popupDropShadowEnabled", "false");
|
System.setProperty("jgoodies.popupDropShadowEnabled", "false");
|
||||||
@@ -88,6 +98,48 @@ public class SwingUtil
|
|||||||
System.setProperty("sun.awt.noerasebackground", "true");
|
System.setProperty("sun.awt.noerasebackground", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offsets an image in the grayscale (darkens/brightens) by an offset
|
||||||
|
*/
|
||||||
|
public static BufferedImage grayscaleOffset(BufferedImage image, int offset)
|
||||||
|
{
|
||||||
|
int numComponents = image.getColorModel().getNumComponents();
|
||||||
|
int index = numComponents - 1;
|
||||||
|
|
||||||
|
LookupTable lookup = new LookupTable(0, numComponents)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public int[] lookupPixel(int[] src, int[] dest)
|
||||||
|
{
|
||||||
|
if (dest[index] != 0)
|
||||||
|
{
|
||||||
|
dest[index] = dest[index] + offset;
|
||||||
|
if (dest[index] < 0)
|
||||||
|
{
|
||||||
|
dest[index] = 0;
|
||||||
|
}
|
||||||
|
else if (dest[index] > 255)
|
||||||
|
{
|
||||||
|
dest[index] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LookupOp op = new LookupOp(lookup, new RenderingHints(null));
|
||||||
|
return op.filter(image, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a given color to it's hexidecimal equivalent.
|
||||||
|
*/
|
||||||
|
public static String toHexColor(Color color)
|
||||||
|
{
|
||||||
|
return "#" + Integer.toHexString(color.getRGB()).substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safely sets Swing theme
|
* Safely sets Swing theme
|
||||||
*
|
*
|
||||||
@@ -210,7 +262,7 @@ public class SwingUtil
|
|||||||
result = JOptionPane.showConfirmDialog(
|
result = JOptionPane.showConfirmDialog(
|
||||||
frame,
|
frame,
|
||||||
"Are you sure you want to exit?", "Exit",
|
"Are you sure you want to exit?", "Exit",
|
||||||
JOptionPane .OK_CANCEL_OPTION,
|
JOptionPane.OK_CANCEL_OPTION,
|
||||||
JOptionPane.QUESTION_MESSAGE);
|
JOptionPane.QUESTION_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,6 +310,7 @@ public class SwingUtil
|
|||||||
: navigationButton.getIcon();
|
: navigationButton.getIcon();
|
||||||
|
|
||||||
final JButton button = new JButton();
|
final JButton button = new JButton();
|
||||||
|
button.setMaximumSize(new Dimension(30, 30));
|
||||||
button.setName(navigationButton.getName());
|
button.setName(navigationButton.getName());
|
||||||
button.setToolTipText(navigationButton.getTooltip());
|
button.setToolTipText(navigationButton.getTooltip());
|
||||||
button.setIcon(new ImageIcon(scaledImage));
|
button.setIcon(new ImageIcon(scaledImage));
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 417 B |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 388 B |
|
Before Width: | Height: | Size: 280 B After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 391 B After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 388 B |
|
Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 692 B After Width: | Height: | Size: 218 B |
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -2,4 +2,6 @@ runelite.title=RuneLite
|
|||||||
runelite.version=${project.version}
|
runelite.version=${project.version}
|
||||||
runescape.version=${rs.version}
|
runescape.version=${rs.version}
|
||||||
runelite.discord.appid=409416265891971072
|
runelite.discord.appid=409416265891971072
|
||||||
runelite.discord.invite=https://discord.gg/R4BQ8tU
|
runelite.discord.invite=https://discord.gg/R4BQ8tU
|
||||||
|
runelite.github.link=https://github.com/runelite
|
||||||
|
runelite.patreon.link=https://www.patreon.com/runelite
|
||||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,166 @@
|
|||||||
|
# Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
# Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
RuneLite Enabled {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#232323
|
||||||
|
colorExtraLight=#232323
|
||||||
|
colorLight=#232323
|
||||||
|
colorMid=#232323
|
||||||
|
colorDark=#232323
|
||||||
|
colorUltraDark=#232323
|
||||||
|
colorForeground=#C6C6C6
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Active {
|
||||||
|
kind=Light
|
||||||
|
colorUltraLight=#4e4e4e
|
||||||
|
colorExtraLight=#4e4e4e
|
||||||
|
colorLight=#4e4e4e
|
||||||
|
colorMid=#232323
|
||||||
|
colorDark=#232323
|
||||||
|
colorUltraDark=#232323
|
||||||
|
colorForeground=#000000
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Selected Disabled Border {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#191919
|
||||||
|
colorExtraLight=#191919
|
||||||
|
colorLight=#191919
|
||||||
|
colorMid=#191919
|
||||||
|
colorDark=#191919
|
||||||
|
colorUltraDark=#191919
|
||||||
|
colorForeground=#C6C6C6
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Border {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#191919
|
||||||
|
colorExtraLight=#191919
|
||||||
|
colorLight=#191919
|
||||||
|
colorMid=#191919
|
||||||
|
colorDark=#191919
|
||||||
|
colorUltraDark=#191919
|
||||||
|
colorForeground=#C6C6C6
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Tab Border {
|
||||||
|
kind=Light
|
||||||
|
colorUltraLight=#232323
|
||||||
|
colorExtraLight=#232323
|
||||||
|
colorLight=#232323
|
||||||
|
colorMid=#232323
|
||||||
|
colorDark=#232323
|
||||||
|
colorUltraDark=#232323
|
||||||
|
colorForeground=#232323
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Mark Active {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#191919
|
||||||
|
colorExtraLight=#191919
|
||||||
|
colorLight=#191919
|
||||||
|
colorMid=#191919
|
||||||
|
colorDark=#191919
|
||||||
|
colorUltraDark=#191919
|
||||||
|
colorForeground=#191919
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Highlight {
|
||||||
|
kind=Light
|
||||||
|
colorUltraLight=#C6C6C6
|
||||||
|
colorExtraLight=#C6C6C6
|
||||||
|
colorLight=#C6C6C6
|
||||||
|
colorMid=#C6C6C6
|
||||||
|
colorDark=#C6C6C6
|
||||||
|
colorUltraDark=#C6C6C6
|
||||||
|
colorForeground=#191919
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Watermark {
|
||||||
|
kind=Light
|
||||||
|
colorUltraLight=#313131
|
||||||
|
colorExtraLight=#313131
|
||||||
|
colorLight=#313131
|
||||||
|
colorMid=#313131
|
||||||
|
colorDark=#313131
|
||||||
|
colorUltraDark=#313131
|
||||||
|
colorForeground=#C6C6C6
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Decorations Watermark {
|
||||||
|
kind=Light
|
||||||
|
colorUltraLight=#1e1e1e
|
||||||
|
colorExtraLight=#1e1e1e
|
||||||
|
colorLight=#1e1e1e
|
||||||
|
colorMid=#1e1e1e
|
||||||
|
colorDark=#1e1e1e
|
||||||
|
colorUltraDark=#1e1e1e
|
||||||
|
colorForeground=#1e1e1e
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Separator {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#232323
|
||||||
|
colorExtraLight=#232323
|
||||||
|
colorLight=#232323
|
||||||
|
colorMid=#232323
|
||||||
|
colorDark=#232323
|
||||||
|
colorUltraDark=#232323
|
||||||
|
colorForeground=#232323
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Decorations Separator {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#232323
|
||||||
|
colorExtraLight=#232323
|
||||||
|
colorLight=#232323
|
||||||
|
colorMid=#232323
|
||||||
|
colorDark=#232323
|
||||||
|
colorUltraDark=#232323
|
||||||
|
colorForeground=#232323
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Header Watermark {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#1e1e1e
|
||||||
|
colorExtraLight=#1e1e1e
|
||||||
|
colorLight=#1e1e1e
|
||||||
|
colorMid=#1e1e1e
|
||||||
|
colorDark=#1e1e1e
|
||||||
|
colorUltraDark=#1e1e1e
|
||||||
|
colorForeground=#C6C6C6
|
||||||
|
}
|
||||||
|
|
||||||
|
RuneLite Header Border {
|
||||||
|
kind=Dark
|
||||||
|
colorUltraLight=#1e1e1e
|
||||||
|
colorExtraLight=#1e1e1e
|
||||||
|
colorLight=#1e1e1e
|
||||||
|
colorMid=#1e1e1e
|
||||||
|
colorDark=#1e1e1e
|
||||||
|
colorUltraDark=#1e1e1e
|
||||||
|
colorForeground=#C6C6C6
|
||||||
|
}
|
||||||
@@ -26,12 +26,39 @@ package net.runelite.client.util;
|
|||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.util.Locale;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class StackFormatterTest
|
public class StackFormatterTest
|
||||||
{
|
{
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
Locale.setDefault(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void quantityToRSDecimalStackSize()
|
||||||
|
{
|
||||||
|
assertEquals("0", StackFormatter.quantityToRSDecimalStack(0));
|
||||||
|
assertEquals("8500", StackFormatter.quantityToRSDecimalStack(8_500));
|
||||||
|
assertEquals("10K", StackFormatter.quantityToRSDecimalStack(10_000));
|
||||||
|
assertEquals("21,7K", StackFormatter.quantityToRSDecimalStack(21_700));
|
||||||
|
assertEquals("100K", StackFormatter.quantityToRSDecimalStack(100_000));
|
||||||
|
assertEquals("100,3K", StackFormatter.quantityToRSDecimalStack(100_300));
|
||||||
|
assertEquals("1M", StackFormatter.quantityToRSDecimalStack(1_000_000));
|
||||||
|
assertEquals("8,4M", StackFormatter.quantityToRSDecimalStack(8_450_000));
|
||||||
|
assertEquals("10M", StackFormatter.quantityToRSDecimalStack(10_000_000));
|
||||||
|
assertEquals("12,8M", StackFormatter.quantityToRSDecimalStack(12_800_000));
|
||||||
|
assertEquals("100M", StackFormatter.quantityToRSDecimalStack(100_000_000));
|
||||||
|
assertEquals("250,1M", StackFormatter.quantityToRSDecimalStack(250_100_000));
|
||||||
|
assertEquals("1B", StackFormatter.quantityToRSDecimalStack(1_000_000_000));
|
||||||
|
assertEquals("1,5B", StackFormatter.quantityToRSDecimalStack(1500_000_000));
|
||||||
|
assertEquals("2,1B", StackFormatter.quantityToRSDecimalStack(Integer.MAX_VALUE));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void quantityToRSStackSize()
|
public void quantityToRSStackSize()
|
||||||
|
|||||||