CustomClientResizing: New Plugin (#2091)

CustomClientResizing: New Plugin
This commit is contained in:
Owain van Brakel
2019-12-06 00:17:28 +01:00
committed by GitHub
14 changed files with 724 additions and 5 deletions

View File

@@ -0,0 +1,9 @@
package net.runelite.client.plugins.customclientresizing;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
@ConfigGroup(CustomClientResizingPlugin.CONFIG_GROUP)
public interface CustomClientResizingConfig extends Config
{
}

View File

@@ -0,0 +1,203 @@
package net.runelite.client.plugins.customclientresizing;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Provides;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.plugins.customclientresizing.ui.CustomClientResizingPluginPanel;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.ContainableFrame;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ImageUtil;
@PluginDescriptor(
name = "Custom Client Resizing",
description = "Resize the window to saved profiles",
tags = {"resize", "window", "position", "layout", "manage"},
type = PluginType.UTILITY,
enabledByDefault = false
)
public class CustomClientResizingPlugin extends Plugin
{
public static final String CONFIG_GROUP = "customclientresizing";
private static final String CONFIG_KEY = "customclientresizingprofiles";
private static final String PLUGIN_NAME = "Custom Client Resizing";
private static final String ICON_FILE = "panel_icon.png";
@Getter
private final List<CustomClientResizingProfile> customclientresizingProfiles = new ArrayList<>();
@Inject
private Client client;
@Inject
private CustomClientResizingConfig config;
@Inject
private ClientToolbar clientToolbar;
@Inject
private ConfigManager configManager;
@Inject
private ClientUI clientUi;
private CustomClientResizingPluginPanel pluginPanel;
private NavigationButton navigationButton;
private NavigationButton titleBarButton;
@Provides
CustomClientResizingConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(CustomClientResizingConfig.class);
}
@Override
protected void startUp()
{
loadConfig(configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY)).forEach(customclientresizingProfiles::add);
pluginPanel = injector.getInstance(CustomClientResizingPluginPanel.class);
pluginPanel.rebuild();
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), ICON_FILE);
navigationButton = NavigationButton.builder()
.tooltip(PLUGIN_NAME)
.icon(icon)
.priority(1)
.panel(pluginPanel)
.build();
titleBarButton = NavigationButton.builder()
.tab(false)
.tooltip("Set resize profile")
.icon(icon)
.onClick(() ->
{
ContainableFrame frame = clientUi.getFrame();
CustomClientResizingProfile active = customclientresizingProfiles.stream().filter(CustomClientResizingProfile::isVisible).findFirst().orElse(null);
if (active == null)
{
return;
}
Rectangle bounds = new Rectangle(
active.getPosition().width, active.getPosition().height,
active.getSize().width, active.getSize().height
);
if (!clientUi.isSidebarOpen())
{
bounds.width -= clientUi.getPluginToolbar().getWidth();
}
if (clientUi.getPluginPanel() == null)
{
bounds.width -= pluginPanel.getWrappedPanel().getPreferredSize().width;
}
frame.setBounds(bounds);
frame.revalidateMinimumSize();
})
.build();
clientToolbar.addNavigation(titleBarButton);
clientToolbar.addNavigation(navigationButton);
}
@Override
protected void shutDown()
{
customclientresizingProfiles.clear();
clientToolbar.removeNavigation(navigationButton);
clientToolbar.removeNavigation(titleBarButton);
pluginPanel = null;
navigationButton = null;
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (customclientresizingProfiles.isEmpty() && event.getGroup().equals(CONFIG_GROUP) && event.getKey().equals(CONFIG_KEY))
{
loadConfig(event.getNewValue()).forEach(customclientresizingProfiles::add);
}
}
public void updateConfig()
{
if (customclientresizingProfiles.isEmpty())
{
configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_KEY);
return;
}
final Gson gson = new Gson();
final String json = gson
.toJson(customclientresizingProfiles);
configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, json);
}
private Stream<CustomClientResizingProfile> loadConfig(String json)
{
if (Strings.isNullOrEmpty(json))
{
return Stream.empty();
}
final Gson gson = new Gson();
final List<CustomClientResizingProfile> customclientresizingProfileData = gson.fromJson(json, new TypeToken<ArrayList<CustomClientResizingProfile>>()
{
}.getType());
return customclientresizingProfileData.stream();
}
public void addProfile()
{
ContainableFrame frame = clientUi.getFrame();
CustomClientResizingProfile profile = new CustomClientResizingProfile(
Instant.now().toEpochMilli(),
"Profile " + (customclientresizingProfiles.size() + 1),
new Dimension(frame.getX(), frame.getY()),
new Dimension(frame.getWidth(), frame.getHeight()),
false
);
customclientresizingProfiles.add(profile);
pluginPanel.updateProfiles();
updateConfig();
}
public void deleteProfile(final CustomClientResizingProfile profile)
{
customclientresizingProfiles.remove(profile);
pluginPanel.updateProfiles();
updateConfig();
}
public void disableProfiles()
{
customclientresizingProfiles.forEach(e -> e.setVisible(false));
pluginPanel.updateProfiles();
}
}

