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
This commit is contained in:
Ruben Amendoeira
2018-04-22 04:39:05 +01:00
parent ab7e969320
commit d0f708e26a
8 changed files with 374 additions and 325 deletions

View File

@@ -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));
}
}
}

View File

@@ -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)

View File

@@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 14 KiB