xp tracker: show on canvas
Co-authored-by: Jasper Ketelaar <Jasperketelaar@kpnmail.nl>
This commit is contained in:
@@ -67,6 +67,9 @@ class XpInfoBox extends JPanel
|
||||
private static final String HTML_LABEL_TEMPLATE =
|
||||
"<html><body style='color:%s'>%s<span style='color:white'>%s</span></body></html>";
|
||||
|
||||
private static final String REMOVE_STATE = "Remove from canvas";
|
||||
private static final String ADD_STATE = "Add to canvas";
|
||||
|
||||
// Instance members
|
||||
private final JPanel panel;
|
||||
|
||||
@@ -89,6 +92,7 @@ class XpInfoBox extends JPanel
|
||||
private final JLabel expLeft = new JLabel();
|
||||
private final JLabel actionsLeft = new JLabel();
|
||||
private final JMenuItem pauseSkill = new JMenuItem("Pause");
|
||||
private final JMenuItem canvasItem = new JMenuItem(ADD_STATE);
|
||||
|
||||
private final XpTrackerConfig xpTrackerConfig;
|
||||
|
||||
@@ -128,6 +132,21 @@ class XpInfoBox extends JPanel
|
||||
popupMenu.add(reset);
|
||||
popupMenu.add(resetOthers);
|
||||
popupMenu.add(pauseSkill);
|
||||
popupMenu.add(canvasItem);
|
||||
|
||||
canvasItem.addActionListener(e ->
|
||||
{
|
||||
if (canvasItem.getText().equals(REMOVE_STATE))
|
||||
{
|
||||
xpTrackerPlugin.removeOverlay(skill);
|
||||
canvasItem.setText(ADD_STATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
xpTrackerPlugin.addOverlay(skill);
|
||||
canvasItem.setText(REMOVE_STATE);
|
||||
}
|
||||
});
|
||||
|
||||
JLabel skillIcon = new JLabel(new ImageIcon(iconManager.getSkillImage(skill)));
|
||||
skillIcon.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
@@ -177,6 +196,7 @@ class XpInfoBox extends JPanel
|
||||
|
||||
void reset()
|
||||
{
|
||||
canvasItem.setText(ADD_STATE);
|
||||
container.remove(statsPanel);
|
||||
panel.remove(this);
|
||||
panel.revalidate();
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jasper Ketelaar <Jasper0781@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.plugins.xptracker;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.components.ComponentOrientation;
|
||||
import net.runelite.client.ui.overlay.components.ImageComponent;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.ProgressBarComponent;
|
||||
import net.runelite.client.ui.overlay.components.SplitComponent;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
|
||||
class XpInfoBoxOverlay extends Overlay
|
||||
{
|
||||
private static final int PANEL_PREFERRED_WIDTH = 150;
|
||||
private static final int BORDER_SIZE = 2;
|
||||
private static final int XP_AND_PROGRESS_BAR_GAP = 2;
|
||||
private static final int XP_AND_ICON_GAP = 4;
|
||||
private static final Rectangle XP_AND_ICON_COMPONENT_BORDER = new Rectangle(2, 1, 4, 0);
|
||||
|
||||
private final PanelComponent panel = new PanelComponent();
|
||||
private final PanelComponent iconXpSplitPanel = new PanelComponent();
|
||||
private final XpTrackerPlugin plugin;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Skill skill;
|
||||
private final BufferedImage icon;
|
||||
|
||||
XpInfoBoxOverlay(
|
||||
XpTrackerPlugin plugin,
|
||||
Skill skill,
|
||||
BufferedImage icon)
|
||||
{
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
this.skill = skill;
|
||||
this.icon = icon;
|
||||
panel.setBorder(new Rectangle(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||
panel.setGap(new Point(0, XP_AND_PROGRESS_BAR_GAP));
|
||||
panel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0));
|
||||
iconXpSplitPanel.setBorder(XP_AND_ICON_COMPONENT_BORDER);
|
||||
iconXpSplitPanel.setBackgroundColor(null);
|
||||
iconXpSplitPanel.setPreferredSize(new Dimension(PANEL_PREFERRED_WIDTH, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
panel.getChildren().clear();
|
||||
iconXpSplitPanel.getChildren().clear();
|
||||
|
||||
//Setting the font to rs small font so that the overlay isn't huge
|
||||
graphics.setFont(FontManager.getRunescapeSmallFont());
|
||||
|
||||
final XpSnapshotSingle snapshot = plugin.getSkillSnapshot(skill);
|
||||
|
||||
final LineComponent xpLine = LineComponent.builder()
|
||||
.left("XP Gained:")
|
||||
.right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpGainedInSession()))
|
||||
.build();
|
||||
|
||||
final LineComponent xpHour = LineComponent.builder()
|
||||
.left("XP/Hour:")
|
||||
.right(StackFormatter.quantityToRSDecimalStack(snapshot.getXpPerHour()))
|
||||
.build();
|
||||
|
||||
final SplitComponent xpSplit = SplitComponent.builder()
|
||||
.first(xpLine)
|
||||
.second(xpHour)
|
||||
.orientation(ComponentOrientation.VERTICAL)
|
||||
.build();
|
||||
|
||||
final ImageComponent imageComponent = new ImageComponent(icon);
|
||||
final SplitComponent iconXpSplit = SplitComponent.builder()
|
||||
.first(imageComponent)
|
||||
.second(xpSplit)
|
||||
.orientation(ComponentOrientation.HORIZONTAL)
|
||||
.gap(new Point(XP_AND_ICON_GAP, 0))
|
||||
.build();
|
||||
|
||||
iconXpSplitPanel.getChildren().add(iconXpSplit);
|
||||
|
||||
final ProgressBarComponent progressBarComponent = new ProgressBarComponent();
|
||||
progressBarComponent.setValue(snapshot.getSkillProgressToGoal());
|
||||
|
||||
panel.getChildren().add(iconXpSplitPanel);
|
||||
panel.getChildren().add(progressBarComponent);
|
||||
|
||||
return panel.render(graphics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return super.getName() + skill.getName();
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,7 @@ import static net.runelite.client.plugins.xptracker.XpWorldType.NORMAL;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.ui.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.http.api.xp.XpClient;
|
||||
|
||||
@@ -98,6 +99,9 @@ public class XpTrackerPlugin extends Plugin
|
||||
@Inject
|
||||
private NPCManager npcManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
private NavigationButton navButton;
|
||||
private XpPanel xpPanel;
|
||||
private XpWorldType lastWorldType;
|
||||
@@ -142,6 +146,7 @@ public class XpTrackerPlugin extends Plugin
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay);
|
||||
xpState.reset();
|
||||
clientToolbar.removeNavigation(navButton);
|
||||
}
|
||||
@@ -208,6 +213,27 @@ public class XpTrackerPlugin extends Plugin
|
||||
return xpType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an overlay to the canvas for tracking a specific skill.
|
||||
*
|
||||
* @param skill the skill for which the overlay should be added
|
||||
*/
|
||||
void addOverlay(Skill skill)
|
||||
{
|
||||
removeOverlay(skill);
|
||||
overlayManager.add(new XpInfoBoxOverlay(this, skill, skillIconManager.getSkillImage(skill)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an overlay from the overlayManager if it's present.
|
||||
*
|
||||
* @param skill the skill for which the overlay should be removed.
|
||||
*/
|
||||
void removeOverlay(Skill skill)
|
||||
{
|
||||
overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay && ((XpInfoBoxOverlay) e).getSkill() == skill);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset internal state and re-initialize all skills with XP currently cached by the RS client
|
||||
* This is called by the user manually clicking resetSkillState in the UI.
|
||||
@@ -230,6 +256,7 @@ public class XpTrackerPlugin extends Plugin
|
||||
}
|
||||
|
||||
xpState.initializeSkill(skill, currentXp);
|
||||
removeOverlay(skill);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +269,7 @@ public class XpTrackerPlugin extends Plugin
|
||||
xpState.reset();
|
||||
xpPanel.resetAllInfoBoxes();
|
||||
xpPanel.updateTotal(new XpSnapshotSingle.XpSnapshotSingleBuilder().build());
|
||||
overlayManager.removeIf(e -> e instanceof XpInfoBoxOverlay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,6 +282,7 @@ public class XpTrackerPlugin extends Plugin
|
||||
int currentXp = client.getSkillExperience(skill);
|
||||
xpState.resetSkill(skill, currentXp);
|
||||
xpPanel.resetSkill(skill);
|
||||
removeOverlay(skill);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +301,6 @@ public class XpTrackerPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onExperienceChanged(ExperienceChanged event)
|
||||
{
|
||||
|
||||
@@ -58,9 +58,8 @@ public class SplitComponent implements LayoutableRenderableEntity
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
graphics.translate(preferredLocation.x, preferredLocation.y);
|
||||
first.setPreferredLocation(preferredLocation);
|
||||
first.setPreferredSize(preferredSize);
|
||||
first.setPreferredLocation(new Point(0, 0));
|
||||
|
||||
final Dimension firstDimension = first.render(graphics);
|
||||
int x = 0, y = 0;
|
||||
@@ -74,7 +73,7 @@ public class SplitComponent implements LayoutableRenderableEntity
|
||||
x = firstDimension.width + gap.x;
|
||||
}
|
||||
|
||||
second.setPreferredLocation(new Point(x, y));
|
||||
second.setPreferredLocation(new Point(x + preferredLocation.x, y + preferredLocation.y));
|
||||
// Make the second component fit to whatever size is left after the first component is rendered
|
||||
second.setPreferredSize(new Dimension(preferredSize.width - x, preferredSize.height - y));
|
||||
|
||||
@@ -95,8 +94,6 @@ public class SplitComponent implements LayoutableRenderableEntity
|
||||
totalWidth = x + secondDimension.width;
|
||||
}
|
||||
|
||||
graphics.translate(-preferredLocation.x, -preferredLocation.y);
|
||||
|
||||
final Dimension dimension = new Dimension(totalWidth, totalHeight);
|
||||
bounds.setLocation(preferredLocation);
|
||||
bounds.setSize(dimension);
|
||||
|
||||
Reference in New Issue
Block a user