Merge remote-tracking branch 'runelite/master'
This commit is contained in:
@@ -27,10 +27,12 @@ package net.runelite.client;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ClientShutdown;
|
||||
import net.runelite.client.task.Schedule;
|
||||
|
||||
@Singleton
|
||||
@@ -38,15 +40,23 @@ import net.runelite.client.task.Schedule;
|
||||
public class ClientSessionManager
|
||||
{
|
||||
private final SessionClient sessionClient;
|
||||
private final ClientThread clientThread;
|
||||
private UUID sessionId;
|
||||
|
||||
|
||||
@Inject
|
||||
ClientSessionManager(ClientThread clientThread)
|
||||
ClientSessionManager(EventBus eventBus)
|
||||
{
|
||||
this.sessionClient = new SessionClient();
|
||||
this.clientThread = clientThread;
|
||||
|
||||
eventBus.subscribe(ClientShutdown.class, this, (e) ->
|
||||
{
|
||||
Future<Void> f = shutdown();
|
||||
if (f != null)
|
||||
{
|
||||
e.waitFor(f);
|
||||
}
|
||||
sessionId = null;
|
||||
});
|
||||
}
|
||||
|
||||
void start()
|
||||
@@ -54,7 +64,8 @@ public class ClientSessionManager
|
||||
sessionClient.openSession()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.single())
|
||||
.subscribe(this::setUuid, this::error);
|
||||
.doOnError(this::error)
|
||||
.subscribe(this::setUuid);
|
||||
}
|
||||
|
||||
@Schedule(period = 10, unit = ChronoUnit.MINUTES, asynchronous = true)
|
||||
@@ -73,18 +84,15 @@ public class ClientSessionManager
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
private Future<Void> shutdown()
|
||||
{
|
||||
if (sessionId != null)
|
||||
{
|
||||
sessionClient.delete(sessionId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.single())
|
||||
.doOnError(this::error)
|
||||
.subscribe();
|
||||
return sessionClient.delete(sessionId)
|
||||
.toFuture();
|
||||
|
||||
sessionId = null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setUuid(UUID uuid)
|
||||
|
||||
@@ -469,7 +469,7 @@ public class RuneLite
|
||||
|
||||
// Initialize UI
|
||||
RuneLiteSplashScreen.stage(.80, "Initialize UI");
|
||||
clientUI.init(this);
|
||||
clientUI.init();
|
||||
|
||||
// Initialize Discord service
|
||||
discordService.init();
|
||||
@@ -599,13 +599,6 @@ public class RuneLite
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown()
|
||||
{
|
||||
clientSessionManager.shutdown();
|
||||
discordService.close();
|
||||
groups.close();
|
||||
}
|
||||
|
||||
private static class ConfigFileConverter implements ValueConverter<File>
|
||||
{
|
||||
@Override
|
||||
|
||||
@@ -371,18 +371,6 @@ public interface RuneLiteConfig extends Config
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "infoBoxWrap",
|
||||
name = "Infobox wrap count",
|
||||
description = "Configures the amount of infoboxes shown before wrapping",
|
||||
position = 29,
|
||||
titleSection = "infoboxTitle"
|
||||
)
|
||||
default int infoBoxWrap()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "infoBoxSize",
|
||||
name = "Infobox size",
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Abex
|
||||
* 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 java.time.Duration;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
@Value
|
||||
@Slf4j
|
||||
public class ClientShutdown implements Event
|
||||
{
|
||||
private Queue<Future<?>> tasks = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public void waitFor(Future<?> future)
|
||||
{
|
||||
tasks.add(future);
|
||||
}
|
||||
|
||||
public void waitForAllConsumers(Duration totalTimeout)
|
||||
{
|
||||
long deadline = System.nanoTime() + totalTimeout.toNanos();
|
||||
for (Future<?> task; (task = tasks.poll()) != null; )
|
||||
{
|
||||
long timeout = deadline - System.nanoTime();
|
||||
if (timeout < 0)
|
||||
{
|
||||
log.warn("Timed out waiting for task completion");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
task.get(timeout, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
catch (ThreadDeath d)
|
||||
{
|
||||
throw d;
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
log.warn("Error during shutdown: ", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,25 +49,52 @@ public class KeyManager
|
||||
|
||||
public void processKeyPressed(KeyEvent keyEvent)
|
||||
{
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (KeyListener keyListener : keyListeners)
|
||||
{
|
||||
keyListener.keyPressed(keyEvent);
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processKeyReleased(KeyEvent keyEvent)
|
||||
{
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (KeyListener keyListener : keyListeners)
|
||||
{
|
||||
keyListener.keyReleased(keyEvent);
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processKeyTyped(KeyEvent keyEvent)
|
||||
{
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (KeyListener keyListener : keyListeners)
|
||||
{
|
||||
keyListener.keyTyped(keyEvent);
|
||||
if (keyEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,30 +82,57 @@ public class MouseManager
|
||||
|
||||
public MouseEvent processMousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
checkExtraMouseButtons(mouseEvent);
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mousePressed(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
public MouseEvent processMouseReleased(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
checkExtraMouseButtons(mouseEvent);
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mouseReleased(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
public MouseEvent processMouseClicked(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
checkExtraMouseButtons(mouseEvent);
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mouseClicked(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
@@ -123,45 +150,90 @@ public class MouseManager
|
||||
|
||||
public MouseEvent processMouseEntered(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mouseEntered(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
public MouseEvent processMouseExited(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mouseExited(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
public MouseEvent processMouseDragged(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mouseDragged(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
public MouseEvent processMouseMoved(MouseEvent mouseEvent)
|
||||
{
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
for (MouseListener mouseListener : mouseListeners)
|
||||
{
|
||||
mouseEvent = mouseListener.mouseMoved(mouseEvent);
|
||||
if (mouseEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
public MouseWheelEvent processMouseWheelMoved(MouseWheelEvent mouseWheelEvent)
|
||||
{
|
||||
if (mouseWheelEvent.isConsumed())
|
||||
{
|
||||
return mouseWheelEvent;
|
||||
}
|
||||
|
||||
for (MouseWheelListener mouseWheelListener : mouseWheelListeners)
|
||||
{
|
||||
mouseWheelEvent = mouseWheelListener.mouseWheelMoved(mouseWheelEvent);
|
||||
if (mouseWheelEvent.isConsumed())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mouseWheelEvent;
|
||||
}
|
||||
|
||||
@@ -44,10 +44,13 @@ import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.Duration;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
@@ -72,7 +75,6 @@ import net.runelite.api.Point;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
@@ -80,6 +82,7 @@ import net.runelite.client.config.ExpandResizeType;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.config.WarningOnExit;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ClientShutdown;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.NavigationButtonAdded;
|
||||
import net.runelite.client.events.NavigationButtonRemoved;
|
||||
@@ -131,6 +134,7 @@ public class ClientUI
|
||||
private final Applet client;
|
||||
private final ConfigManager configManager;
|
||||
private final Provider<ClientThread> clientThreadProvider;
|
||||
private final EventBus eventBus;
|
||||
private final CardLayout cardLayout = new CardLayout();
|
||||
private final Rectangle sidebarButtonPosition = new Rectangle();
|
||||
private boolean withTitleBar;
|
||||
@@ -144,6 +148,7 @@ public class ClientUI
|
||||
private NavigationButton sidebarNavigationButton;
|
||||
private JButton sidebarNavigationJButton;
|
||||
private Dimension lastClientSize;
|
||||
private Cursor defaultCursor;
|
||||
private Field opacityField;
|
||||
private Field peerField;
|
||||
private Method setOpacityMethod;
|
||||
@@ -164,6 +169,7 @@ public class ClientUI
|
||||
this.client = client;
|
||||
this.configManager = configManager;
|
||||
this.clientThreadProvider = clientThreadProvider;
|
||||
this.eventBus = eventbus;
|
||||
|
||||
eventbus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||
eventbus.subscribe(NavigationButtonAdded.class, this, this::onNavigationButtonAdded);
|
||||
@@ -313,11 +319,8 @@ public class ClientUI
|
||||
|
||||
/**
|
||||
* Initialize UI.
|
||||
*
|
||||
* @param runelite runelite instance that will be shut down on exit
|
||||
* @throws Exception exception that can occur during creation of the UI
|
||||
*/
|
||||
public void init(final RuneLite runelite) throws Exception
|
||||
public void init() throws Exception
|
||||
{
|
||||
SwingUtilities.invokeAndWait(() ->
|
||||
{
|
||||
@@ -335,14 +338,36 @@ public class ClientUI
|
||||
frame.setLocationRelativeTo(frame.getOwner());
|
||||
frame.setResizable(true);
|
||||
|
||||
SwingUtil.addGracefulExitCallback(frame,
|
||||
() ->
|
||||
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event)
|
||||
{
|
||||
saveClientBoundsConfig();
|
||||
runelite.shutdown();
|
||||
},
|
||||
this::showWarningOnExit
|
||||
);
|
||||
int result = JOptionPane.OK_OPTION;
|
||||
|
||||
if (showWarningOnExit())
|
||||
{
|
||||
try
|
||||
{
|
||||
result = JOptionPane.showConfirmDialog(
|
||||
frame,
|
||||
"Are you sure you want to exit?", "Exit",
|
||||
JOptionPane.OK_CANCEL_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unexpected exception occurred while check for confirm required", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == JOptionPane.OK_OPTION)
|
||||
{
|
||||
shutdownClient();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
container = new JPanel();
|
||||
container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
|
||||
@@ -550,7 +575,7 @@ public class ClientUI
|
||||
SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(frame,
|
||||
"OpenOSRS has not yet been updated to work with the latest\n"
|
||||
+ "game update, it will work with reduced functionality until then.",
|
||||
"RuneLite is outdated", INFORMATION_MESSAGE));
|
||||
"OpenOSRS is outdated", INFORMATION_MESSAGE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,6 +594,45 @@ public class ClientUI
|
||||
return false;
|
||||
}
|
||||
|
||||
private void shutdownClient()
|
||||
{
|
||||
saveClientBoundsConfig();
|
||||
ClientShutdown csev = new ClientShutdown();
|
||||
eventBus.post(ClientShutdown.class, csev);
|
||||
new Thread(() ->
|
||||
{
|
||||
csev.waitForAllConsumers(Duration.ofSeconds(10));
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
// The client can call System.exit when it's done shutting down
|
||||
// if it doesn't though, we want to exit anyway, so race it
|
||||
int clientShutdownWaitMS;
|
||||
if (client instanceof Client)
|
||||
{
|
||||
((Client) client).stopNow();
|
||||
clientShutdownWaitMS = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it will continue rendering for about 4 seconds before attempting shutdown if its vanilla
|
||||
client.stop();
|
||||
frame.setVisible(false);
|
||||
clientShutdownWaitMS = 6000;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(clientShutdownWaitMS);
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
System.exit(0);
|
||||
}, "OpenOSRS Shutdown").start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint this component to target graphics
|
||||
*
|
||||
@@ -654,7 +718,27 @@ public class ClientUI
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cursor for client window. Requires ${@link ClientUI#init(RuneLite)} to be called first.
|
||||
* Returns current cursor set on game container
|
||||
*
|
||||
* @return awt cursor
|
||||
*/
|
||||
public Cursor getCurrentCursor()
|
||||
{
|
||||
return container.getCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current custom cursor or default system cursor if cursor is not set
|
||||
*
|
||||
* @return awt cursor
|
||||
*/
|
||||
public Cursor getDefaultCursor()
|
||||
{
|
||||
return defaultCursor != null ? defaultCursor : Cursor.getDefaultCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cursor for client window. Requires ${@link ClientUI#init()} to be called first.
|
||||
* FIXME: This is working properly only on Windows, Linux and Mac are displaying cursor incorrectly
|
||||
*
|
||||
* @param image cursor image
|
||||
@@ -669,7 +753,18 @@ public class ClientUI
|
||||
|
||||
final java.awt.Point hotspot = new java.awt.Point(0, 0);
|
||||
final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name);
|
||||
container.setCursor(cursorAwt);
|
||||
defaultCursor = cursorAwt;
|
||||
setCursor(cursorAwt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes cursor for client window. Requires ${@link ClientUI#init()} to be called first.
|
||||
*
|
||||
* @param cursor awt cursor
|
||||
*/
|
||||
public void setCursor(final Cursor cursor)
|
||||
{
|
||||
container.setCursor(cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -684,6 +779,7 @@ public class ClientUI
|
||||
return;
|
||||
}
|
||||
|
||||
defaultCursor = null;
|
||||
container.setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +128,12 @@ public class FlatTextField extends JPanel
|
||||
setBackground(color, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestFocusInWindow()
|
||||
{
|
||||
return textField.requestFocusInWindow();
|
||||
}
|
||||
|
||||
public void setBackground(Color color, boolean saveColor)
|
||||
{
|
||||
if (color == null)
|
||||
|
||||
@@ -49,6 +49,7 @@ public abstract class Overlay implements LayoutableRenderableEntity
|
||||
private OverlayPriority priority = OverlayPriority.NONE;
|
||||
private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS;
|
||||
private final List<OverlayMenuEntry> menuEntries = new ArrayList<>();
|
||||
private boolean resizable;
|
||||
|
||||
protected Overlay()
|
||||
{
|
||||
|
||||
@@ -261,7 +261,7 @@ public class OverlayManager
|
||||
saveOverlay(overlay);
|
||||
}
|
||||
|
||||
private synchronized void rebuildOverlayLayers()
|
||||
synchronized void rebuildOverlayLayers()
|
||||
{
|
||||
for (OverlayLayer l : OverlayLayer.values())
|
||||
{
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@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.ui.overlay;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.overlay.components.ComponentConstants;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class OverlayPanel extends Overlay
|
||||
{
|
||||
protected final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
/**
|
||||
* Enables/disables automatic clearing of {@link this#getPanelComponent()} children after rendering (enabled by default)
|
||||
*/
|
||||
private boolean clearChildren = true;
|
||||
|
||||
/**
|
||||
* Enables/disables automatic font size changes based on panel component size relative to default panel component size.
|
||||
*/
|
||||
private boolean dynamicFont = false;
|
||||
|
||||
protected OverlayPanel()
|
||||
{
|
||||
super();
|
||||
setResizable(true);
|
||||
}
|
||||
|
||||
protected OverlayPanel(Plugin plugin)
|
||||
{
|
||||
super(plugin);
|
||||
setResizable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(final Graphics2D graphics)
|
||||
{
|
||||
final Dimension oldSize = panelComponent.getPreferredSize();
|
||||
|
||||
if (getPreferredSize() != null)
|
||||
{
|
||||
panelComponent.setPreferredSize(getPreferredSize());
|
||||
|
||||
if (dynamicFont)
|
||||
{
|
||||
if (getPreferredSize().width >= ComponentConstants.STANDARD_WIDTH * 1.3)
|
||||
{
|
||||
graphics.setFont(FontManager.getRunescapeBoldFont());
|
||||
}
|
||||
else if (getPreferredSize().width <= ComponentConstants.STANDARD_WIDTH * 0.8)
|
||||
{
|
||||
graphics.setFont(FontManager.getRunescapeSmallFont());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Dimension dimension = panelComponent.render(graphics);
|
||||
|
||||
if (clearChildren)
|
||||
{
|
||||
panelComponent.getChildren().clear();
|
||||
}
|
||||
|
||||
panelComponent.setPreferredSize(oldSize);
|
||||
return dimension;
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,10 @@
|
||||
package net.runelite.client.ui.overlay;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.primitives.Ints;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
@@ -60,6 +62,7 @@ import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.input.MouseAdapter;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.MiscUtils;
|
||||
@@ -71,21 +74,29 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
private static final int BORDER = 5;
|
||||
private static final int BORDER_TOP = BORDER + 15;
|
||||
private static final int PADDING = 2;
|
||||
private static final int MIN_OVERLAY_SIZE = 32;
|
||||
private static final int OVERLAY_RESIZE_TOLERANCE = 5;
|
||||
private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80);
|
||||
private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50);
|
||||
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_RESIZING_COLOR = new Color(255, 0, 255, 200);
|
||||
private final Client client;
|
||||
private final OverlayManager overlayManager;
|
||||
private final RuneLiteConfig runeLiteConfig;
|
||||
private final ClientUI clientUI;
|
||||
|
||||
// Overlay movement variables
|
||||
private final Point overlayOffset = new Point();
|
||||
private final Point mousePosition = new Point();
|
||||
private Overlay movedOverlay;
|
||||
private Overlay currentManagedOverlay;
|
||||
private Rectangle currentManagedBounds;
|
||||
private boolean inOverlayManagingMode;
|
||||
private boolean inOverlayResizingMode;
|
||||
private boolean inOverlayDraggingMode;
|
||||
private boolean inMenuEntryMode;
|
||||
private boolean startedMovingOverlay;
|
||||
private MenuEntry[] menuEntries;
|
||||
|
||||
// Overlay state validation
|
||||
@@ -106,11 +117,13 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
final RuneLiteConfig runeLiteConfig,
|
||||
final MouseManager mouseManager,
|
||||
final KeyManager keyManager,
|
||||
final EventBus eventbus)
|
||||
final EventBus eventbus,
|
||||
final ClientUI clientUI)
|
||||
{
|
||||
this.client = client;
|
||||
this.overlayManager = overlayManager;
|
||||
this.runeLiteConfig = runeLiteConfig;
|
||||
this.clientUI = clientUI;
|
||||
keyManager.registerKeyListener(this);
|
||||
mouseManager.registerMouseListener(this);
|
||||
|
||||
@@ -123,7 +136,8 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
{
|
||||
if (!event.isFocused())
|
||||
{
|
||||
inOverlayDraggingMode = false;
|
||||
inOverlayManagingMode = false;
|
||||
resetOverlayManagementMode();
|
||||
inMenuEntryMode = false;
|
||||
menuEntries = null;
|
||||
}
|
||||
@@ -202,7 +216,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
OverlayUtil.setGraphicProperties(graphics);
|
||||
|
||||
// Draw snap corners
|
||||
if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null && movedOverlay.getPosition() != OverlayPosition.DETACHED)
|
||||
if (inOverlayDraggingMode && layer == OverlayLayer.UNDER_WIDGETS && currentManagedOverlay != null && currentManagedOverlay.getPosition() != OverlayPosition.DETACHED)
|
||||
{
|
||||
final OverlayBounds translatedSnapCorners = snapCorners.translated(
|
||||
-SNAP_CORNER_SIZE.width,
|
||||
@@ -294,12 +308,19 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
|
||||
if (!bounds.isEmpty())
|
||||
{
|
||||
if (inOverlayDraggingMode)
|
||||
if (inOverlayManagingMode)
|
||||
{
|
||||
final Color previous = graphics.getColor();
|
||||
graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR);
|
||||
if (inOverlayResizingMode && currentManagedOverlay == overlay)
|
||||
{
|
||||
graphics.setColor(MOVING_OVERLAY_RESIZING_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.setColor(inOverlayDraggingMode && currentManagedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR);
|
||||
}
|
||||
|
||||
graphics.draw(bounds);
|
||||
graphics.setColor(previous);
|
||||
graphics.setPaint(paint);
|
||||
}
|
||||
|
||||
if (!client.isMenuOpen() && !client.isSpellSelected() && bounds.contains(mouse))
|
||||
@@ -319,7 +340,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
@Override
|
||||
public MouseEvent mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (!inOverlayDraggingMode)
|
||||
if (!inOverlayManagingMode)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
@@ -327,71 +348,205 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
final Point mousePoint = mouseEvent.getPoint();
|
||||
mousePosition.setLocation(mousePoint);
|
||||
|
||||
synchronized (overlayManager)
|
||||
if (currentManagedOverlay == null)
|
||||
{
|
||||
for (Overlay overlay : overlayManager.getOverlays())
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||
{
|
||||
overlayManager.resetOverlay(currentManagedOverlay);
|
||||
}
|
||||
else if (SwingUtilities.isLeftMouseButton(mouseEvent))
|
||||
{
|
||||
final Point offset = new Point(mousePoint.x, mousePoint.y);
|
||||
offset.translate(-currentManagedOverlay.getBounds().x, -currentManagedOverlay.getBounds().y);
|
||||
overlayOffset.setLocation(offset);
|
||||
|
||||
inOverlayResizingMode = currentManagedOverlay != null && currentManagedOverlay.isResizable() && clientUI.getCurrentCursor() != clientUI.getDefaultCursor();
|
||||
inOverlayDraggingMode = !inOverlayResizingMode;
|
||||
startedMovingOverlay = true;
|
||||
currentManagedBounds = new Rectangle(currentManagedOverlay.getBounds());
|
||||
}
|
||||
else
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
mouseEvent.consume();
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseMoved(MouseEvent mouseEvent)
|
||||
{
|
||||
if (!inOverlayManagingMode)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Point mousePoint = mouseEvent.getPoint();
|
||||
mousePosition.setLocation(mousePoint);
|
||||
|
||||
if (!inOverlayResizingMode && !inOverlayDraggingMode)
|
||||
{
|
||||
currentManagedOverlay = null;
|
||||
|
||||
synchronized (overlayManager)
|
||||
{
|
||||
final OverlayPosition overlayPosition = getCorrectedOverlayPosition(overlay);
|
||||
|
||||
if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP)
|
||||
for (Overlay overlay : overlayManager.getOverlays())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (overlay.getBounds().contains(mousePoint))
|
||||
{
|
||||
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||
final Rectangle bounds = overlay.getBounds();
|
||||
if (bounds.contains(mousePoint))
|
||||
{
|
||||
overlayManager.resetOverlay(overlay);
|
||||
currentManagedOverlay = overlay;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
final Point offset = new Point(mousePoint.x, mousePoint.y);
|
||||
offset.translate(-overlay.getBounds().x, -overlay.getBounds().y);
|
||||
overlayOffset.setLocation(offset);
|
||||
|
||||
mousePoint.translate(-offset.x, -offset.y);
|
||||
movedOverlay = overlay;
|
||||
movedOverlay.setPreferredPosition(null);
|
||||
movedOverlay.setPreferredLocation(mousePoint);
|
||||
overlayManager.saveOverlay(movedOverlay);
|
||||
}
|
||||
|
||||
mouseEvent.consume();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentManagedOverlay == null || !currentManagedOverlay.isResizable())
|
||||
{
|
||||
clientUI.setCursor(clientUI.getDefaultCursor());
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Rectangle toleranceRect = new Rectangle(currentManagedOverlay.getBounds());
|
||||
toleranceRect.grow(-OVERLAY_RESIZE_TOLERANCE, -OVERLAY_RESIZE_TOLERANCE);
|
||||
final int outcode = toleranceRect.outcode(mouseEvent.getPoint());
|
||||
|
||||
switch (outcode)
|
||||
{
|
||||
case Rectangle.OUT_TOP:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_TOP | Rectangle.OUT_LEFT:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_LEFT:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_LEFT | Rectangle.OUT_BOTTOM:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_BOTTOM:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_BOTTOM | Rectangle.OUT_RIGHT:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_RIGHT:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
|
||||
break;
|
||||
case Rectangle.OUT_RIGHT | Rectangle.OUT_TOP:
|
||||
clientUI.setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
|
||||
break;
|
||||
default:
|
||||
// center
|
||||
clientUI.setCursor(clientUI.getDefaultCursor());
|
||||
}
|
||||
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseDragged(MouseEvent mouseEvent)
|
||||
{
|
||||
if (!inOverlayDraggingMode)
|
||||
if (!inOverlayManagingMode)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Point p = mouseEvent.getPoint();
|
||||
mousePosition.setLocation(p);
|
||||
|
||||
if (currentManagedOverlay == null)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Point mousePoint = mouseEvent.getPoint();
|
||||
mousePosition.setLocation(mousePoint);
|
||||
final Rectangle canvasRect = new Rectangle(client.getRealDimensions());
|
||||
|
||||
if (!canvasRect.contains(mousePoint))
|
||||
if (!canvasRect.contains(p))
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
if (movedOverlay != null)
|
||||
if (inOverlayResizingMode)
|
||||
{
|
||||
final Rectangle r = currentManagedBounds;
|
||||
|
||||
final int dx = p.x - r.x;
|
||||
final int dy = p.y - r.y;
|
||||
switch (clientUI.getCurrentCursor().getType())
|
||||
{
|
||||
case Cursor.N_RESIZE_CURSOR:
|
||||
int height = r.height - dy;
|
||||
r.setRect(r.x, r.y + dy, r.width, height);
|
||||
break;
|
||||
case Cursor.NW_RESIZE_CURSOR:
|
||||
int width = r.width - dx;
|
||||
height = r.height - dy;
|
||||
r.setRect(r.x + dx, r.y + dy, width, height);
|
||||
break;
|
||||
case Cursor.W_RESIZE_CURSOR:
|
||||
width = r.width - dx;
|
||||
r.setRect(r.x + dx, r.y, width, r.height);
|
||||
break;
|
||||
case Cursor.SW_RESIZE_CURSOR:
|
||||
width = r.width - dx;
|
||||
height = dy;
|
||||
r.setRect(r.x + dx, r.y, width, height);
|
||||
break;
|
||||
case Cursor.S_RESIZE_CURSOR:
|
||||
height = dy;
|
||||
r.setRect(r.x, r.y, r.width, height);
|
||||
break;
|
||||
case Cursor.SE_RESIZE_CURSOR:
|
||||
width = dx;
|
||||
height = dy;
|
||||
r.setRect(r.x, r.y, width, height);
|
||||
break;
|
||||
case Cursor.E_RESIZE_CURSOR:
|
||||
width = dx;
|
||||
r.setRect(r.x, r.y, width, r.height);
|
||||
break;
|
||||
case Cursor.NE_RESIZE_CURSOR:
|
||||
width = dx;
|
||||
height = r.height - dy;
|
||||
r.setRect(r.x, r.y + dy, width, height);
|
||||
break;
|
||||
default:
|
||||
// center
|
||||
}
|
||||
|
||||
currentManagedOverlay.setPreferredSize(new Dimension(Math.max(MIN_OVERLAY_SIZE, currentManagedBounds.width), Math.max(MIN_OVERLAY_SIZE, currentManagedBounds.height)));
|
||||
|
||||
if (currentManagedOverlay.getPreferredLocation() != null)
|
||||
{
|
||||
currentManagedOverlay.setPreferredLocation(currentManagedBounds.getLocation());
|
||||
}
|
||||
}
|
||||
else if (inOverlayDraggingMode)
|
||||
{
|
||||
final Dimension realDimension = client.getRealDimensions();
|
||||
mousePoint.translate(-overlayOffset.x, -overlayOffset.y);
|
||||
mousePoint.x = MiscUtils.clamp(mousePoint.x, 0, Math.max(0, realDimension.width - movedOverlay.getBounds().width));
|
||||
mousePoint.y = MiscUtils.clamp(mousePoint.y, 0, Math.max(0, realDimension.height - movedOverlay.getBounds().height));
|
||||
movedOverlay.setPreferredPosition(null);
|
||||
movedOverlay.setPreferredLocation(mousePoint);
|
||||
mouseEvent.consume();
|
||||
p.translate(-overlayOffset.x, -overlayOffset.y);
|
||||
p.x = Ints.constrainToRange(p.x, 0, Math.max(0, realDimension.width - currentManagedOverlay.getBounds().width));
|
||||
p.y = Ints.constrainToRange(p.y, 0, Math.max(0, realDimension.height - currentManagedOverlay.getBounds().height));
|
||||
currentManagedOverlay.setPreferredPosition(null);
|
||||
currentManagedOverlay.setPreferredLocation(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
if (startedMovingOverlay)
|
||||
{
|
||||
// Move currently moved overlay to correct layer
|
||||
overlayManager.rebuildOverlayLayers();
|
||||
startedMovingOverlay = false;
|
||||
}
|
||||
|
||||
return mouseEvent;
|
||||
@@ -400,39 +555,40 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
@Override
|
||||
public MouseEvent mouseReleased(MouseEvent mouseEvent)
|
||||
{
|
||||
if (movedOverlay != null)
|
||||
if (!inOverlayManagingMode || currentManagedOverlay == null || (!inOverlayDraggingMode && !inOverlayResizingMode))
|
||||
{
|
||||
mousePosition.setLocation(-1, -1);
|
||||
|
||||
// do not snapcorner detached overlays
|
||||
if (movedOverlay.getPosition() != OverlayPosition.DETACHED)
|
||||
{
|
||||
final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height);
|
||||
|
||||
for (Rectangle snapCorner : snapCorners.getBounds())
|
||||
{
|
||||
if (snapCorner.contains(mouseEvent.getPoint()))
|
||||
{
|
||||
OverlayPosition position = snapCorners.fromBounds(snapCorner);
|
||||
|
||||
if (position == movedOverlay.getPosition())
|
||||
{
|
||||
// overlay moves back to default position
|
||||
position = null;
|
||||
}
|
||||
|
||||
movedOverlay.setPreferredPosition(position);
|
||||
movedOverlay.setPreferredLocation(null); // from dragging
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlayManager.saveOverlay(movedOverlay);
|
||||
movedOverlay = null;
|
||||
mouseEvent.consume();
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
mousePosition.setLocation(-1, -1);
|
||||
|
||||
// do not snapcorner detached overlays
|
||||
if (currentManagedOverlay.getPosition() != OverlayPosition.DETACHED && inOverlayDraggingMode)
|
||||
{
|
||||
final OverlayBounds snapCorners = this.snapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height);
|
||||
|
||||
for (Rectangle snapCorner : snapCorners.getBounds())
|
||||
{
|
||||
if (snapCorner.contains(mouseEvent.getPoint()))
|
||||
{
|
||||
OverlayPosition position = snapCorners.fromBounds(snapCorner);
|
||||
|
||||
if (position == currentManagedOverlay.getPosition())
|
||||
{
|
||||
// overlay moves back to default position
|
||||
position = null;
|
||||
}
|
||||
|
||||
currentManagedOverlay.setPreferredPosition(position);
|
||||
currentManagedOverlay.setPreferredLocation(null); // from dragging
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overlayManager.saveOverlay(currentManagedOverlay);
|
||||
resetOverlayManagementMode();
|
||||
mouseEvent.consume();
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@@ -446,7 +602,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
{
|
||||
if (e.isAltDown())
|
||||
{
|
||||
inOverlayDraggingMode = true;
|
||||
inOverlayManagingMode = true;
|
||||
}
|
||||
|
||||
if (e.isShiftDown() && runeLiteConfig.menuEntryShift())
|
||||
@@ -460,7 +616,8 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
{
|
||||
if (!e.isAltDown())
|
||||
{
|
||||
inOverlayDraggingMode = false;
|
||||
inOverlayManagingMode = false;
|
||||
resetOverlayManagementMode();
|
||||
}
|
||||
|
||||
if (!e.isShiftDown())
|
||||
@@ -546,6 +703,15 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
return overlayPosition;
|
||||
}
|
||||
|
||||
private void resetOverlayManagementMode()
|
||||
{
|
||||
inOverlayResizingMode = false;
|
||||
inOverlayDraggingMode = false;
|
||||
currentManagedOverlay = null;
|
||||
currentManagedBounds = null;
|
||||
clientUI.setCursor(clientUI.getDefaultCursor());
|
||||
}
|
||||
|
||||
private boolean shouldInvalidateBounds()
|
||||
{
|
||||
final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX);
|
||||
|
||||
@@ -45,6 +45,7 @@ public class PanelComponent implements LayoutableRenderableEntity
|
||||
private Point preferredLocation = new Point();
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private Dimension preferredSize = new Dimension(ComponentConstants.STANDARD_WIDTH, 0);
|
||||
|
||||
@Setter
|
||||
@@ -58,7 +59,7 @@ public class PanelComponent implements LayoutableRenderableEntity
|
||||
private ComponentOrientation orientation = ComponentOrientation.VERTICAL;
|
||||
|
||||
@Setter
|
||||
private int wrapping = -1;
|
||||
private boolean wrap = false;
|
||||
|
||||
@Setter
|
||||
private Rectangle border = new Rectangle(
|
||||
@@ -114,12 +115,23 @@ public class PanelComponent implements LayoutableRenderableEntity
|
||||
int totalWidth = 0;
|
||||
|
||||
// Render all children
|
||||
for (int i = 0; i < children.size(); i++)
|
||||
for (final LayoutableRenderableEntity child : children)
|
||||
{
|
||||
final LayoutableRenderableEntity child = children.get(i);
|
||||
// Correctly propagate child dimensions based on orientation and wrapping
|
||||
if (!wrap)
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case VERTICAL:
|
||||
child.setPreferredSize(new Dimension(childPreferredSize.width, 0));
|
||||
break;
|
||||
case HORIZONTAL:
|
||||
child.setPreferredSize(new Dimension(0, childPreferredSize.height));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
child.setPreferredLocation(new Point(x, y));
|
||||
child.setPreferredSize(childPreferredSize);
|
||||
final Dimension childDimension = child.render(graphics);
|
||||
|
||||
switch (orientation)
|
||||
@@ -140,28 +152,38 @@ public class PanelComponent implements LayoutableRenderableEntity
|
||||
totalWidth = Math.max(totalWidth, width);
|
||||
totalHeight = Math.max(totalHeight, height);
|
||||
|
||||
if (wrapping > 0 && i < children.size() - 1 && (i + 1) % wrapping == 0)
|
||||
if (!wrap)
|
||||
{
|
||||
switch (orientation)
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (orientation)
|
||||
{
|
||||
case VERTICAL:
|
||||
{
|
||||
case VERTICAL:
|
||||
if (childPreferredSize.height > 0 && height >= childPreferredSize.height)
|
||||
{
|
||||
height = 0;
|
||||
y = baseY;
|
||||
int diff = childDimension.width + gap.x;
|
||||
x += diff;
|
||||
width += diff;
|
||||
break;
|
||||
}
|
||||
case HORIZONTAL:
|
||||
|
||||
break;
|
||||
}
|
||||
case HORIZONTAL:
|
||||
{
|
||||
if (childPreferredSize.width > 0 && width >= childPreferredSize.width)
|
||||
{
|
||||
width = 0;
|
||||
x = baseX;
|
||||
int diff = childDimension.height + gap.y;
|
||||
y += diff;
|
||||
height += diff;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,19 +36,20 @@ import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPanel;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.ComponentOrientation;
|
||||
import net.runelite.client.ui.overlay.components.InfoBoxComponent;
|
||||
import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
|
||||
@Singleton
|
||||
public class InfoBoxOverlay extends Overlay
|
||||
public class InfoBoxOverlay extends OverlayPanel
|
||||
{
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
private static final int GAP = 1;
|
||||
private static final int DEFAULT_WRAP_COUNT = 4;
|
||||
|
||||
private final InfoBoxManager infoboxManager;
|
||||
private final TooltipManager tooltipManager;
|
||||
private final Client client;
|
||||
@@ -66,10 +67,12 @@ public class InfoBoxOverlay extends Overlay
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
setPosition(OverlayPosition.TOP_LEFT);
|
||||
setClearChildren(false);
|
||||
|
||||
panelComponent.setWrap(true);
|
||||
panelComponent.setBackgroundColor(null);
|
||||
panelComponent.setBorder(new Rectangle());
|
||||
panelComponent.setGap(new Point(1, 1));
|
||||
panelComponent.setGap(new Point(GAP, GAP));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,12 +85,12 @@ public class InfoBoxOverlay extends Overlay
|
||||
return null;
|
||||
}
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
panelComponent.setWrapping(config.infoBoxWrap());
|
||||
// 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.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
|
||||
|
||||
for (InfoBox box : infoBoxes)
|
||||
{
|
||||
@@ -107,10 +110,11 @@ public class InfoBoxOverlay extends Overlay
|
||||
}
|
||||
infoBoxComponent.setImage(box.getScaledImage());
|
||||
infoBoxComponent.setTooltip(box.getTooltip());
|
||||
infoBoxComponent.setPreferredSize(new Dimension(config.infoBoxSize(), config.infoBoxSize()));
|
||||
panelComponent.getChildren().add(infoBoxComponent);
|
||||
}
|
||||
|
||||
final Dimension dimension = panelComponent.render(graphics);
|
||||
final Dimension dimension = super.render(graphics);
|
||||
|
||||
// Handle tooltips
|
||||
final Point mouse = new Point(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY());
|
||||
@@ -135,6 +139,7 @@ public class InfoBoxOverlay extends Overlay
|
||||
}
|
||||
}
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
return dimension;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,27 +24,14 @@
|
||||
*/
|
||||
package net.runelite.client.ui.overlay.tooltip;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
|
||||
@Singleton
|
||||
public class TooltipManager
|
||||
{
|
||||
private final ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private TooltipManager(final ConfigManager configManager)
|
||||
{
|
||||
this.configManager = configManager;
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final List<Tooltip> tooltips = new ArrayList<>();
|
||||
|
||||
@@ -62,17 +49,4 @@ public class TooltipManager
|
||||
{
|
||||
tooltips.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(final ConfigChanged event)
|
||||
{
|
||||
// Temporary fix for resetting repositioned tooltip overlay
|
||||
// TODO: Remove this eventually
|
||||
if (event.getGroup().equals("runelite") &&
|
||||
event.getKey().equals("TooltipOverlay_preferredLocation") &&
|
||||
!Strings.isNullOrEmpty(event.getNewValue()))
|
||||
{
|
||||
configManager.unsetConfiguration(event.getGroup(), event.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.AccessLevel;
|
||||
@@ -12,6 +14,8 @@ import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.OpenOSRSConfig;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ClientShutdown;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.ui.RuneLiteSplashScreen;
|
||||
import org.jgroups.Address;
|
||||
@@ -38,7 +42,7 @@ public class Groups extends ReceiverAdapter
|
||||
private final PublishSubject<Message> messageObjectSubject = PublishSubject.create();
|
||||
|
||||
@Inject
|
||||
public Groups(OpenOSRSConfig openOSRSConfig) throws Exception
|
||||
public Groups(OpenOSRSConfig openOSRSConfig, EventBus eventBus) throws Exception
|
||||
{
|
||||
this.openOSRSConfig = openOSRSConfig;
|
||||
|
||||
@@ -47,6 +51,11 @@ public class Groups extends ReceiverAdapter
|
||||
.setReceiver(this)
|
||||
.setDiscardOwnMessages(true)
|
||||
.connect("openosrs");
|
||||
|
||||
eventBus.subscribe(ClientShutdown.class, this, (e) -> {
|
||||
Future<Void> f = close();
|
||||
e.waitFor(f);
|
||||
});
|
||||
}
|
||||
|
||||
public void broadcastSring(String command)
|
||||
@@ -134,10 +143,22 @@ public class Groups extends ReceiverAdapter
|
||||
{
|
||||
messageObjectSubject.onNext(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void close()
|
||||
private CompletableFuture<Void> close()
|
||||
{
|
||||
channel.close();
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
try
|
||||
{
|
||||
channel.close();
|
||||
future.complete(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
future.completeExceptionally(ex);
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,22 +41,18 @@ import java.awt.Toolkit;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiConsumer;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
@@ -67,7 +63,6 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
@@ -214,48 +209,6 @@ public class SwingUtil
|
||||
return trayIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add graceful exit callback.
|
||||
*
|
||||
* @param frame the frame
|
||||
* @param callback the callback
|
||||
* @param confirmRequired the confirm required
|
||||
*/
|
||||
public static void addGracefulExitCallback(@Nonnull final JFrame frame, @Nonnull final Runnable callback, @Nonnull final Callable<Boolean> confirmRequired)
|
||||
{
|
||||
frame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event)
|
||||
{
|
||||
int result = JOptionPane.OK_OPTION;
|
||||
|
||||
try
|
||||
{
|
||||
if (confirmRequired.call())
|
||||
{
|
||||
result = JOptionPane.showConfirmDialog(
|
||||
frame,
|
||||
"Are you sure you want to exit?", "Exit",
|
||||
JOptionPane.OK_CANCEL_OPTION,
|
||||
JOptionPane.QUESTION_MESSAGE);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unexpected exception occurred while check for confirm required", e);
|
||||
}
|
||||
|
||||
if (result == JOptionPane.OK_OPTION)
|
||||
{
|
||||
callback.run();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create swing button from navigation button.
|
||||
*
|
||||
|
||||
@@ -83,7 +83,7 @@ public class WeaponMap
|
||||
StyleMap.put(ItemID.BLACK_SWORD, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLACK_WARHAMMER, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLADE_OF_SAELDOR, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLADE_OF_SAELDOR_I, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLADE_OF_SAELDOR_C, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLADE_OF_SAELDOR_INACTIVE, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLESSED_AXE, WeaponStyle.MELEE);
|
||||
StyleMap.put(ItemID.BLUE_FLOWERS, WeaponStyle.MELEE);
|
||||
|
||||
@@ -8706,6 +8706,14 @@
|
||||
20621,
|
||||
20622
|
||||
],
|
||||
"tangleroot": [
|
||||
20661,
|
||||
24555,
|
||||
24557,
|
||||
24559,
|
||||
24561,
|
||||
24563
|
||||
],
|
||||
"rift guardian": [
|
||||
20665,
|
||||
20667,
|
||||
|
||||
Reference in New Issue
Block a user