View File

@@ -0,0 +1,18 @@
package net.runelite.client.plugins.customclientresizing;
import java.awt.Dimension;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CustomClientResizingProfile
{
private long id;
private String name;
private Dimension position;
private Dimension size;
private boolean visible;
}

View File

@@ -0,0 +1,136 @@
package net.runelite.client.plugins.customclientresizing.ui;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import lombok.Getter;
import net.runelite.client.plugins.customclientresizing.CustomClientResizingPlugin;
import net.runelite.client.plugins.customclientresizing.CustomClientResizingProfile;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.util.ImageUtil;
@Singleton
public class CustomClientResizingPluginPanel extends PluginPanel
{
private static final ImageIcon ADD_ICON;
private static final ImageIcon ADD_HOVER_ICON;
private static final Color DEFAULT_BORDER_COLOR = Color.GREEN;
private static final Color DEFAULT_FILL_COLOR = new Color(0, 255, 0, 0);
private static final int DEFAULT_BORDER_THICKNESS = 3;
static
{
final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(CustomClientResizingPlugin.class, "add_icon.png");
ADD_ICON = new ImageIcon(addIcon);
ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f));
}
private final JLabel addMarker = new JLabel(ADD_ICON);
private final JLabel title = new JLabel();
private final JPanel markerView = new JPanel(new GridBagLayout());
@Inject
private CustomClientResizingPlugin plugin;
@Getter
private Color selectedColor = DEFAULT_BORDER_COLOR;
@Getter
private Color selectedFillColor = DEFAULT_FILL_COLOR;
@Getter
private int selectedBorderThickness = DEFAULT_BORDER_THICKNESS;
public void init()
{
setLayout(new BorderLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
JPanel northPanel = new JPanel(new BorderLayout());
northPanel.setBorder(new EmptyBorder(1, 0, 10, 0));
title.setText("Resize Profiles");
title.setForeground(Color.WHITE);
northPanel.add(title, BorderLayout.WEST);
northPanel.add(addMarker, BorderLayout.EAST);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
markerView.setBackground(ColorScheme.DARK_GRAY_COLOR);
updateProfiles();
addMarker.setToolTipText("Add new screen marker");
addMarker.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
plugin.addProfile();
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
addMarker.setIcon(ADD_HOVER_ICON);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
addMarker.setIcon(ADD_ICON);
}
});
centerPanel.add(markerView, BorderLayout.CENTER);
add(northPanel, BorderLayout.NORTH);
add(centerPanel, BorderLayout.CENTER);
}
public void rebuild()
{
removeAll();
repaint();
revalidate();
init();
}
public void updateProfiles()
{
markerView.removeAll();
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
constraints.gridx = 0;
constraints.gridy = 0;
for (final CustomClientResizingProfile marker : plugin.getCustomclientresizingProfiles())
{
markerView.add(new CustomClientResizingProfilePanel(plugin, marker), constraints);
constraints.gridy++;
markerView.add(Box.createRigidArea(new Dimension(0, 10)), constraints);
constraints.gridy++;
}
repaint();
revalidate();
}
}

View File

