Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigSection;
import net.runelite.client.config.Keybind;
import net.runelite.client.config.Range;
import net.runelite.client.ui.ColorScheme;

import java.awt.*;
Expand Down Expand Up @@ -134,6 +135,48 @@ default Keybind quickSetKeybind()
)
String appearanceSection = "appearanceSection";

@ConfigSection(
name = "Sidebar price graph",
description = "Configure the price graph shown in the sidebar for the current suggestion",
position = 21
)
String sidebarGraphSection = "sidebarGraphSection";

@ConfigItem(
keyName = "sidebarGraphEnabled",
name = "Show sidebar price graph",
description = "Show a compact price graph in the sidebar for the current suggestion.",
section = sidebarGraphSection,
position = 1
)
default boolean sidebarGraphEnabled() {
return true;
}

@ConfigItem(
keyName = "sidebarGraphMinutesBefore",
name = "Minutes before now",
description = "How many minutes before the current time to show on the sidebar graph.",
section = sidebarGraphSection,
position = 2
)
@Range(min = 15, max = 180)
default int sidebarGraphMinutesBefore() {
return 60;
}

@ConfigItem(
keyName = "sidebarGraphMinutesAfter",
name = "Minutes after now",
description = "How many minutes after the current time to show on the sidebar graph.",
section = sidebarGraphSection,
position = 3
)
@Range(min = 15, max = 180)
default int sidebarGraphMinutesAfter() {
return 60;
}

