infobox: add support for multiple infobox groups
Co-authored-by: Ron Young <admin@ryoung.io>
This commit is contained in:
@@ -79,7 +79,6 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayRenderer;
|
||||
import net.runelite.client.ui.overlay.WidgetOverlay;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay;
|
||||
import net.runelite.client.ws.PartyService;
|
||||
@@ -134,7 +133,7 @@ public class RuneLite
|
||||
private ClientUI clientUI;
|
||||
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
private Provider<InfoBoxManager> infoBoxManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
@@ -160,9 +159,6 @@ public class RuneLite
|
||||
@Inject
|
||||
private Provider<CommandManager> commandManager;
|
||||
|
||||
@Inject
|
||||
private Provider<InfoBoxOverlay> infoBoxOverlay;
|
||||
|
||||
@Inject
|
||||
private Provider<TooltipOverlay> tooltipOverlay;
|
||||
|
||||
@@ -367,7 +363,6 @@ public class RuneLite
|
||||
eventBus.register(externalPluginManager);
|
||||
eventBus.register(overlayManager);
|
||||
eventBus.register(drawManager);
|
||||
eventBus.register(infoBoxManager);
|
||||
eventBus.register(configManager);
|
||||
eventBus.register(discordService);
|
||||
|
||||
@@ -376,6 +371,7 @@ public class RuneLite
|
||||
// Initialize chat colors
|
||||
chatMessageManager.get().loadColors();
|
||||
|
||||
eventBus.register(infoBoxManager.get());
|
||||
eventBus.register(partyService.get());
|
||||
eventBus.register(overlayRenderer.get());
|
||||
eventBus.register(friendsChatManager.get());
|
||||
@@ -386,11 +382,9 @@ public class RuneLite
|
||||
eventBus.register(lootManager.get());
|
||||
eventBus.register(chatboxPanelManager.get());
|
||||
eventBus.register(hooks.get());
|
||||
eventBus.register(infoBoxOverlay.get());
|
||||
|
||||
// Add core overlays
|
||||
WidgetOverlay.createOverlays(client).forEach(overlayManager::add);
|
||||
overlayManager.add(infoBoxOverlay.get());
|
||||
overlayManager.add(worldMapOverlay.get());
|
||||
overlayManager.add(tooltipOverlay.get());
|
||||
}
|
||||
|
||||
@@ -334,7 +334,8 @@ public interface RuneLiteConfig extends Config
|
||||
name = "Display infoboxes vertically",
|
||||
description = "Toggles the infoboxes to display vertically",
|
||||
position = 40,
|
||||
section = overlaySettings
|
||||
section = overlaySettings,
|
||||
hidden = true
|
||||
)
|
||||
default boolean infoBoxVertical()
|
||||
{
|
||||
|
||||
@@ -89,4 +89,10 @@ public class BoostIndicator extends InfoBox
|
||||
{
|
||||
return config.displayInfoboxes() && plugin.canShowBoosts() && plugin.getSkillsToDisplay().contains(getSkill());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "Boost " + skill.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,4 +45,10 @@ class TimerTimer extends Timer
|
||||
{
|
||||
return timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return timer.name();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
@@ -52,6 +53,13 @@ public abstract class Overlay implements LayoutableRenderableEntity
|
||||
private boolean resizable;
|
||||
private boolean resettable = true;
|
||||
|
||||
/**
|
||||
* Whether this overlay can be dragged onto other overlays & have
|
||||
* other overlays dragged onto it.
|
||||
*/
|
||||
@Setter(AccessLevel.PROTECTED)
|
||||
private boolean dragTargetable;
|
||||
|
||||
protected Overlay()
|
||||
{
|
||||
plugin = null;
|
||||
@@ -64,6 +72,7 @@ public abstract class Overlay implements LayoutableRenderableEntity
|
||||
|
||||
/**
|
||||
* Overlay name, used for saving the overlay, needs to be unique
|
||||
*
|
||||
* @return overlay name
|
||||
*/
|
||||
public String getName()
|
||||
@@ -74,4 +83,17 @@ public abstract class Overlay implements LayoutableRenderableEntity
|
||||
public void onMouseOver()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an overlay is dragged onto this, if dragTargetable is true.
|
||||
* Return true to consume the mouse event and prevent the other
|
||||
* overlay from being moved
|
||||
*
|
||||
* @param other the overlay being dragged
|
||||
* @return
|
||||
*/
|
||||
public boolean onDrag(Overlay other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100);
|
||||
private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100);
|
||||
private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200);
|
||||
private static final Color MOVING_OVERLAY_TARGET_COLOR = Color.RED;
|
||||
private static final Color MOVING_OVERLAY_RESIZING_COLOR = new Color(255, 0, 255, 200);
|
||||
private final Client client;
|
||||
private final OverlayManager overlayManager;
|
||||
@@ -87,6 +88,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
private final Point overlayOffset = new Point();
|
||||
private final Point mousePosition = new Point();
|
||||
private Overlay currentManagedOverlay;
|
||||
private Overlay dragTargetOverlay;
|
||||
private Rectangle currentManagedBounds;
|
||||
private boolean inOverlayManagingMode;
|
||||
private boolean inOverlayResizingMode;
|
||||
@@ -292,15 +294,28 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
{
|
||||
if (inOverlayManagingMode)
|
||||
{
|
||||
Color boundsColor;
|
||||
if (inOverlayResizingMode && currentManagedOverlay == overlay)
|
||||
{
|
||||
graphics.setColor(MOVING_OVERLAY_RESIZING_COLOR);
|
||||
boundsColor = MOVING_OVERLAY_RESIZING_COLOR;
|
||||
}
|
||||
else if (inOverlayDraggingMode && currentManagedOverlay == overlay)
|
||||
{
|
||||
boundsColor = MOVING_OVERLAY_ACTIVE_COLOR;
|
||||
}
|
||||
else if (inOverlayDraggingMode && overlay.isDragTargetable() && currentManagedOverlay.isDragTargetable()
|
||||
&& currentManagedOverlay.getBounds().intersects(bounds))
|
||||
{
|
||||
boundsColor = MOVING_OVERLAY_TARGET_COLOR;
|
||||
assert currentManagedOverlay != overlay;
|
||||
dragTargetOverlay = overlay;
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.setColor(inOverlayDraggingMode && currentManagedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR);
|
||||
boundsColor = MOVING_OVERLAY_COLOR;
|
||||
}
|
||||
|
||||
graphics.setColor(boundsColor);
|
||||
graphics.draw(bounds);
|
||||
graphics.setPaint(paint);
|
||||
}
|
||||
@@ -457,6 +472,12 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
if (dragTargetOverlay != null && !currentManagedOverlay.getBounds().intersects(dragTargetOverlay.getBounds()))
|
||||
{
|
||||
// No longer over drag target
|
||||
dragTargetOverlay = null;
|
||||
}
|
||||
|
||||
final Rectangle canvasRect = new Rectangle(client.getRealDimensions());
|
||||
|
||||
if (!canvasRect.contains(p))
|
||||
@@ -584,7 +605,17 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
|
||||
mousePosition.setLocation(-1, -1);
|
||||
|
||||
// do not snapcorner detached overlays
|
||||
if (dragTargetOverlay != null)
|
||||
{
|
||||
if (dragTargetOverlay.onDrag(currentManagedOverlay))
|
||||
{
|
||||
mouseEvent.consume();
|
||||
resetOverlayManagementMode();
|
||||
return mouseEvent;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the overlay is over a snapcorner and move it if so, unless it is a detached overlay
|
||||
if (currentManagedOverlay.getPosition() != OverlayPosition.DETACHED && inOverlayDraggingMode)
|
||||
{
|
||||
final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height);
|
||||
@@ -720,6 +751,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
inOverlayResizingMode = false;
|
||||
inOverlayDraggingMode = false;
|
||||
currentManagedOverlay = null;
|
||||
dragTargetOverlay = null;
|
||||
currentManagedBounds = null;
|
||||
clientUI.setCursor(clientUI.getDefaultCursor());
|
||||
}
|
||||
|
||||
@@ -81,4 +81,11 @@ public abstract class InfoBox
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
// Use a combination of plugin name and infobox implementation name to try and make each infobox as unique
|
||||
// as possible by default
|
||||
return plugin.getClass().getSimpleName() + "_" + getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,33 +25,76 @@
|
||||
package net.runelite.client.ui.overlay.infobox;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.InfoBoxMenuClicked;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.components.ComponentOrientation;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
import net.runelite.client.util.AsyncBufferedImage;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class InfoBoxManager
|
||||
{
|
||||
private final List<InfoBox> infoBoxes = new CopyOnWriteArrayList<>();
|
||||
private static final String INFOBOXLAYER_KEY = "infoboxlayer";
|
||||
private static final String INFOBOXOVERLAY_KEY = "infoboxoverlay";
|
||||
private static final String INFOBOXOVERLAY_ORIENTATION_PREFIX = "orient_";
|
||||
private static final String DEFAULT_LAYER = "InfoBoxOverlay";
|
||||
|
||||
private static final String DETACH = "Detach";
|
||||
private static final String FLIP = "Flip";
|
||||
private static final String DELETE = "Delete";
|
||||
|
||||
private static final OverlayMenuEntry DETACH_ME = new OverlayMenuEntry(MenuAction.RUNELITE_INFOBOX, DETACH, "InfoBox");
|
||||
private static final OverlayMenuEntry FLIP_ME = new OverlayMenuEntry(MenuAction.RUNELITE_INFOBOX, FLIP, "InfoBox Group");
|
||||
private static final OverlayMenuEntry DELETE_ME = new OverlayMenuEntry(MenuAction.RUNELITE_INFOBOX, DELETE, "InfoBox Group");
|
||||
|
||||
private final Map<String, InfoBoxOverlay> layers = new ConcurrentHashMap<>();
|
||||
|
||||
private final RuneLiteConfig runeLiteConfig;
|
||||
private final TooltipManager tooltipManager;
|
||||
private final Client client;
|
||||
private final EventBus eventBus;
|
||||
private final OverlayManager overlayManager;
|
||||
private final ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private InfoBoxManager(final RuneLiteConfig runeLiteConfig)
|
||||
private InfoBoxManager(
|
||||
final RuneLiteConfig runeLiteConfig,
|
||||
final TooltipManager tooltipManager,
|
||||
final Client client,
|
||||
final EventBus eventBus,
|
||||
final OverlayManager overlayManager,
|
||||
final ConfigManager configManager)
|
||||
{
|
||||
this.runeLiteConfig = runeLiteConfig;
|
||||
this.tooltipManager = tooltipManager;
|
||||
this.client = client;
|
||||
this.eventBus = eventBus;
|
||||
this.overlayManager = overlayManager;
|
||||
this.configManager = configManager;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -59,7 +102,33 @@ public class InfoBoxManager
|
||||
{
|
||||
if (event.getGroup().equals("runelite") && event.getKey().equals("infoBoxSize"))
|
||||
{
|
||||
infoBoxes.forEach(this::updateInfoBoxImage);
|
||||
layers.values().forEach(l -> l.getInfoBoxes().forEach(this::updateInfoBoxImage));
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onInfoBoxMenuClicked(InfoBoxMenuClicked event)
|
||||
{
|
||||
if (DETACH.equals(event.getEntry().getOption()))
|
||||
{
|
||||
// The layer name doesn't matter as long as it is unique
|
||||
splitInfobox(event.getInfoBox().getName() + "_" + System.currentTimeMillis(), event.getInfoBox());
|
||||
}
|
||||
else if (FLIP.equals(event.getEntry().getOption()))
|
||||
{
|
||||
InfoBoxOverlay infoBoxOverlay = layers.get(getLayer(event.getInfoBox()));
|
||||
ComponentOrientation newOrientation = infoBoxOverlay.flip();
|
||||
setOrientation(infoBoxOverlay.getName(), newOrientation);
|
||||
}
|
||||
else if (DELETE.equals(event.getEntry().getOption()))
|
||||
{
|
||||
// This is just a merge into the default layer
|
||||
InfoBoxOverlay source = layers.get(getLayer(event.getInfoBox()));
|
||||
InfoBoxOverlay dest = layers.computeIfAbsent(DEFAULT_LAYER, this::makeOverlay);
|
||||
if (source != dest)
|
||||
{
|
||||
mergeInfoBoxes(source, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,14 +139,25 @@ public class InfoBoxManager
|
||||
|
||||
updateInfoBoxImage(infoBox);
|
||||
|
||||
String layerName = getLayer(infoBox);
|
||||
InfoBoxOverlay overlay = layers.computeIfAbsent(layerName, this::makeOverlay);
|
||||
List<OverlayMenuEntry> menuEntries = infoBox.getMenuEntries();
|
||||
menuEntries.add(DETACH_ME);
|
||||
menuEntries.add(FLIP_ME);
|
||||
if (!layerName.equals(DEFAULT_LAYER))
|
||||
{
|
||||
// Non default-group infoboxes have a delete option to delete the group
|
||||
menuEntries.add(DELETE_ME);
|
||||
}
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
int idx = findInsertionIndex(infoBoxes, infoBox, (b1, b2) -> ComparisonChain
|
||||
int idx = findInsertionIndex(overlay.getInfoBoxes(), infoBox, (b1, b2) -> ComparisonChain
|
||||
.start()
|
||||
.compare(b1.getPriority(), b2.getPriority())
|
||||
.compare(b1.getPlugin().getName(), b2.getPlugin().getName())
|
||||
.result());
|
||||
infoBoxes.add(idx, infoBox);
|
||||
overlay.getInfoBoxes().add(idx, infoBox);
|
||||
}
|
||||
|
||||
BufferedImage image = infoBox.getImage();
|
||||
@@ -91,28 +171,40 @@ public class InfoBoxManager
|
||||
|
||||
public synchronized void removeInfoBox(InfoBox infoBox)
|
||||
{
|
||||
if (infoBoxes.remove(infoBox))
|
||||
if (infoBox == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (layers.get(getLayer(infoBox)).getInfoBoxes().remove(infoBox))
|
||||
{
|
||||
log.debug("Removed InfoBox {}", infoBox);
|
||||
}
|
||||
|
||||
infoBox.getMenuEntries().remove(DETACH_ME);
|
||||
infoBox.getMenuEntries().remove(FLIP_ME);
|
||||
infoBox.getMenuEntries().remove(DELETE_ME);
|
||||
}
|
||||
|
||||
public synchronized void removeIf(Predicate<InfoBox> filter)
|
||||
{
|
||||
if (infoBoxes.removeIf(filter))
|
||||
for (InfoBoxOverlay overlay : layers.values())
|
||||
{
|
||||
log.debug("Removed InfoBoxes for filter {}", filter);
|
||||
if (overlay.getInfoBoxes().removeIf(filter))
|
||||
{
|
||||
log.debug("Removed InfoBoxes for filter {} from {}", filter, overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<InfoBox> getInfoBoxes()
|
||||
{
|
||||
return Collections.unmodifiableList(infoBoxes);
|
||||
return layers.values().stream().map(InfoBoxOverlay::getInfoBoxes).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public synchronized void cull()
|
||||
{
|
||||
infoBoxes.removeIf(InfoBox::cull);
|
||||
layers.values().forEach(l -> l.getInfoBoxes().removeIf(InfoBox::cull));
|
||||
}
|
||||
|
||||
public void updateInfoBoxImage(final InfoBox infoBox)
|
||||
@@ -152,6 +244,140 @@ public class InfoBoxManager
|
||||
infoBox.setScaledImage(resultImage);
|
||||
}
|
||||
|
||||
private InfoBoxOverlay makeOverlay(String name)
|
||||
{
|
||||
ComponentOrientation orientation = getOrientation(name);
|
||||
if (orientation == null)
|
||||
{
|
||||
if (name.equals(DEFAULT_LAYER))
|
||||
{
|
||||
// Fall back to old orientation config option
|
||||
orientation = runeLiteConfig.infoBoxVertical() ? ComponentOrientation.VERTICAL : ComponentOrientation.HORIZONTAL;
|
||||
setOrientation(name, orientation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default infobox orientation
|
||||
orientation = ComponentOrientation.HORIZONTAL;
|
||||
}
|
||||
}
|
||||
|
||||
InfoBoxOverlay infoBoxOverlay = new InfoBoxOverlay(
|
||||
this,
|
||||
tooltipManager,
|
||||
client,
|
||||
runeLiteConfig,
|
||||
eventBus,
|
||||
name,
|
||||
orientation);
|
||||
overlayManager.add(infoBoxOverlay);
|
||||
eventBus.register(infoBoxOverlay);
|
||||
return infoBoxOverlay;
|
||||
}
|
||||
|
||||
private void removeOverlay(InfoBoxOverlay overlay)
|
||||
{
|
||||
unsetOrientation(overlay.getName());
|
||||
eventBus.unregister(overlay);
|
||||
overlayManager.remove(overlay);
|
||||
layers.remove(overlay.getName());
|
||||
}
|
||||
|
||||
private synchronized void splitInfobox(String newLayer, InfoBox infoBox)
|
||||
{
|
||||
String layer = getLayer(infoBox);
|
||||
InfoBoxOverlay oldOverlay = layers.get(layer);
|
||||
// Find all infoboxes with the same name, as they are all within the same group and so move at once.
|
||||
Collection<InfoBox> filtered = oldOverlay.getInfoBoxes().stream()
|
||||
.filter(i -> i.getName().equals(infoBox.getName())).collect(Collectors.toList());
|
||||
|
||||
oldOverlay.getInfoBoxes().removeAll(filtered);
|
||||
if (oldOverlay.getInfoBoxes().isEmpty())
|
||||
{
|
||||
log.debug("Deleted layer: {}", oldOverlay.getName());
|
||||
removeOverlay(oldOverlay);
|
||||
}
|
||||
|
||||
InfoBoxOverlay newOverlay = layers.computeIfAbsent(newLayer, this::makeOverlay);
|
||||
newOverlay.getInfoBoxes().addAll(filtered);
|
||||
|
||||
// Adjust config for new infoboxes
|
||||
for (InfoBox i : filtered)
|
||||
{
|
||||
setLayer(i, newLayer);
|
||||
|
||||
if (!i.getMenuEntries().contains(DELETE_ME))
|
||||
{
|
||||
i.getMenuEntries().add(DELETE_ME);
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("Moving infobox named {} (layer {}) to layer {}: {} boxes", infoBox.getName(), layer, newLayer, filtered.size());
|
||||
}
|
||||
|
||||
public synchronized void mergeInfoBoxes(InfoBoxOverlay source, InfoBoxOverlay dest)
|
||||
{
|
||||
Collection<InfoBox> infoBoxesToMove = source.getInfoBoxes();
|
||||
boolean isDefault = dest.getName().equals(DEFAULT_LAYER);
|
||||
|
||||
log.debug("Merging InfoBoxes from {} into {} ({} boxes)", source.getName(), dest.getName(), infoBoxesToMove.size());
|
||||
|
||||
for (InfoBox infoBox : infoBoxesToMove)
|
||||
{
|
||||
setLayer(infoBox, dest.getName());
|
||||
|
||||
if (isDefault)
|
||||
{
|
||||
infoBox.getMenuEntries().remove(DELETE_ME);
|
||||
}
|
||||
}
|
||||
|
||||
dest.getInfoBoxes().addAll(infoBoxesToMove);
|
||||
source.getInfoBoxes().clear();
|
||||
|
||||
// remove source
|
||||
removeOverlay(source);
|
||||
log.debug("Deleted layer: {}", source.getName());
|
||||
}
|
||||
|
||||
private String getLayer(InfoBox infoBox)
|
||||
{
|
||||
String name = configManager.getConfiguration(INFOBOXLAYER_KEY, infoBox.getName());
|
||||
if (Strings.isNullOrEmpty(name))
|
||||
{
|
||||
return DEFAULT_LAYER;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private void setLayer(InfoBox infoBox, String layer)
|
||||
{
|
||||
if (layer.equals(DEFAULT_LAYER))
|
||||
{
|
||||
configManager.unsetConfiguration(INFOBOXLAYER_KEY, infoBox.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
configManager.setConfiguration(INFOBOXLAYER_KEY, infoBox.getName(), layer);
|
||||
}
|
||||
}
|
||||
|
||||
ComponentOrientation getOrientation(String name)
|
||||
{
|
||||
return configManager.getConfiguration(INFOBOXOVERLAY_KEY, INFOBOXOVERLAY_ORIENTATION_PREFIX + name, ComponentOrientation.class);
|
||||
}
|
||||
|
||||
void setOrientation(String name, ComponentOrientation orientation)
|
||||
{
|
||||
configManager.setConfiguration(INFOBOXOVERLAY_KEY, INFOBOXOVERLAY_ORIENTATION_PREFIX + name, orientation);
|
||||
}
|
||||
|
||||
void unsetOrientation(String name)
|
||||
{
|
||||
configManager.unsetConfiguration(INFOBOXOVERLAY_KEY, INFOBOXOVERLAY_ORIENTATION_PREFIX + name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find insertion point for the given key into the given sorted list. If key already exists in the list,
|
||||
* return the index after the last occurrence.
|
||||
|
||||
@@ -33,8 +33,9 @@ import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
@@ -42,6 +43,7 @@ import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.InfoBoxMenuClicked;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.OverlayPanel;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
@@ -51,7 +53,6 @@ import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
|
||||
@Singleton
|
||||
public class InfoBoxOverlay extends OverlayPanel
|
||||
{
|
||||
private static final int GAP = 1;
|
||||
@@ -62,24 +63,33 @@ public class InfoBoxOverlay extends OverlayPanel
|
||||
private final Client client;
|
||||
private final RuneLiteConfig config;
|
||||
private final EventBus eventBus;
|
||||
private final String name;
|
||||
private ComponentOrientation orientation;
|
||||
|
||||
@Getter
|
||||
private final List<InfoBox> infoBoxes = new CopyOnWriteArrayList<>();
|
||||
|
||||
private InfoBoxComponent hoveredComponent;
|
||||
|
||||
@Inject
|
||||
private InfoBoxOverlay(
|
||||
InfoBoxOverlay(
|
||||
InfoBoxManager infoboxManager,
|
||||
TooltipManager tooltipManager,
|
||||
Client client,
|
||||
RuneLiteConfig config,
|
||||
EventBus eventBus)
|
||||
EventBus eventBus,
|
||||
String name,
|
||||
@NonNull ComponentOrientation orientation)
|
||||
{
|
||||
this.tooltipManager = tooltipManager;
|
||||
this.infoboxManager = infoboxManager;
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
this.eventBus = eventBus;
|
||||
this.name = name;
|
||||
this.orientation = orientation;
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
setClearChildren(false);
|
||||
setDragTargetable(true);
|
||||
|
||||
panelComponent.setWrap(true);
|
||||
panelComponent.setBackgroundColor(null);
|
||||
@@ -87,11 +97,15 @@ public class InfoBoxOverlay extends OverlayPanel
|
||||
panelComponent.setGap(new Point(GAP, GAP));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
final List<InfoBox> infoBoxes = infoboxManager.getInfoBoxes();
|
||||
|
||||
final boolean menuOpen = client.isMenuOpen();
|
||||
if (!menuOpen)
|
||||
{
|
||||
@@ -106,9 +120,7 @@ public class InfoBoxOverlay extends OverlayPanel
|
||||
// Set preferred size to the size of DEFAULT_WRAP_COUNT infoboxes, including the padding - which is applied
|
||||
// to the last infobox prior to wrapping too.
|
||||
panelComponent.setPreferredSize(new Dimension(DEFAULT_WRAP_COUNT * (config.infoBoxSize() + GAP), DEFAULT_WRAP_COUNT * (config.infoBoxSize() + GAP)));
|
||||
panelComponent.setOrientation(config.infoBoxVertical()
|
||||
? ComponentOrientation.VERTICAL
|
||||
: ComponentOrientation.HORIZONTAL);
|
||||
panelComponent.setOrientation(orientation);
|
||||
|
||||
for (InfoBox box : infoBoxes)
|
||||
{
|
||||
@@ -177,7 +189,7 @@ public class InfoBoxOverlay extends OverlayPanel
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked menuOptionClicked)
|
||||
{
|
||||
if (menuOptionClicked.getMenuAction() != MenuAction.RUNELITE_INFOBOX)
|
||||
if (menuOptionClicked.getMenuAction() != MenuAction.RUNELITE_INFOBOX || hoveredComponent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -192,4 +204,21 @@ public class InfoBoxOverlay extends OverlayPanel
|
||||
eventBus.post(new InfoBoxMenuClicked(overlayMenuEntry, infoBox));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(Overlay source)
|
||||
{
|
||||
if (!(source instanceof InfoBoxOverlay))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
infoboxManager.mergeInfoBoxes((InfoBoxOverlay) source, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
ComponentOrientation flip()
|
||||
{
|
||||
return orientation = orientation == ComponentOrientation.HORIZONTAL ? ComponentOrientation.VERTICAL : ComponentOrientation.HORIZONTAL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -91,6 +92,10 @@ public class ItemChargePluginTest
|
||||
@Bind
|
||||
private Notifier notifier;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private ItemChargeConfig config;
|
||||
|
||||
@@ -34,6 +34,7 @@ import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ChatColorConfig;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.util.ImageCapture;
|
||||
import net.runelite.client.ws.PartyService;
|
||||
import net.runelite.http.api.chat.ChatClient;
|
||||
@@ -85,6 +86,10 @@ public class RaidsPluginTest
|
||||
@Inject
|
||||
RaidsPlugin raidsPlugin;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private PartyService partyService;
|
||||
|
||||
@@ -45,6 +45,7 @@ import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.DrawManager;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -105,6 +106,10 @@ public class ScreenshotPluginTest
|
||||
@Bind
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
|
||||
@@ -32,6 +32,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -53,6 +55,14 @@ public class InfoBoxManagerTest
|
||||
@Bind
|
||||
private RuneLiteConfig runeLiteConfig;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Mock
|
||||
@Bind
|
||||
private Client client;
|
||||
|
||||
@Before
|
||||
public void before()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user