@@ -0,0 +1,349 @@
package net.runelite.client.plugins.customclientresizing.ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeListener;
import net.runelite.client.plugins.customclientresizing.CustomClientResizingPlugin;
import net.runelite.client.plugins.customclientresizing.CustomClientResizingProfile;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.components.FlatTextField;
import net.runelite.client.util.ImageUtil;
public class CustomClientResizingProfilePanel extends JPanel
{
private static final int DEFAULT_FILL_OPACITY = 75;
private static final Border NAME_BOTTOM_BORDER = new CompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.DARK_GRAY_COLOR),
BorderFactory.createLineBorder(ColorScheme.DARKER_GRAY_COLOR));
private static final ImageIcon VISIBLE_ICON;
private static final ImageIcon VISIBLE_HOVER_ICON;
private static final ImageIcon INVISIBLE_ICON;
private static final ImageIcon INVISIBLE_HOVER_ICON;
private static final ImageIcon DELETE_ICON;
private static final ImageIcon DELETE_HOVER_ICON;
static
{
final BufferedImage visibleImg = ImageUtil.getResourceStreamFromClass(CustomClientResizingPlugin.class, "visible_icon.png");
VISIBLE_ICON = new ImageIcon(visibleImg);
VISIBLE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(visibleImg, -100));
final BufferedImage invisibleImg = ImageUtil.getResourceStreamFromClass(CustomClientResizingPlugin.class, "invisible_icon.png");
INVISIBLE_ICON = new ImageIcon(invisibleImg);
INVISIBLE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(invisibleImg, -100));
final BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(CustomClientResizingPlugin.class, "delete_icon.png");
DELETE_ICON = new ImageIcon(deleteImg);
DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, -100));
}
private final CustomClientResizingPlugin plugin;
private final CustomClientResizingProfile profile;
private final JLabel visibilityLabel = new JLabel();
private final JLabel deleteLabel = new JLabel();
private final FlatTextField nameInput = new FlatTextField();
private final JLabel save = new JLabel("Save");
private final JLabel cancel = new JLabel("Cancel");
private final JLabel rename = new JLabel("Rename");
CustomClientResizingProfilePanel(CustomClientResizingPlugin plugin, CustomClientResizingProfile profile)
{
this.plugin = plugin;
this.profile = profile;
setLayout(new BorderLayout());
setBackground(ColorScheme.DARKER_GRAY_COLOR);
JPanel nameWrapper = new JPanel(new BorderLayout());
nameWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
nameWrapper.setBorder(NAME_BOTTOM_BORDER);
JPanel nameActions = new JPanel(new BorderLayout(3, 0));
nameActions.setBorder(new EmptyBorder(0, 0, 0, 8));
nameActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
save.setVisible(false);
save.setFont(FontManager.getRunescapeSmallFont());
save.setForeground(ColorScheme.PROGRESS_COMPLETE_COLOR);
save.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
profile.setName(nameInput.getText());
plugin.updateConfig();
nameInput.setEditable(false);
updateNameActions(false);
requestFocusInWindow();
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
save.setForeground(ColorScheme.PROGRESS_COMPLETE_COLOR.darker());
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
save.setForeground(ColorScheme.PROGRESS_COMPLETE_COLOR);
}
});
cancel.setVisible(false);
cancel.setFont(FontManager.getRunescapeSmallFont());
cancel.setForeground(ColorScheme.PROGRESS_ERROR_COLOR);
cancel.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
nameInput.setEditable(false);
nameInput.setText(profile.getName());
updateNameActions(false);
requestFocusInWindow();
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
cancel.setForeground(ColorScheme.PROGRESS_ERROR_COLOR.darker());
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
cancel.setForeground(ColorScheme.PROGRESS_ERROR_COLOR);
}
});
rename.setFont(FontManager.getRunescapeSmallFont());
rename.setForeground(ColorScheme.LIGHT_GRAY_COLOR.darker());
rename.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
nameInput.setEditable(true);
updateNameActions(true);
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
rename.setForeground(ColorScheme.LIGHT_GRAY_COLOR.darker().darker());
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
rename.setForeground(ColorScheme.LIGHT_GRAY_COLOR.darker());
}
});
nameActions.add(save, BorderLayout.EAST);
nameActions.add(cancel, BorderLayout.WEST);
nameActions.add(rename, BorderLayout.CENTER);
nameInput.setText(profile.getName());
nameInput.setBorder(null);
nameInput.setEditable(false);
nameInput.setBackground(ColorScheme.DARKER_GRAY_COLOR);
nameInput.setPreferredSize(new Dimension(0, 24));
nameInput.getTextField().setForeground(Color.WHITE);
nameInput.getTextField().setBorder(new EmptyBorder(0, 8, 0, 0));
nameWrapper.add(nameInput, BorderLayout.CENTER);
nameWrapper.add(nameActions, BorderLayout.EAST);
JPanel bottomContainer = new JPanel(new BorderLayout());
bottomContainer.setBorder(new EmptyBorder(8, 0, 8, 0));
bottomContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
JPanel leftActions = new JPanel(new BorderLayout());
leftActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
JPanel positionPanel = createPositionPanel(profile.getPosition().width, profile.getPosition().height);
JPanel sizePanel = createSizePanel(profile.getSize().width, profile.getSize().height);
leftActions.add(positionPanel, BorderLayout.NORTH);
leftActions.add(sizePanel, BorderLayout.SOUTH);
JPanel rightActions = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
rightActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
visibilityLabel.setToolTipText(profile.isVisible() ? "Deactivated" : "Activate resize profile");
visibilityLabel.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
if (profile.isVisible())
{
return;
}
plugin.disableProfiles();
profile.setVisible(true);
updateVisibility();
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
visibilityLabel.setIcon(profile.isVisible() ? VISIBLE_HOVER_ICON : INVISIBLE_HOVER_ICON);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
updateVisibility();
}
});
deleteLabel.setIcon(DELETE_ICON);
deleteLabel.setToolTipText("Delete resize profile");
deleteLabel.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
int confirm = JOptionPane.showConfirmDialog(CustomClientResizingProfilePanel.this,
"Are you sure you want to permanently delete this resize profile?",
"Warning", JOptionPane.OK_CANCEL_OPTION);
if (confirm == 0)
{
plugin.deleteProfile(profile);
}
}
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
deleteLabel.setIcon(DELETE_HOVER_ICON);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
deleteLabel.setIcon(DELETE_ICON);
}
});
rightActions.add(visibilityLabel);
rightActions.add(deleteLabel);
bottomContainer.add(leftActions, BorderLayout.WEST);
bottomContainer.add(rightActions, BorderLayout.EAST);
add(nameWrapper, BorderLayout.NORTH);
add(bottomContainer, BorderLayout.CENTER);
updateVisibility();
}
private JPanel createPositionPanel(int width, int height)
{
JPanel dimensionPanel = new JPanel();
dimensionPanel.setLayout(new BorderLayout());
JSpinner widthSpinner = createSpinner(width);
JSpinner heightSpinner = createSpinner(height);
ChangeListener listener = e -> updatePosition((Integer) widthSpinner.getValue(), (Integer) heightSpinner.getValue());
widthSpinner.addChangeListener(listener);
heightSpinner.addChangeListener(listener);
dimensionPanel.add(widthSpinner, BorderLayout.WEST);
dimensionPanel.add(new JLabel(" x "), BorderLayout.CENTER);
dimensionPanel.add(heightSpinner, BorderLayout.EAST);
return dimensionPanel;
}
private JPanel createSizePanel(int width, int height)
{
JPanel dimensionPanel = new JPanel();
dimensionPanel.setLayout(new BorderLayout());
JSpinner widthSpinner = createSpinner(width);
JSpinner heightSpinner = createSpinner(height);
ChangeListener listener = e -> updateSize((Integer) widthSpinner.getValue(), (Integer) heightSpinner.getValue());
widthSpinner.addChangeListener(listener);
heightSpinner.addChangeListener(listener);
dimensionPanel.add(widthSpinner, BorderLayout.WEST);
dimensionPanel.add(new JLabel(" x "), BorderLayout.CENTER);
dimensionPanel.add(heightSpinner, BorderLayout.EAST);
return dimensionPanel;
}
private JSpinner createSpinner(int value)
{
SpinnerModel model = new SpinnerNumberModel(value, Integer.MIN_VALUE, Integer.MAX_VALUE, 1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(4);
return spinner;
}
private void updateNameActions(boolean saveAndCancel)
{
save.setVisible(saveAndCancel);
cancel.setVisible(saveAndCancel);
rename.setVisible(!saveAndCancel);
if (saveAndCancel)
{
nameInput.getTextField().requestFocusInWindow();
nameInput.getTextField().selectAll();
}
}
private void updateVisibility()
{
visibilityLabel.setIcon(profile.isVisible() ? VISIBLE_ICON : INVISIBLE_ICON);
plugin.updateConfig();
}
private void updatePosition(int x, int y)
{
profile.setPosition(new Dimension(x, y));
plugin.updateConfig();
}
private void updateSize(int w, int h)
{
profile.setSize(new Dimension(w, h));
plugin.updateConfig();
}
}

