runelite-client: add screen markers plugin

This commit is contained in:
Adam
2018-05-20 15:09:22 -04:00
parent af7b2e6c97
commit 9c4878e8da
9 changed files with 942 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* Copyright (c) 2018, 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.plugins.screenmarkers;
import java.awt.Color;
import java.awt.Rectangle;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ScreenMarker
{
private Rectangle bounds;
private String name;
private int borderThickness;
private Color color;
private Color fill;
private boolean visible;
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* 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.plugins.screenmarkers;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import javax.inject.Inject;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
public class ScreenMarkerCreationOverlay extends Overlay
{
@Inject
private ScreenMarkerPlugin plugin;
public ScreenMarkerCreationOverlay()
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
ScreenMarker marker = plugin.getCurrentMarker();
if (marker == null)
{
return null;
}
Rectangle bounds = marker.getBounds();
int thickness = marker.getBorderThickness();
int offset = thickness / 2;
int width = bounds.width - thickness;
int height = bounds.height - thickness;
graphics.setStroke(createStripedStroke(thickness));
graphics.setColor(marker.getColor());
graphics.drawRect(bounds.x + offset, bounds.y + offset, width, height);
return bounds.getSize();
}
private Stroke createStripedStroke(int thickness)
{
return new BasicStroke(thickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{9}, 0);
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* 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.plugins.screenmarkers;
import java.awt.Point;
import java.awt.event.MouseEvent;
import static java.lang.Math.max;
import static java.lang.Math.min;
import javax.swing.SwingUtilities;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.input.MouseListener;
@Slf4j
public class ScreenMarkerMouseListener extends MouseListener
{
private final ScreenMarkerPlugin plugin;
private Point lastMousePoint = null;
public ScreenMarkerMouseListener(ScreenMarkerPlugin plugin)
{
this.plugin = plugin;
}
@Override
public MouseEvent mouseClicked(MouseEvent event)
{
if (SwingUtilities.isMiddleMouseButton(event))
{
return event;
}
event.consume();
return event;
}
@Override
public MouseEvent mousePressed(MouseEvent event)
{
if (SwingUtilities.isMiddleMouseButton(event))
{
return event;
}
if (SwingUtilities.isLeftMouseButton(event))
{
lastMousePoint = event.getPoint();
plugin.startCreation(event.getPoint());
}
else if (plugin.isCreatingScreenMarker())
{
plugin.finishCreation(true);
lastMousePoint = null;
}
event.consume();
return event;
}
@Override
public MouseEvent mouseReleased(MouseEvent event)
{
if (SwingUtilities.isMiddleMouseButton(event))
{
return event;
}
if (SwingUtilities.isLeftMouseButton(event) && plugin.isCreatingScreenMarker())
{
plugin.finishCreation(false);
}
event.consume();
return event;
}
@Override
public MouseEvent mouseDragged(MouseEvent event)
{
if (!plugin.isCreatingScreenMarker())
{
return event;
}
if (SwingUtilities.isLeftMouseButton(event))
{
Point currentPoint = event.getPoint();
int dx = currentPoint.x - lastMousePoint.x;
int dy = currentPoint.y - lastMousePoint.y;
//if shift is down, constrain proportions
if (event.isShiftDown() && dx != dy)
{
int x = dx;
if (dx > 0 || dy > 0)
{
dx = max(dx, dy);
dy = max(dy, x);
}
else
{
dx = min(dx, dy);
dy = min(dy, x);
}
}
plugin.resizeMarker(currentPoint, dx, dy);
lastMousePoint = currentPoint;
}
return event;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* Copyright (c) 2018, 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.plugins.screenmarkers;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics2D;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
public class ScreenMarkerOverlay extends Overlay
{
private final ScreenMarker marker;
private final ScreenMarkerRenderable screenMarkerRenderable;
public ScreenMarkerOverlay(ScreenMarker marker)
{
this.marker = marker;
setPosition(OverlayPosition.DETACHED);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
setPriority(OverlayPriority.HIGH);
setPreferredLocation(marker.getBounds().getLocation());
screenMarkerRenderable = new ScreenMarkerRenderable();
screenMarkerRenderable.setBorderThickness(marker.getBorderThickness());
screenMarkerRenderable.setColor(marker.getColor());
screenMarkerRenderable.setFill(marker.getFill());
screenMarkerRenderable.setStroke(new BasicStroke(marker.getBorderThickness()));
screenMarkerRenderable.setPreferredSize(marker.getBounds().getSize());
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!marker.isVisible())
{
return null;
}
return screenMarkerRenderable.render(graphics);
}
}

View File

@@ -0,0 +1,249 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* Copyright (c) 2018, 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.plugins.screenmarkers;
import com.google.common.base.Strings;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.ConfigChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.input.MouseManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.screenmarkers.ui.ScreenMarkerPluginPanel;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.PluginToolbar;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayRenderer;
@PluginDescriptor(
name = "Screen Markers"
)
@Slf4j
public class ScreenMarkerPlugin extends Plugin
{
private static final String PLUGIN_NAME = "Screen Markers";
private static final String CONFIG_GROUP = "screenmarkers";
private static final String CONFIG_KEY = "markers";
private static final String ICON_FILE = "panel_icon.png";
private static final String DEFAULT_MARKER_NAME = "Marker";
private static final Dimension DEFAULT_SIZE = new Dimension(2, 2);
@Inject
private EventBus eventBus;
@Inject
private ConfigManager configManager;
@Inject
private MouseManager mouseManager;
@Inject
private PluginToolbar pluginToolbar;
@Inject
private ScreenMarkerCreationOverlay overlay;
@Inject
private OverlayRenderer overlayRenderer;
private ScreenMarkerMouseListener mouseListener;
private ScreenMarkerPluginPanel pluginPanel;
private NavigationButton navigationButton;
@Getter
private List<ScreenMarker> screenMarkers = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private ScreenMarker currentMarker;
@Getter
private boolean creatingScreenMarker = false;
@Override
public Collection<Overlay> getOverlays()
{
List<Overlay> overlays = new ArrayList<>();
overlays.add(overlay);
for (ScreenMarker marker : screenMarkers)
{
ScreenMarkerOverlay screenMarkerOverlay = new ScreenMarkerOverlay(marker);
overlays.add(screenMarkerOverlay);
}
return overlays;
}
@Override
protected void startUp() throws Exception
{
screenMarkers = loadConfig(null);
pluginPanel = injector.getInstance(ScreenMarkerPluginPanel.class);
pluginPanel.init();
BufferedImage icon;
synchronized (ImageIO.class)
{
icon = ImageIO.read(ScreenMarkerPlugin.class.getResourceAsStream(ICON_FILE));
}
navigationButton = NavigationButton.builder()
.tooltip(PLUGIN_NAME)
.icon(icon)
.panel(pluginPanel)
.build();
pluginToolbar.addNavigation(navigationButton);
mouseListener = new ScreenMarkerMouseListener(this);
}
@Override
protected void shutDown() throws Exception
{
pluginToolbar.removeNavigation(navigationButton);
setMouseListenerEnabled(false);
creatingScreenMarker = false;
screenMarkers.clear();
pluginPanel = null;
currentMarker = null;
mouseListener = null;
navigationButton = null;
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (screenMarkers.isEmpty() && event.getGroup().equals(CONFIG_GROUP) && event.getKey().equals(CONFIG_KEY))
{
screenMarkers = loadConfig(event.getNewValue());
}
}
public void setMouseListenerEnabled(boolean enabled)
{
if (enabled)
{
mouseManager.registerMouseListener(mouseListener);
}
else
{
mouseManager.unregisterMouseListener(mouseListener);
}
}
public void startCreation(Point location)
{
currentMarker = new ScreenMarker(
new Rectangle(location, DEFAULT_SIZE),
DEFAULT_MARKER_NAME,
pluginPanel.getSelectedBorderThickness(),
pluginPanel.getSelectedColor(),
pluginPanel.getSelectedFillColor(),
true
);
creatingScreenMarker = true;
}
public void finishCreation(boolean aborted)
{
if (!aborted)
{
setMouseListenerEnabled(false);
pluginPanel.setCreationEnabled(false);
screenMarkers.add(currentMarker);
pluginPanel.rebuild();
updateConfig();
overlayRenderer.rebuildOverlays();
}
creatingScreenMarker = false;
currentMarker = null;
}
public void deleteMarker(ScreenMarker marker)
{
screenMarkers.remove(marker);
pluginPanel.rebuild();
updateConfig();
overlayRenderer.rebuildOverlays();
}
public void resizeMarker(Point point, int dx, int dy)
{
//TODO: Allow resizing below base point
Dimension currentSize = currentMarker.getBounds().getSize();
currentMarker.getBounds().setSize(new Dimension(currentSize.width + dx, currentSize.height + dy));
}
public void updateConfig()
{
if (screenMarkers.isEmpty())
{
configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_KEY);
return;
}
final Gson gson = new Gson();
String json = gson.toJson(screenMarkers);
configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, json);
}
private List<ScreenMarker> loadConfig(String json)
{
if (json == null)
{
json = configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY);
}
if (Strings.isNullOrEmpty(json))
{
return Collections.emptyList();
}
final Gson gson = new Gson();
return gson.fromJson(json, new TypeToken<ArrayList<ScreenMarker>>()
{
}.getType());
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* 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.plugins.screenmarkers;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Stroke;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
public class ScreenMarkerRenderable implements LayoutableRenderableEntity
{
@Getter(AccessLevel.PACKAGE)
private Dimension preferredSize;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private int borderThickness;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private Color color;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private Color fill;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
private Stroke stroke;
@Override
public Dimension render(Graphics2D graphics)
{
int thickness = borderThickness;
int width = preferredSize.width;
int height = preferredSize.height;
//draw the fill
graphics.setColor(fill);
graphics.fillRect(thickness, thickness, width - thickness * 2, height - thickness * 2);
//because the stroke is centered on the rectangle we draw, we need to translate where we draw the rectangle
//this is to ensure that the rectangle we draw is our preferred size
int offset = thickness / 2;
graphics.setColor(color);
graphics.setStroke(stroke);
graphics.drawRect(offset, offset, width - thickness, height - thickness);
return preferredSize;
}
@Override
public void setPreferredSize(Dimension preferredSize)
{
this.preferredSize = preferredSize;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* 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.plugins.screenmarkers.ui;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import net.runelite.client.plugins.screenmarkers.ScreenMarker;
import net.runelite.client.plugins.screenmarkers.ScreenMarkerPlugin;
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
public class ScreenMarkerPanel extends JPanel
{
private static final String DELETE_TEXT = "Delete";
private static final String HIDE_TEXT = "Hide";
private static final String SHOW_TEXT = "Show";
private final ScreenMarkerPlugin plugin;
private final ScreenMarker marker;
private JToggleButton visibleToggle;
public ScreenMarkerPanel(ScreenMarkerPlugin plugin, ScreenMarker marker)
{
this.plugin = plugin;
this.marker = marker;
construct();
}
private void construct()
{
setLayout(new GridLayout(0, 1, 0, 3));
JPanel container = new JPanel(new FlowLayout());
JButton deleteButton = new JButton(DELETE_TEXT);
deleteButton.addActionListener(l -> plugin.deleteMarker(marker));
boolean selected = !marker.isVisible();
visibleToggle = new JToggleButton(selected ? SHOW_TEXT : HIDE_TEXT, selected);
visibleToggle.setFocusable(false);
visibleToggle.addActionListener(l ->
{
boolean visible = !visibleToggle.isSelected();
marker.setVisible(visible);
visibleToggle.setText(visible ? HIDE_TEXT : SHOW_TEXT);
plugin.updateConfig();
});
container.add(new JShadowedLabel(marker.getName()));
container.add(visibleToggle);
container.add(deleteButton);
add(container);
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (c) 2018, Kamiel, <https://github.com/Kamielvf>
* 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.plugins.screenmarkers.ui;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import lombok.Getter;
import net.runelite.client.plugins.screenmarkers.ScreenMarker;
import net.runelite.client.plugins.screenmarkers.ScreenMarkerPlugin;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
@Singleton
public class ScreenMarkerPluginPanel extends PluginPanel
{
private static final String TITLE = "Screen Markers";
private static final Color DEFAULT_COLOR = Color.BLUE;
private static final int DEFAULT_BORDER_THICKNESS = 5;
private static final int DEFAULT_FILL_OPACITY = 75;
private static final String COLOR_PICKER_TITLE = "Choose a color..";
private static final String COLOR_TEXT = "Color";
private static final String FILL_TEXT = "Fill";
private static final String NEW_TEXT = "New";
private static final String CANCEL_TEXT = "Cancel";
private static final Color CANCEL_BUTTON_COLOR = Color.RED.darker();
@Inject
private ScreenMarkerPlugin plugin;
private JPanel markerView;
private JButton markerButton;
@Getter
private Color selectedColor = DEFAULT_COLOR;
@Getter
private Color selectedFillColor = new Color(DEFAULT_COLOR.getRed(), DEFAULT_COLOR.getGreen(), DEFAULT_COLOR.getBlue(), DEFAULT_FILL_OPACITY);
@Getter
private int selectedBorderThickness = DEFAULT_BORDER_THICKNESS;
private boolean creationEnabled = false;
public void init()
{
setLayout(new BorderLayout());
JPanel northPanel = new JPanel(new GridLayout(0, 2, 0, 3));
markerButton = new JButton(NEW_TEXT);
markerButton.setFocusable(false);
markerButton.addActionListener(l -> startOrCancelCreation());
northPanel.add(new JShadowedLabel(TITLE));
northPanel.add(new JLabel());
northPanel.add(new JShadowedLabel("Border size:"));
northPanel.add(createBorderThicknessSpinner());
northPanel.add(new JShadowedLabel("Border color:"));
northPanel.add(createBorderColorButton());
northPanel.add(new JShadowedLabel("Fill color:"));
northPanel.add(createFillColorButton());
northPanel.add(markerButton);
JPanel centerPanel = new JPanel();
markerView = new JPanel(new GridLayout(0, 1, 0, 3));
for (ScreenMarker marker : plugin.getScreenMarkers())
{
markerView.add(new ScreenMarkerPanel(plugin, marker));
}
centerPanel.add(markerView, BorderLayout.NORTH);
add(northPanel, BorderLayout.NORTH);
add(centerPanel, BorderLayout.CENTER);
}
public void rebuild()
{
removeAll();
repaint();
revalidate();
init();
}
private void startOrCancelCreation()
{
creationEnabled = !creationEnabled;
plugin.setMouseListenerEnabled(creationEnabled);
setMarkerButtonState(creationEnabled);
}
public void setCreationEnabled(boolean creationEnabled)
{
this.creationEnabled = creationEnabled;
setMarkerButtonState(creationEnabled);
}
private void setMarkerButtonState(boolean selected)
{
markerButton.setSelected(selected);
markerButton.setText(selected ? CANCEL_TEXT : NEW_TEXT);
markerButton.setBackground(selected ? CANCEL_BUTTON_COLOR : null);
}
private JSpinner createBorderThicknessSpinner()
{
SpinnerModel model = new SpinnerNumberModel(selectedBorderThickness, 0, Integer.MAX_VALUE, 1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(5);
spinner.addChangeListener(ce -> selectedBorderThickness = (Integer) spinner.getValue());
return spinner;
}
private JButton createBorderColorButton()
{
JButton colorPicker = new JButton(COLOR_TEXT);
colorPicker.setFocusable(false);
colorPicker.setBackground(selectedColor);
colorPicker.addActionListener(e ->
{
final JFrame parent = new JFrame(COLOR_PICKER_TITLE);
JColorChooser jColorChooser = new JColorChooser(selectedColor);
jColorChooser.getSelectionModel().addChangeListener(e1 -> colorPicker.setBackground(jColorChooser.getColor()));
parent.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
selectedColor = jColorChooser.getColor();
}
});
parent.add(jColorChooser);
parent.pack();
parent.setLocationRelativeTo(null);
parent.setVisible(true);
});
return colorPicker;
}
private JButton createFillColorButton()
{
JButton colorPicker = new JButton(FILL_TEXT);
colorPicker.setFocusable(false);
colorPicker.setBackground(selectedFillColor);
colorPicker.addActionListener(e ->
{
final JFrame parent = new JFrame(COLOR_PICKER_TITLE);
JColorChooser jColorChooser = new JColorChooser(selectedFillColor);
jColorChooser.getSelectionModel().addChangeListener(e1 -> colorPicker.setBackground(jColorChooser.getColor()));
parent.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
Color color = jColorChooser.getColor();
selectedFillColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), DEFAULT_FILL_OPACITY);
}
});
parent.add(jColorChooser);
parent.pack();
parent.setLocationRelativeTo(null);
parent.setVisible(true);
});
return colorPicker;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B