@ConfigItem(
keyName = "priceGraphMenuOptionEnabled",
name = "Enable price graph menu option",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ public class ApiRequestHandler {
private final SuggestionPreferencesManager preferencesManager;
private final ClientThread clientThread;


public void authenticate(String username, String password, Consumer<LoginResponse> successCallback, Consumer<String> failureCallback) {
Request request = new Request.Builder()
.url(serverUrl + "/login")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@ public void onConfigChanged(ConfigChanged event) {
highlightController.redraw();
});
}
if (event.getKey().equals("sidebarGraphEnabled") || event.getKey().equals("sidebarGraphMinutesBefore") || event.getKey().equals("sidebarGraphMinutesAfter")) {
clientThread.invokeLater(() -> mainPanel.copilotPanel.refresh());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ public void togglePause() {
if (pausedManager.isPaused()) {
pausedManager.setPaused(false);
suggestionManager.setSuggestionNeeded(true);
suggestionPanel.refresh();
copilotPanel.refresh();
} else {
pausedManager.setPaused(true);
highlightController.removeAll();
suggestionPanel.refresh();
copilotPanel.refresh();
}
}

Expand Down Expand Up @@ -151,7 +151,11 @@ public void getSuggestionAsync() {
suggestionManager.setGraphDataReadingInProgress(!skipGraphData);
Consumer<Suggestion> suggestionConsumer = (newSuggestion) -> handleSuggestionReceived(oldSuggestion, newSuggestion, accountStatus);
Consumer<Data> graphDataConsumer = (d) -> {
SwingUtilities.invokeLater(() -> flipDialogController.priceGraphPanel.setSuggestionPriceData(d));
SwingUtilities.invokeLater(() -> {
suggestionManager.setSuggestionGraphData(d);
flipDialogController.priceGraphPanel.setSuggestionPriceData(d);
copilotPanel.refresh();
});
suggestionManager.setGraphDataReadingInProgress(false);
};
Consumer<HttpResponseException> onFailure = (e) -> {
Expand All @@ -164,10 +168,10 @@ public void getSuggestionAsync() {
mainPanel.refresh();
loginPanel.showLoginErrorMessage("Login timed out. Please log in again");
} else {
suggestionPanel.refresh();
copilotPanel.refresh();
}
};
suggestionPanel.refresh();
copilotPanel.refresh();
log.debug("tick {} getting suggestion", client.getTickCount());
apiRequestHandler.getSuggestionAsync(accountStatus.toJson(gson, grandExchange.isOpen(), config.priceGraphWebsite() == FlippingCopilotConfig.PriceGraphWebsite.FLIPPING_COPILOT), suggestionConsumer, graphDataConsumer, onFailure, skipGraphData);
}
Expand Down Expand Up @@ -205,7 +209,7 @@ private synchronized void handleSuggestionReceived(Suggestion oldSuggestion, Sug
log.debug("Received suggestion: {}", newSuggestion.toString());
accountStatusManager.resetSkipSuggestion();
offerManager.setOfferJustPlaced(false);
suggestionPanel.refresh();
copilotPanel.refresh();
showNotifications(oldSuggestion, newSuggestion, accountStatus);
if (!newSuggestion.isWaitSuggestion()) {
SwingUtilities.invokeLater(() -> flipDialogController.priceGraphPanel.newSuggestedItemId(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.flippingcopilot.model;

import com.flippingcopilot.ui.graph.model.Data;
import lombok.Getter;
import lombok.Setter;

Expand All @@ -17,6 +18,7 @@ public class SuggestionManager {
private Instant lastFailureAt;
private HttpResponseException suggestionError;
private Suggestion suggestion;
private volatile Data suggestionGraphData;
private Instant suggestionReceivedAt;
private int lastOfferSubmittedTick = -1;

Expand All @@ -33,7 +35,9 @@ public class SuggestionManager {
public void setSuggestion(Suggestion suggestion) {
this.suggestion = suggestion;
suggestionReceivedAt = Instant.now();

if (suggestion == null || suggestion.isWaitSuggestion()) {
this.suggestionGraphData = null;
}
}

public void setSuggestionError(HttpResponseException error) {
Expand All @@ -44,6 +48,7 @@ public void setSuggestionError(HttpResponseException error) {
public void reset() {
suggestionNeeded = false;
suggestion = null;
suggestionGraphData = null;
suggestionReceivedAt = null;
lastFailureAt = null;
lastOfferSubmittedTick = -1;
Expand Down
15 changes: 14 additions & 1 deletion src/main/java/com/flippingcopilot/ui/CopilotPanel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.flippingcopilot.ui;

import com.flippingcopilot.config.FlippingCopilotConfig;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.*;
Expand All @@ -11,14 +13,20 @@ public class CopilotPanel extends JPanel {
public final SuggestionPanel suggestionPanel;
public final StatsPanelV2 statsPanel;
public final ControlPanel controlPanel;
public final SidebarGraphPanel sidebarGraphPanel;
private final FlippingCopilotConfig config;

@Inject
public CopilotPanel(SuggestionPanel suggestionPanel,
StatsPanelV2 statsPanel,
ControlPanel controlPanel) {
ControlPanel controlPanel,
SidebarGraphPanel sidebarGraphPanel,
FlippingCopilotConfig config) {
this.statsPanel = statsPanel;
this.suggestionPanel = suggestionPanel;
this.controlPanel = controlPanel;
this.sidebarGraphPanel = sidebarGraphPanel;
this.config = config;

setLayout(new BorderLayout());

Expand All @@ -28,7 +36,10 @@ public CopilotPanel(SuggestionPanel suggestionPanel,
topPanel.add(Box.createRigidArea(new Dimension(MainPanel.CONTENT_WIDTH, 5)));
topPanel.add(controlPanel);
topPanel.add(Box.createRigidArea(new Dimension(MainPanel.CONTENT_WIDTH, 5)));
topPanel.add(sidebarGraphPanel);
topPanel.add(Box.createRigidArea(new Dimension(MainPanel.CONTENT_WIDTH, 5)));

sidebarGraphPanel.setVisible(config.sidebarGraphEnabled());
add(topPanel, BorderLayout.NORTH);
add(statsPanel, BorderLayout.CENTER);
}
Expand All @@ -39,7 +50,9 @@ public void refresh() {
SwingUtilities.invokeLater(this::refresh);
return;
}
sidebarGraphPanel.setVisible(config.sidebarGraphEnabled());
suggestionPanel.refresh();
controlPanel.refresh();
sidebarGraphPanel.refresh();
}
}
176 changes: 176 additions & 0 deletions src/main/java/com/flippingcopilot/ui/SidebarGraphPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package com.flippingcopilot.ui;

import com.flippingcopilot.config.FlippingCopilotConfig;
import com.flippingcopilot.manager.PriceGraphConfigManager;
import com.flippingcopilot.model.Suggestion;
import com.flippingcopilot.model.SuggestionManager;
import com.flippingcopilot.ui.graph.DataManager;
import com.flippingcopilot.ui.graph.GraphPanel;
import com.flippingcopilot.ui.graph.model.Data;
import com.flippingcopilot.ui.graph.model.PriceLine;
import net.runelite.client.ui.ColorScheme;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.*;
import java.awt.*;

@Singleton
public class SidebarGraphPanel extends JPanel {

private static final int SIDEBAR_GRAPH_HEIGHT = 200;

private final SuggestionManager suggestionManager;
private final FlippingCopilotConfig config;
private final GraphPanel graphPanel;
private final JPanel contentPanel;
private final CardLayout cardLayout = new CardLayout();
private final JPanel loadingPanel;
private final JPanel emptyPanel;

private static final String CARD_GRAPH = "graph";
private static final String CARD_LOADING = "loading";
private static final String CARD_EMPTY = "empty";

/** Cached so we only create a new DataManager when graph data or suggestion actually changed. */
private int lastGraphDataItemId = -1;
private Integer lastSuggestionPrice = null;
private Boolean lastSuggestionWasBuy = null;

@Inject
public SidebarGraphPanel(SuggestionManager suggestionManager,
PriceGraphConfigManager configManager,
FlippingCopilotConfig config) {
this.suggestionManager = suggestionManager;
this.config = config;
setLayout(new BorderLayout());
setBackground(ColorScheme.DARKER_GRAY_COLOR);

graphPanel = new GraphPanel(configManager, true);
graphPanel.setPreferredSize(new Dimension(MainPanel.CONTENT_WIDTH, SIDEBAR_GRAPH_HEIGHT));
graphPanel.setMinimumSize(new Dimension(MainPanel.CONTENT_WIDTH, SIDEBAR_GRAPH_HEIGHT));
graphPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, SIDEBAR_GRAPH_HEIGHT));

contentPanel = new JPanel(cardLayout);
contentPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
contentPanel.setPreferredSize(new Dimension(MainPanel.CONTENT_WIDTH, SIDEBAR_GRAPH_HEIGHT));
contentPanel.setMinimumSize(new Dimension(MainPanel.CONTENT_WIDTH, SIDEBAR_GRAPH_HEIGHT));

JPanel graphWrapper = new JPanel(new BorderLayout());
graphWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
graphWrapper.setOpaque(true);
graphWrapper.add(graphPanel, BorderLayout.CENTER);
contentPanel.add(graphWrapper, CARD_GRAPH);

loadingPanel = buildLoadingPanel();
contentPanel.add(loadingPanel, CARD_LOADING);

emptyPanel = buildEmptyPanel();
contentPanel.add(emptyPanel, CARD_EMPTY);

add(contentPanel, BorderLayout.CENTER);
cardLayout.show(contentPanel, CARD_EMPTY);
}

@Override
public Dimension getPreferredSize() {
Dimension pref = super.getPreferredSize();
Container parent = getParent();
if (parent != null && parent.getWidth() > 0) {
int w = Math.max(parent.getWidth(), MainPanel.CONTENT_WIDTH);
pref = new Dimension(w, pref.height);
}
return pref;
}

private JPanel buildLoadingPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
panel.setPreferredSize(new Dimension(MainPanel.CONTENT_WIDTH, SIDEBAR_GRAPH_HEIGHT));
JLabel label = new JLabel("Loading price graph...");
label.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
Spinner spinner = new Spinner();
spinner.show();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(0, 0, 8, 0);
panel.add(spinner, gbc);
gbc.gridy = 1;
panel.add(label, gbc);
return panel;
}

private JPanel buildEmptyPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
panel.setPreferredSize(new Dimension(MainPanel.CONTENT_WIDTH, SIDEBAR_GRAPH_HEIGHT));
JLabel label = new JLabel("<html><center>Price graph for the<br>current suggestion<br>appears here</center></html>");
label.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
label.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(label);
return panel;
}

private static PriceLine buildPriceLine(Suggestion suggestion) {
if (suggestion == null) {
return null;
}
if (suggestion.isBuySuggestion()) {
return new PriceLine(
suggestion.getPrice(),
"Suggested buy price",
false
);
}
if (suggestion.isSellSuggestion()) {
return new PriceLine(
suggestion.getPrice(),
"Suggested sell price",
true
);
}
return null;
}

public void refresh() {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(this::refresh);
return;
}

graphPanel.setSidebarTimeRange(config.sidebarGraphMinutesBefore(), config.sidebarGraphMinutesAfter());

Suggestion suggestion = suggestionManager.getSuggestion();
Data graphData = suggestionManager.getSuggestionGraphData();

if (suggestionManager.isGraphDataReadingInProgress()) {
cardLayout.show(contentPanel, CARD_LOADING);
return;
}

if (suggestion != null && !suggestion.isWaitSuggestion()
&& graphData != null && graphData.itemId == suggestion.getItemId()) {
int suggestionPrice = suggestion.getPrice();
boolean suggestionIsBuy = suggestion.isBuySuggestion();
boolean dataUnchanged = lastGraphDataItemId == graphData.itemId
&& lastSuggestionPrice != null && lastSuggestionPrice == suggestionPrice
&& lastSuggestionWasBuy != null && lastSuggestionWasBuy == suggestionIsBuy;

if (!dataUnchanged) {
lastGraphDataItemId = graphData.itemId;
lastSuggestionPrice = suggestionPrice;
lastSuggestionWasBuy = suggestionIsBuy;
DataManager dm = new DataManager(graphData, null);
PriceLine priceLine = buildPriceLine(suggestion);
graphPanel.setData(dm, priceLine);
}
cardLayout.show(contentPanel, CARD_GRAPH);
} else {
lastGraphDataItemId = -1;
lastSuggestionPrice = null;
lastSuggestionWasBuy = null;
cardLayout.show(contentPanel, CARD_EMPTY);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,11 @@ private static TimeAxis calculateSubDayTimeAxis(int timeMin, int timeMax, int ti
}

public static YAxis calculatePriceAxis(Bounds bounds) {
int maxAllowableTicks = 18;
int maxAllowableGridLines = 28;
return calculatePriceAxis(bounds, 18);
}

public static YAxis calculatePriceAxis(Bounds bounds, int maxAllowableTicks) {
int maxAllowableGridLines = maxAllowableTicks * 2;

int priceRange = (int) bounds.yDelta();
int priceMin = (int) bounds.yMin;
Expand Down
Loading