View File

@@ -119,6 +119,14 @@ public class ClientUI
@Getter
private TrayIcon trayIcon;
@Getter
public static ContainableFrame frame;
@Getter
public static ClientPluginToolbar pluginToolbar;
@Getter
private boolean sidebarOpen;
@Getter
public static PluginPanel pluginPanel;
private final RuneLiteConfig config;
private final KeyManager keyManager;
@@ -131,14 +139,10 @@ public class ClientUI
private boolean withTitleBar;
private BufferedImage sidebarOpenIcon;
private BufferedImage sidebarClosedIcon;
public static ContainableFrame frame;
private JPanel navContainer;
public static PluginPanel pluginPanel;
public static ClientPluginToolbar pluginToolbar;
private ClientTitleToolbar titleToolbar;
private JButton currentButton;
private NavigationButton currentNavButton;
private boolean sidebarOpen;
private JPanel container;
private NavigationButton sidebarNavigationButton;
private JButton sidebarNavigationJButton;

View File

@@ -44,7 +44,7 @@ public abstract class PluginPanel extends JPanel
@Getter(AccessLevel.PROTECTED)
private final JScrollPane scrollPane;
@Getter(AccessLevel.PACKAGE)
@Getter(AccessLevel.PUBLIC)
private final JPanel wrappedPanel;
protected PluginPanel()

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B