Hiscore Plugin redesign
Overall: - Applied new colors, positions and sizes, following issue #1342. Search: - Applied the new IconTextField, with search, error and loading indicator (and respective image files). - Blocked tabs witching while results are loading. Endpoints: - Moved the endpoints to right below the search bar (this follows a more logical sequence of usage). - Changed the endpoint presentation style and size. The selected endpoint now displays a orange underline. - Edited the endpoint icons to better fit the visual context. - Changed the way currently selected endpoint is stored. Stats: - Changed the sizing of the labels/panels. - Changed the font to a smaller version. Total/Combat: - Switched the order of the combat and total indicator - Changed the font to a smaller version. Clues/Minigames: - Changed the font to a smaller version. Details Panel: - Completely removed the details panel, instead went for a more in-line with the game approach, tooltips! - Rewrote the way skills and labels are matched - Added html progress bar to the next level
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -25,10 +26,8 @@
|
||||
package net.runelite.client.plugins.hiscore;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridLayout;
|
||||
@@ -39,29 +38,22 @@ import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.MatteBorder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Experience;
|
||||
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.components.IconTextField;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
@@ -102,13 +94,17 @@ import net.runelite.http.api.hiscore.Skill;
|
||||
@Slf4j
|
||||
public class HiscorePanel extends PluginPanel
|
||||
{
|
||||
private static final String SKILL_NAME = "SKILL_NAME";
|
||||
private static final String SKILL = "SKILL";
|
||||
/* The maximum allowed username length in runescape accounts */
|
||||
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.
|
||||
*/
|
||||
private static final Set<HiscoreSkill> SKILLS = new LinkedHashSet<>(Arrays.asList(
|
||||
private static final List<HiscoreSkill> SKILLS = ImmutableList.of(
|
||||
ATTACK, HITPOINTS, MINING,
|
||||
STRENGTH, AGILITY, SMITHING,
|
||||
DEFENCE, HERBLORE, FISHING,
|
||||
@@ -117,7 +113,7 @@ public class HiscorePanel extends PluginPanel
|
||||
MAGIC, FLETCHING, WOODCUTTING,
|
||||
RUNECRAFT, SLAYER, FARMING,
|
||||
CONSTRUCTION, HUNTER
|
||||
));
|
||||
);
|
||||
|
||||
@Inject
|
||||
ScheduledExecutorService executor;
|
||||
@@ -132,24 +128,45 @@ public class HiscorePanel extends PluginPanel
|
||||
private final List<JLabel> skillLabels = new ArrayList<>();
|
||||
|
||||
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 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
|
||||
public HiscorePanel(HiscoreConfig config)
|
||||
{
|
||||
super();
|
||||
this.config = config;
|
||||
|
||||
// Panel "constants"
|
||||
// This was an EtchedBorder, but the style would change when the window was maximized.
|
||||
Border subPanelBorder = BorderFactory.createLineBorder(this.getBackground().brighter(), 2);
|
||||
setBorder(new EmptyBorder(10, 10, 0, 10));
|
||||
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
|
||||
// Create GBL to arrange sub items
|
||||
GridBagLayout gridBag = new GridBagLayout();
|
||||
@@ -160,28 +177,11 @@ public class HiscorePanel extends PluginPanel
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.anchor = GridBagConstraints.NORTH;
|
||||
|
||||
// Search box
|
||||
JPanel inputPanel = new JPanel();
|
||||
inputPanel.setLayout(new BorderLayout(7, 7));
|
||||
inputPanel.setBorder(subPanelBorder);
|
||||
|
||||
ImageIcon 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.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.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@@ -192,7 +192,6 @@ public class HiscorePanel extends PluginPanel
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
return;
|
||||
@@ -206,97 +205,20 @@ public class HiscorePanel extends PluginPanel
|
||||
}
|
||||
}
|
||||
});
|
||||
inputPanel.add(input, BorderLayout.CENTER);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.weightx = 1;
|
||||
c.weighty = 0;
|
||||
c.insets = new Insets(0, 0, 3, 0);
|
||||
gridBag.setConstraints(inputPanel, c);
|
||||
add(inputPanel);
|
||||
|
||||
// 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);
|
||||
c.insets = new Insets(0, 0, 10, 0);
|
||||
gridBag.setConstraints(input, c);
|
||||
add(input);
|
||||
|
||||
/* The container for all the endpoint selectors */
|
||||
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())
|
||||
{
|
||||
try
|
||||
@@ -307,25 +229,32 @@ public class HiscorePanel extends PluginPanel
|
||||
iconImage = ImageIO.read(HiscorePanel.class.getResourceAsStream(
|
||||
endpoint.name().toLowerCase() + ".png"));
|
||||
}
|
||||
JToggleButton button = new JToggleButton();
|
||||
button.setIcon(new ImageIcon(iconImage));
|
||||
button.setPreferredSize(new Dimension(24, 24));
|
||||
button.setBackground(Color.WHITE);
|
||||
button.setFocusPainted(false);
|
||||
button.setActionCommand(endpoint.name());
|
||||
button.setToolTipText(endpoint.getName() + " Hiscores");
|
||||
button.addActionListener((e -> executor.execute(this::lookup)));
|
||||
button.addMouseListener(new MouseAdapter()
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
JLabel label = new JLabel();
|
||||
|
||||
label.setIcon(new ImageIcon(iconImage));
|
||||
|
||||
panel.add(label);
|
||||
panel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
panel.setToolTipText(endpoint.getName() + " Hiscores");
|
||||
panel.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
if (loading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
executor.execute(HiscorePanel.this::lookup);
|
||||
selectedEndPoint = endpoint;
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
endpointButtons.add(button);
|
||||
endpointButtonGroup.add(button);
|
||||
endpointPanel.add(button);
|
||||
|
||||
endPoints.add(panel);
|
||||
endpointPanel.add(panel);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
@@ -333,156 +262,61 @@ public class HiscorePanel extends PluginPanel
|
||||
}
|
||||
}
|
||||
|
||||
endpointButtons.get(0).setSelected(true);
|
||||
endpointButtons.get(0).setBackground(Color.CYAN);
|
||||
/* Default endpoint is the general (normal) endpoint */
|
||||
selectedEndPoint = HiscoreEndpoint.NORMAL;
|
||||
updateButtons();
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 5;
|
||||
// Last item has a nonzero weighty so it will expand to fill vertical space
|
||||
c.weighty = 1;
|
||||
c.gridy = 1;
|
||||
gridBag.setConstraints(endpointPanel, c);
|
||||
add(endpointPanel);
|
||||
}
|
||||
|
||||
void addInputKeyListener(KeyListener l)
|
||||
{
|
||||
this.input.addKeyListener(l);
|
||||
}
|
||||
// Panel that holds skill icons
|
||||
GridLayout stats = new GridLayout(8, 3);
|
||||
statsPanel.setLayout(stats);
|
||||
statsPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
statsPanel.setBorder(new EmptyBorder(5, 0, 5, 0));
|
||||
|
||||
void removeInputKeyListener(KeyListener l)
|
||||
{
|
||||
this.input.removeKeyListener(l);
|
||||
}
|
||||
|
||||
private void changeDetail(String skillName, HiscoreSkill skill)
|
||||
{
|
||||
if (result == null || result.getPlayer() == null)
|
||||
// For each skill on the ingame skill panel, create a Label and add it to the UI
|
||||
for (HiscoreSkill skill : SKILLS)
|
||||
{
|
||||
return;
|
||||
JPanel panel = makeSkillPanel(skill);
|
||||
panel.setOpaque(false);
|
||||
statsPanel.add(panel);
|
||||
}
|
||||
|
||||
String text;
|
||||
int progress = -1;
|
||||
switch (skillName)
|
||||
{
|
||||
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;
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
gridBag.setConstraints(statsPanel, c);
|
||||
add(statsPanel);
|
||||
|
||||
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;
|
||||
double xpGoal = xpForNextLevel != -1 ? xpForNextLevel - xpForCurrentLevel : 100;
|
||||
progress = (int) ((xpGained / xpGoal) * 100f);
|
||||
totalPanel.add(makeSkillPanel(null)); //combat has no hiscore skill, refered to as null
|
||||
totalPanel.add(makeSkillPanel(OVERALL));
|
||||
|
||||
}
|
||||
text = "Skill: " + skillName + System.lineSeparator()
|
||||
+ "Rank: " + rank + System.lineSeparator()
|
||||
+ "Experience: " + exp + System.lineSeparator()
|
||||
+ "Remaining XP: " + remainingXp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c.gridx = 0;
|
||||
c.gridy = 3;
|
||||
gridBag.setConstraints(totalPanel, c);
|
||||
add(totalPanel);
|
||||
|
||||
details.setFont(UIManager.getFont("Label.font"));
|
||||
details.setText(text);
|
||||
JPanel minigamePanel = new JPanel();
|
||||
// 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)
|
||||
{
|
||||
progressBar.setVisible(true);
|
||||
progressBar.setValue(progress);
|
||||
progressBar.setBackground(Color.getHSBColor((progress / 100.f) * (120.f / 360.f), 1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.setVisible(false);
|
||||
}
|
||||
minigamePanel.add(makeSkillPanel(CLUE_SCROLL_ALL));
|
||||
minigamePanel.add(makeSkillPanel(LAST_MAN_STANDING));
|
||||
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_ROGUE));
|
||||
minigamePanel.add(makeSkillPanel(BOUNTY_HUNTER_HUNTER));
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 4;
|
||||
gridBag.setConstraints(minigamePanel, c);
|
||||
add(minigamePanel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -492,16 +326,14 @@ public class HiscorePanel extends PluginPanel
|
||||
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();
|
||||
label.setFont(FontManager.getRunescapeSmallFont());
|
||||
label.setText("--");
|
||||
|
||||
// Store the skill that the label displays so we can tell them apart
|
||||
label.putClientProperty(SKILL_NAME, skillName);
|
||||
label.putClientProperty(SKILL, skill);
|
||||
|
||||
String skillIcon = "skill_icons_small/" + skillName.toLowerCase() + ".png";
|
||||
String skillIcon = "skill_icons_small/" + (skill == null ? "combat" : skill.getName().toLowerCase()) + ".png";
|
||||
log.debug("Loading skill icon from {}", skillIcon);
|
||||
|
||||
try
|
||||
@@ -518,36 +350,31 @@ public class HiscorePanel extends PluginPanel
|
||||
log.warn(null, ex);
|
||||
}
|
||||
|
||||
// Show skill details on hover
|
||||
label.addMouseListener(new MouseInputAdapter()
|
||||
{
|
||||
@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);
|
||||
boolean totalLabel = skill == HiscoreSkill.OVERALL || skill == null; //overall or combat
|
||||
label.setIconTextGap(totalLabel ? 10 : 4);
|
||||
|
||||
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));
|
||||
|
||||
return skillPanel;
|
||||
}
|
||||
|
||||
public void lookup(String username)
|
||||
{
|
||||
input.setText(username);
|
||||
|
||||
selectedEndPoint = HiscoreEndpoint.NORMAL; //reset the endpoint to regular player
|
||||
updateButtons();
|
||||
|
||||
lookup();
|
||||
}
|
||||
|
||||
private void lookup()
|
||||
{
|
||||
String lookup = input.getText();
|
||||
details.setText("Loading...");
|
||||
progressBar.setVisible(false);
|
||||
|
||||
lookup = sanitize(lookup);
|
||||
|
||||
@@ -556,32 +383,66 @@ public class HiscorePanel extends PluginPanel
|
||||
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)
|
||||
{
|
||||
label.setText("--");
|
||||
}
|
||||
|
||||
// if for some reason no endpoint was selected, default to normal
|
||||
if (selectedEndPoint == null)
|
||||
{
|
||||
selectedEndPoint = HiscoreEndpoint.NORMAL;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HiscoreEndpoint endpoint = HiscoreEndpoint.valueOf(endpointButtonGroup.getSelection().getActionCommand());
|
||||
log.debug("Hiscore endpoint " + endpoint.name() + " selected");
|
||||
|
||||
result = hiscoreClient.lookup(lookup, endpoint);
|
||||
log.debug("Hiscore endpoint " + selectedEndPoint.name() + " selected");
|
||||
result = hiscoreClient.lookup(lookup, selectedEndPoint);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.warn("Error fetching Hiscore data " + ex.getMessage());
|
||||
details.setText("Error fetching Hiscore data");
|
||||
progressBar.setVisible(false);
|
||||
input.setIcon(ERROR_ICON);
|
||||
input.setEditable(true);
|
||||
loading = false;
|
||||
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)
|
||||
{
|
||||
String skillName = (String) label.getClientProperty(SKILL_NAME);
|
||||
HiscoreSkill skill = (HiscoreSkill) label.getClientProperty(SKILL);
|
||||
HiscoreSkill skill = find(index);
|
||||
|
||||
if (skillName.equals("Combat"))
|
||||
if (skill == null)
|
||||
{
|
||||
if (result.getPlayer() != null)
|
||||
{
|
||||
@@ -600,7 +461,6 @@ public class HiscorePanel extends PluginPanel
|
||||
else if (result.getSkill(skill) != null && result.getSkill(skill).getRank() != -1)
|
||||
{
|
||||
Skill s = result.getSkill(skill);
|
||||
|
||||
int level;
|
||||
if (config.virtualLevels() && SKILLS.contains(skill))
|
||||
{
|
||||
@@ -613,12 +473,191 @@ public class HiscorePanel extends PluginPanel
|
||||
|
||||
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
|
||||
details.setFont(UIManager.getFont("Label.font").deriveFont(Font.ITALIC));
|
||||
details.setText("Hover over a skill for details");
|
||||
progressBar.setVisible(false);
|
||||
switch (index - SKILLS.size())
|
||||
{
|
||||
case 0:
|
||||
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)
|
||||
@@ -626,20 +665,18 @@ public class HiscorePanel extends PluginPanel
|
||||
return lookup.replace('\u00A0', ' ');
|
||||
}
|
||||
|
||||
/*
|
||||
When an endpoint gets selected, this method will correctly display the selected one
|
||||
with an orange underline.
|
||||
*/
|
||||
private void updateButtons()
|
||||
{
|
||||
for (JToggleButton button : endpointButtons)
|
||||
for (JPanel panel : endPoints)
|
||||
{
|
||||
Color color;
|
||||
if (button.isSelected())
|
||||
{
|
||||
color = Color.CYAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Color.WHITE;
|
||||
}
|
||||
button.setBackground(color);
|
||||
panel.setBorder(new EmptyBorder(0, 0, 1, 0));
|
||||
}
|
||||
|
||||
int selectedIndex = selectedEndPoint.ordinal();
|
||||
endPoints.get(selectedIndex).setBorder(new MatteBorder(0, 0, 1, 0, ColorScheme.BRAND_ORANGE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ 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;
|
||||
@@ -129,6 +130,16 @@ public class IconTextField extends JPanel
|
||||
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)
|
||||
|
||||
@@ -79,6 +79,7 @@ public class SwingUtil
|
||||
// Force heavy-weight popups/tooltips.
|
||||
// Prevents them from being obscured by the game applet.
|
||||
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
|
||||
ToolTipManager.sharedInstance().setInitialDelay(300);
|
||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||
|
||||
UIManager.put("Button.foreground", Color.WHITE);
|
||||
|
||||
|
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 |