340 lines
10 KiB
Java
340 lines
10 KiB
Java
package com.example.essentialsplus.ui;
|
|||
|
|
|
||
|
|
import com.example.essentialsplus.data.AccountData;
|
||
|
|
import java.awt.BorderLayout;
|
||
|
|
import java.awt.Component;
|
||
|
|
import java.awt.Cursor;
|
||
|
|
import java.awt.Dimension;
|
||
|
|
import java.awt.FlowLayout;
|
||
|
|
import java.awt.GridBagConstraints;
|
||
|
|
import java.awt.GridBagLayout;
|
||
|
|
import java.awt.Insets;
|
||
|
|
import java.awt.event.WindowAdapter;
|
||
|
|
import java.awt.event.WindowEvent;
|
||
|
|
import java.util.ArrayList;
|
||
|
|
import java.util.List;
|
||
|
|
import java.util.Objects;
|
||
|
|
import javax.swing.BorderFactory;
|
||
|
|
import javax.swing.DefaultListCellRenderer;
|
||
|
|
import javax.swing.JButton;
|
||
|
|
import javax.swing.JComboBox;
|
||
|
|
import javax.swing.JComponent;
|
||
|
|
import javax.swing.JFrame;
|
||
|
|
import javax.swing.JLabel;
|
||
|
|
import javax.swing.JList;
|
||
|
|
import javax.swing.JPanel;
|
||
|
|
import javax.swing.JScrollPane;
|
||
|
|
import javax.swing.ScrollPaneConstants;
|
||
|
|
import javax.swing.WindowConstants;
|
||
|
|
import net.runelite.client.ui.DynamicGridLayout;
|
||
|
|
import net.runelite.client.ui.FontManager;
|
||
|
|
|
||
|
|
/** Large resizable analysis window with its own character selection. */
|
||
|
|
class WealthPopout extends JFrame
|
||
|
|
{
|
||
|
|
static final String AUTO = "__logged_in__";
|
||
|
|
|
||
|
|
private final WealthPanel panel;
|
||
|
|
private final WealthPanel.DetailView view;
|
||
|
|
private final Segmented rangeBar;
|
||
|
|
private final Segmented styleBar;
|
||
|
|
private final JComboBox<Choice> characterBox = new JComboBox<>();
|
||
|
|
private final JLabel sessionLabel = new JLabel();
|
||
|
|
private String choice = AUTO;
|
||
|
|
private String resolved = WealthPanel.ALL;
|
||
|
|
private List<String> comboKeys = new ArrayList<>();
|
||
|
|
private boolean updatingCombo;
|
||
|
|
|
||
|
|
private static final class Choice
|
||
|
|
{
|
||
|
|
final String key;
|
||
|
|
final String label;
|
||
|
|
|
||
|
|
Choice(String key, String label)
|
||
|
|
{
|
||
|
|
this.key = key;
|
||
|
|
this.label = label;
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public String toString()
|
||
|
|
{
|
||
|
|
return label;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
WealthPopout(WealthPanel panel, TimeRange range, Runnable onClose)
|
||
|
|
{
|
||
|
|
super("Wealth Tracker");
|
||
|
|
this.panel = panel;
|
||
|
|
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
|
||
|
|
addWindowListener(new WindowAdapter()
|
||
|
|
{
|
||
|
|
@Override
|
||
|
|
public void windowClosed(WindowEvent e)
|
||
|
|
{
|
||
|
|
onClose.run();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
view = new WealthPanel.DetailView(panel.getIcons(), true);
|
||
|
|
view.main.setMode(panel.getMainMode());
|
||
|
|
view.breakdown.setOnOpen((v, label) -> panel.openItems(v, label, resolved));
|
||
|
|
rangeBar = Segmented.ranges(range, panel::setRange);
|
||
|
|
rangeBar.setSelected(panel.isCustomSessionView() ? -1 : range.ordinal());
|
||
|
|
styleBar = new Segmented(new String[]{"Line", "Candles"}, panel.getMainMode() == WealthChart.Mode.CANDLES ? 1 : 0,
|
||
|
|
i -> panel.setMainMode(i == 1 ? WealthChart.Mode.CANDLES : WealthChart.Mode.LINE));
|
||
|
|
|
||
|
|
java.awt.event.MouseAdapter popoutRightClick = new java.awt.event.MouseAdapter()
|
||
|
|
{
|
||
|
|
@Override
|
||
|
|
public void mousePressed(java.awt.event.MouseEvent e)
|
||
|
|
{
|
||
|
|
if (e.isPopupTrigger())
|
||
|
|
{
|
||
|
|
showPopup(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void mouseReleased(java.awt.event.MouseEvent e)
|
||
|
|
{
|
||
|
|
if (e.isPopupTrigger())
|
||
|
|
{
|
||
|
|
showPopup(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void showPopup(java.awt.event.MouseEvent e)
|
||
|
|
{
|
||
|
|
if (!panel.isHourly())
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
javax.swing.JPopupMenu menu = new javax.swing.JPopupMenu();
|
||
|
|
javax.swing.JMenuItem reset = new javax.swing.JMenuItem("Reset Hourly");
|
||
|
|
reset.addActionListener(a ->
|
||
|
|
{
|
||
|
|
panel.resetHourly(resolved);
|
||
|
|
panel.refreshLater();
|
||
|
|
});
|
||
|
|
menu.add(reset);
|
||
|
|
menu.show((java.awt.Component) e.getSource(), e.getX(), e.getY());
|
||
|
|
}
|
||
|
|
};
|
||
|
|
view.main.addMouseListener(popoutRightClick);
|
||
|
|
view.stats.addMouseListener(popoutRightClick);
|
||
|
|
|
||
|
|
characterBox.setFont(FontManager.getRunescapeBoldFont());
|
||
|
|
characterBox.setBackground(Ui.CARD);
|
||
|
|
characterBox.setForeground(Ui.TEXT);
|
||
|
|
characterBox.setFocusable(false);
|
||
|
|
characterBox.setPreferredSize(new Dimension(260, 30));
|
||
|
|
characterBox.setRenderer(new DefaultListCellRenderer()
|
||
|
|
{
|
||
|
|
@Override
|
||
|
|
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus)
|
||
|
|
{
|
||
|
|
JLabel l = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||
|
|
l.setFont(FontManager.getRunescapeBoldFont());
|
||
|
|
l.setBorder(BorderFactory.createEmptyBorder(3, 8, 3, 8));
|
||
|
|
return l;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
characterBox.addActionListener(e ->
|
||
|
|
{
|
||
|
|
if (updatingCombo)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
Choice c = (Choice) characterBox.getSelectedItem();
|
||
|
|
if (c != null)
|
||
|
|
{
|
||
|
|
choice = c.key;
|
||
|
|
panel.refreshLater();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
JPanel root = new JPanel(new BorderLayout(12, 10));
|
||
|
|
root.setBackground(Ui.BG);
|
||
|
|
root.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
|
||
|
|
|
||
|
|
// ---- top bar
|
||
|
|
JPanel top = new JPanel(new BorderLayout(12, 0));
|
||
|
|
top.setOpaque(false);
|
||
|
|
JPanel left = new JPanel(new FlowLayout(FlowLayout.LEFT, 12, 0));
|
||
|
|
left.setOpaque(false);
|
||
|
|
view.title.setFont(FontManager.getRunescapeBoldFont().deriveFont(24f));
|
||
|
|
view.title.setForeground(Ui.ACCENT);
|
||
|
|
left.add(view.title);
|
||
|
|
left.add(characterBox);
|
||
|
|
top.add(left, BorderLayout.WEST);
|
||
|
|
|
||
|
|
JPanel controls = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
|
||
|
|
controls.setOpaque(false);
|
||
|
|
sessionLabel.setFont(FontManager.getRunescapeFont());
|
||
|
|
sessionLabel.setForeground(Ui.MUTED);
|
||
|
|
controls.add(sessionLabel);
|
||
|
|
controls.add(button("Session", panel::showSession));
|
||
|
|
controls.add(button("New session", panel::newSession));
|
||
|
|
styleBar.setPreferredSize(new Dimension(150, 30));
|
||
|
|
rangeBar.setPreferredSize(new Dimension(380, 30));
|
||
|
|
controls.add(styleBar);
|
||
|
|
controls.add(rangeBar);
|
||
|
|
top.add(controls, BorderLayout.EAST);
|
||
|
|
root.add(top, BorderLayout.NORTH);
|
||
|
|
|
||
|
|
// ---- charts
|
||
|
|
JPanel charts = new JPanel(new GridBagLayout());
|
||
|
|
charts.setOpaque(false);
|
||
|
|
int row = 0;
|
||
|
|
row = addChart(charts, row, "NET WORTH", view.main, 0.5);
|
||
|
|
row = addChart(charts, row, "CHANGE PER PERIOD", view.bars, 0.2);
|
||
|
|
addChart(charts, row, "COMPOSITION", view.stacked, 0.3);
|
||
|
|
root.add(charts, BorderLayout.CENTER);
|
||
|
|
|
||
|
|
// ---- side column
|
||
|
|
JPanel side = new JPanel(new DynamicGridLayout(0, 1, 0, 6));
|
||
|
|
side.setBackground(Ui.BG);
|
||
|
|
side.add(label("STATISTICS"));
|
||
|
|
side.add(view.stats);
|
||
|
|
side.add(label("BREAKDOWN (click to view items)"));
|
||
|
|
JPanel viewButtons = new JPanel(new java.awt.GridLayout(1, 4, 4, 0));
|
||
|
|
viewButtons.setOpaque(false);
|
||
|
|
viewButtons.add(button("Bank", () -> panel.openItems("bank", "Bank", resolved)));
|
||
|
|
viewButtons.add(button("Inventory", () -> panel.openItems("inventory", "Inventory", resolved)));
|
||
|
|
viewButtons.add(button("Equipment", () -> panel.openItems("equipment", "Equipment", resolved)));
|
||
|
|
viewButtons.add(button("GE", () -> panel.openItems("ge", "Grand Exchange", resolved)));
|
||
|
|
side.add(viewButtons);
|
||
|
|
side.add(view.breakdown);
|
||
|
|
side.add(label("WHAT CHANGED"));
|
||
|
|
side.add(view.movers);
|
||
|
|
side.add(label("MOST VALUABLE"));
|
||
|
|
side.add(view.topItems);
|
||
|
|
|
||
|
|
JPanel sideWrap = new JPanel(new BorderLayout());
|
||
|
|
sideWrap.setBackground(Ui.BG);
|
||
|
|
sideWrap.add(side, BorderLayout.NORTH);
|
||
|
|
JScrollPane scroll = new JScrollPane(sideWrap, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||
|
|
scroll.setBorder(null);
|
||
|
|
scroll.getVerticalScrollBar().setUnitIncrement(16);
|
||
|
|
scroll.setPreferredSize(new Dimension(340, 10));
|
||
|
|
root.add(scroll, BorderLayout.EAST);
|
||
|
|
|
||
|
|
setContentPane(root);
|
||
|
|
setSize(1600, 900);
|
||
|
|
setMinimumSize(new Dimension(900, 560));
|
||
|
|
setLocationRelativeTo(panel);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int addChart(JPanel charts, int row, String title, JComponent chart, double weight)
|
||
|
|
{
|
||
|
|
GridBagConstraints c = new GridBagConstraints();
|
||
|
|
c.gridx = 0;
|
||
|
|
c.fill = GridBagConstraints.BOTH;
|
||
|
|
c.weightx = 1;
|
||
|
|
c.gridy = row;
|
||
|
|
c.weighty = 0;
|
||
|
|
c.insets = new Insets(row == 0 ? 0 : 8, 0, 4, 0);
|
||
|
|
charts.add(label(title), c);
|
||
|
|
c.gridy = row + 1;
|
||
|
|
c.weighty = weight;
|
||
|
|
c.insets = new Insets(0, 0, 0, 0);
|
||
|
|
chart.setPreferredSize(new Dimension(10, 60));
|
||
|
|
charts.add(chart, c);
|
||
|
|
return row + 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Character shown in this window: the logged-in one by default, or the one picked in the box. */
|
||
|
|
String resolveSelection(List<AccountData> accounts, String activeKey)
|
||
|
|
{
|
||
|
|
if (AUTO.equals(choice))
|
||
|
|
{
|
||
|
|
if (activeKey != null && accounts.stream().anyMatch(a -> a.key.equals(activeKey)))
|
||
|
|
{
|
||
|
|
resolved = activeKey;
|
||
|
|
}
|
||
|
|
else if (accounts.stream().noneMatch(a -> a.key.equals(resolved)))
|
||
|
|
{
|
||
|
|
resolved = WealthPanel.ALL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (WealthPanel.ALL.equals(choice) || accounts.stream().anyMatch(a -> a.key.equals(choice)))
|
||
|
|
{
|
||
|
|
resolved = choice;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
choice = AUTO;
|
||
|
|
resolved = WealthPanel.ALL;
|
||
|
|
}
|
||
|
|
return resolved;
|
||
|
|
}
|
||
|
|
|
||
|
|
void setRange(int index)
|
||
|
|
{
|
||
|
|
rangeBar.setSelected(index);
|
||
|
|
}
|
||
|
|
|
||
|
|
void setMainMode(WealthChart.Mode mode)
|
||
|
|
{
|
||
|
|
styleBar.setSelected(mode == WealthChart.Mode.CANDLES ? 1 : 0);
|
||
|
|
view.main.setMode(mode);
|
||
|
|
}
|
||
|
|
|
||
|
|
void update(WealthPanel.Model m, List<AccountData> accounts, String selectionKey)
|
||
|
|
{
|
||
|
|
List<String> keys = new ArrayList<>();
|
||
|
|
accounts.forEach(a -> keys.add(a.key + "=" + a.name));
|
||
|
|
if (!keys.equals(comboKeys))
|
||
|
|
{
|
||
|
|
comboKeys = keys;
|
||
|
|
updatingCombo = true;
|
||
|
|
characterBox.removeAllItems();
|
||
|
|
characterBox.addItem(new Choice(AUTO, "Logged-in character"));
|
||
|
|
characterBox.addItem(new Choice(WealthPanel.ALL, "All characters"));
|
||
|
|
for (AccountData a : accounts)
|
||
|
|
{
|
||
|
|
characterBox.addItem(new Choice(a.key, a.name));
|
||
|
|
}
|
||
|
|
updatingCombo = false;
|
||
|
|
}
|
||
|
|
updatingCombo = true;
|
||
|
|
for (int i = 0; i < characterBox.getItemCount(); i++)
|
||
|
|
{
|
||
|
|
if (Objects.equals(characterBox.getItemAt(i).key, choice))
|
||
|
|
{
|
||
|
|
characterBox.setSelectedIndex(i);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
updatingCombo = false;
|
||
|
|
|
||
|
|
long sessionStart = panel.sessionStart();
|
||
|
|
sessionLabel.setText(panel.isSessionView() ? "Since session start" : sessionStart > 0 ? "Session: " + Ui.ago(sessionStart).replace(" ago", "") : "");
|
||
|
|
sessionLabel.setForeground(panel.isSessionView() ? Ui.ACCENT : Ui.MUTED);
|
||
|
|
|
||
|
|
view.update(m, 10);
|
||
|
|
panel.resolveNames(view.lastMovers);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static JButton button(String text, Runnable action)
|
||
|
|
{
|
||
|
|
JButton b = new JButton(text);
|
||
|
|
b.setFont(FontManager.getRunescapeSmallFont());
|
||
|
|
b.setFocusPainted(false);
|
||
|
|
b.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||
|
|
b.setPreferredSize(new Dimension(Math.max(70, text.length() * 8 + 20), 30));
|
||
|
|
b.addActionListener(e -> action.run());
|
||
|
|
return b;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static JLabel label(String text)
|
||
|
|
{
|
||
|
|
JLabel l = new JLabel(text);
|
||
|
|
l.setFont(FontManager.getRunescapeSmallFont());
|
||
|
|
l.setForeground(Ui.MUTED);
|
||
|
|
return l;
|
||
|
|
}
|
||
|
|
}
|