client: add support for menu options on infoboxes

This commit is contained in:
Adam
2020-06-16 21:06:53 -04:00
committed by Adam
parent 1b7dadeb68
commit 48357f9329
9 changed files with 129 additions and 22 deletions

View File

@@ -277,6 +277,10 @@ public enum MenuAction
* a player and have its identifier set to a player index.
*/
RUNELITE_PLAYER(1503),
/**
* Menu action for InfoBox menu entries
*/
RUNELITE_INFOBOX(1504),
/**
* Menu action triggered when the id is not defined in this class.

View File

@@ -361,6 +361,7 @@ 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);

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020, Adam <Adam@sigterm.info>
* 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.events;
import lombok.Value;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.infobox.InfoBox;
@Value
public class InfoBoxMenuClicked
{
private OverlayMenuEntry entry;
private InfoBox infoBox;
}

View File

@@ -33,9 +33,11 @@ import javax.inject.Inject;
import javax.swing.JButton;
import javax.swing.JPanel;
import net.runelite.api.Client;
import net.runelite.api.MenuAction;
import net.runelite.client.Notifier;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.infobox.Counter;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.ImageUtil;
@@ -166,7 +168,12 @@ class DevToolsPanel extends PluginPanel
});
final JButton newInfoboxBtn = new JButton("Infobox");
newInfoboxBtn.addActionListener(e -> infoBoxManager.addInfoBox(new Counter(ImageUtil.getResourceStreamFromClass(getClass(), "devtools_icon.png"), plugin, 42)));
newInfoboxBtn.addActionListener(e ->
{
Counter counter = new Counter(ImageUtil.getResourceStreamFromClass(getClass(), "devtools_icon.png"), plugin, 42);
counter.getMenuEntries().add(new OverlayMenuEntry(MenuAction.RUNELITE_INFOBOX, "Test", "DevTools"));
infoBoxManager.addInfoBox(counter);
});
container.add(newInfoboxBtn);
final JButton clearInfoboxBtn = new JButton("Clear Infobox");

View File

@@ -33,7 +33,6 @@ import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -136,7 +135,8 @@ public class OverlayManager
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (event.getMenuAction() != MenuAction.RUNELITE_OVERLAY)
MenuAction menuAction = event.getMenuAction();
if (menuAction != MenuAction.RUNELITE_OVERLAY && menuAction != MenuAction.RUNELITE_OVERLAY_CONFIG)
{
return;
}
@@ -147,12 +147,13 @@ public class OverlayManager
if (overlay != null)
{
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
Optional<OverlayMenuEntry> optionalOverlayMenuEntry = menuEntries.stream()
OverlayMenuEntry overlayMenuEntry = menuEntries.stream()
.filter(me -> me.getOption().equals(event.getMenuOption()))
.findAny();
if (optionalOverlayMenuEntry.isPresent())
.findAny()
.orElse(null);
if (overlayMenuEntry != null)
{
eventBus.post(new OverlayMenuClicked(optionalOverlayMenuEntry.get(), overlay));
eventBus.post(new OverlayMenuClicked(overlayMenuEntry, overlay));
}
}
}

View File

@@ -46,7 +46,6 @@ import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry;
import net.runelite.api.events.BeforeRender;
import net.runelite.api.events.ClientTick;
@@ -807,7 +806,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
final MenuEntry entry = new MenuEntry();
entry.setOption(overlayMenuEntry.getOption());
entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET));
entry.setType(MenuAction.RUNELITE_OVERLAY.getId());
entry.setType(overlayMenuEntry.getMenuAction().getId());
entry.setIdentifier(overlayManager.getOverlays().indexOf(overlay)); // overlay id
entries[i] = entry;

View File

@@ -35,6 +35,7 @@ import java.awt.image.BufferedImage;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.infobox.InfoBox;
@Setter
public class InfoBoxComponent implements LayoutableRenderableEntity
@@ -54,6 +55,8 @@ public class InfoBoxComponent implements LayoutableRenderableEntity
private Color color = Color.WHITE;
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
private BufferedImage image;
@Getter
private InfoBox infoBox;
@Override
public Dimension render(Graphics2D graphics)

View File

@@ -26,11 +26,14 @@ package net.runelite.client.ui.overlay.infobox;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
public abstract class InfoBox
{
@@ -54,6 +57,10 @@ public abstract class InfoBox
@Setter
private String tooltip;
@Getter
@Setter
private List<OverlayMenuEntry> menuEntries = new ArrayList<>();
public InfoBox(BufferedImage image, @Nonnull Plugin plugin)
{
this.plugin = plugin;

View File

@@ -31,11 +31,18 @@ import java.awt.Dimension;
import java.awt.Graphics2D;
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 net.runelite.api.Client;
import net.runelite.api.MenuAction;
import net.runelite.api.events.MenuOptionClicked;
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.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPanel;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ComponentOrientation;
@@ -54,18 +61,23 @@ public class InfoBoxOverlay extends OverlayPanel
private final TooltipManager tooltipManager;
private final Client client;
private final RuneLiteConfig config;
private final EventBus eventBus;
private InfoBoxComponent hoveredComponent;
@Inject
private InfoBoxOverlay(
InfoBoxManager infoboxManager,
TooltipManager tooltipManager,
Client client,
RuneLiteConfig config)
RuneLiteConfig config,
EventBus eventBus)
{
this.tooltipManager = tooltipManager;
this.infoboxManager = infoboxManager;
this.client = client;
this.config = config;
this.eventBus = eventBus;
setPosition(OverlayPosition.TOP_LEFT);
setClearChildren(false);
@@ -80,6 +92,12 @@ public class InfoBoxOverlay extends OverlayPanel
{
final List<InfoBox> infoBoxes = infoboxManager.getInfoBoxes();
final boolean menuOpen = client.isMenuOpen();
if (!menuOpen)
{
hoveredComponent = null;
}
if (infoBoxes.isEmpty())
{
return null;
@@ -112,6 +130,7 @@ public class InfoBoxOverlay extends OverlayPanel
infoBoxComponent.setTooltip(box.getTooltip());
infoBoxComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
infoBoxComponent.setBackgroundColor(config.overlayBackgroundColor());
infoBoxComponent.setInfoBox(box);
panelComponent.getChildren().add(infoBoxComponent);
}
@@ -122,25 +141,55 @@ public class InfoBoxOverlay extends OverlayPanel
for (final LayoutableRenderableEntity child : panelComponent.getChildren())
{
if (child instanceof InfoBoxComponent)
final InfoBoxComponent component = (InfoBoxComponent) child;
// Create intersection rectangle
final Rectangle intersectionRectangle = new Rectangle(component.getBounds());
intersectionRectangle.translate(getBounds().x, getBounds().y);
if (intersectionRectangle.contains(mouse))
{
final InfoBoxComponent component = (InfoBoxComponent) child;
if (!Strings.isNullOrEmpty(component.getTooltip()))
final String tooltip = component.getTooltip();
if (!Strings.isNullOrEmpty(tooltip))
{
// Create intersection rectangle
final Rectangle intersectionRectangle = new Rectangle(component.getBounds());
intersectionRectangle.translate(getBounds().x, getBounds().y);
if (intersectionRectangle.contains(mouse))
{
tooltipManager.add(new Tooltip(component.getTooltip()));
}
tooltipManager.add(new Tooltip(tooltip));
}
if (!menuOpen)
{
hoveredComponent = component;
}
break;
}
}
panelComponent.getChildren().clear();
return dimension;
}
@Override
public List<OverlayMenuEntry> getMenuEntries()
{
// we dynamically build the menu options based on which infobox is hovered
return hoveredComponent == null ? Collections.emptyList() : hoveredComponent.getInfoBox().getMenuEntries();
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked menuOptionClicked)
{
if (menuOptionClicked.getMenuAction() != MenuAction.RUNELITE_INFOBOX)
{
return;
}
InfoBox infoBox = hoveredComponent.getInfoBox();
OverlayMenuEntry overlayMenuEntry = infoBox.getMenuEntries().stream()
.filter(me -> me.getOption().equals(menuOptionClicked.getMenuOption()))
.findAny()
.orElse(null);
if (overlayMenuEntry != null)
{
eventBus.post(new InfoBoxMenuClicked(overlayMenuEntry, infoBox));
}
}
}