/*
* This software copyright by various authors including the RPTools.net
* development team, and licensed under the LGPL Version 3 or, at your option,
* any later version.
*
* Portions of this software were originally covered under the Apache Software
* License, Version 1.1 or Version 2.0.
*
* See the file LICENSE elsewhere in this distribution for license details.
*/
package net.rptools.maptool.client.ui.macrobuttons.buttongroups;
import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;
import net.rptools.lib.swing.SwingUtil;
import net.rptools.maptool.client.AppStyle;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.ui.TokenPopupMenu;
import net.rptools.maptool.client.ui.macrobuttons.buttons.MacroButton;
import net.rptools.maptool.client.ui.macrobuttons.panels.AbstractMacroPanel;
import net.rptools.maptool.client.ui.token.EditTokenDialog;
import net.rptools.maptool.client.ui.zone.ZoneRenderer;
import net.rptools.maptool.model.GUID;
import net.rptools.maptool.model.MacroButtonProperties;
import net.rptools.maptool.model.Token;
import net.rptools.maptool.util.ImageManager;
public abstract class AbstractButtonGroup extends JPanel implements DropTargetListener, MouseListener {
protected DropTarget dt;
private GUID tokenId;
private List<Token> tokenList;
private List<MacroButtonProperties> propertiesList;
private AbstractMacroPanel panel;
private String panelClass = "";
private String groupLabel = "";
private String groupClass = "";
private String macroGroup = "";
private int spacerHeight = 0;
private AreaGroup area;
public void dragEnter(DropTargetDragEvent event) {
//System.out.println("BG: drag enter");
}
public void dragOver(DropTargetDragEvent event) {
//System.out.println("BG: drag over");
}
public void dropActionChanged(DropTargetDragEvent event) {
//System.out.println("BG: drag action changed");
}
public void dragExit(DropTargetEvent event) {
//System.out.println("BG: drag exit");
}
public void drop(DropTargetDropEvent event) {
//System.out.println("BG: drop!");
}
public Token getToken() {
if (tokenId == null) {
return null;
} else {
return MapTool.getFrame().getCurrentZoneRenderer() != null ? MapTool.getFrame().getCurrentZoneRenderer().getZone().getToken(tokenId) : null;
}
}
public GUID getTokenId() {
return this.tokenId;
}
public void setTokenId(GUID tokenId) {
this.tokenId = tokenId;
}
public void setTokenId(Token token) {
if (token == null) {
this.tokenId = null;
} else {
this.tokenId = token.getId();
}
}
public List<Token> getTokenList() {
return tokenList;
}
public void setTokenList(List<Token> tokenList) {
this.tokenList = tokenList;
}
public String getGroupClass() {
return groupClass;
}
public void setGroupClass(String groupClass) {
this.groupClass = groupClass;
}
public String getGroupLabel() {
return groupLabel;
}
public void setGroupLabel(String label) {
this.groupLabel = label;
}
public AbstractMacroPanel getPanel() {
return panel;
}
public void setPanel(AbstractMacroPanel panel) {
this.panel = panel;
}
public String getPanelClass() {
return panelClass;
}
public void setPanelClass(String panelClass) {
this.panelClass = panelClass;
}
public List<MacroButtonProperties> getPropertiesList() {
return propertiesList;
}
public void setPropertiesList(List<MacroButtonProperties> propertiesList) {
MacroButtonProperties.fixOldMacroSetCompare(propertiesList);
this.propertiesList = propertiesList;
}
public String getMacroGroup() {
return macroGroup;
}
public void setMacroGroup(String group) {
this.macroGroup = group;
}
public void setSpacerHeight(int height) {
this.spacerHeight = height;
}
public AreaGroup getArea() {
return area;
}
public void setArea(AreaGroup newArea) {
area = newArea;
}
protected String getTokenName(Token token) {
// if a token has a GM name, put that to button title too
if (token.getGMName() != null && token.getGMName().trim().length() > 0) {
return token.getName() + " (" + token.getGMName() + ")";
} else {
return token.getName();
}
}
// Override these mouse events in subclasses to specify component specific behavior.
public void mouseClicked(MouseEvent event) {
}
public void mousePressed(MouseEvent event) {
}
public void mouseReleased(MouseEvent event) {
Token token = getToken();
if (SwingUtilities.isRightMouseButton(event)) {
if (getPanelClass() == "CampaignPanel" && !MapTool.getPlayer().isGM()) {
return;
}
// open button group menu
new ButtonGroupPopupMenu(getPanelClass(), area, getMacroGroup(), token).show(this, event.getX(), event.getY());
}
}
public void mouseEntered(MouseEvent event) {
}
public void mouseExited(MouseEvent event) {
}
protected ThumbnailedBorder createBorder(String label) {
if (getToken() != null) {
ImageIcon i = new ImageIcon(ImageManager.getImageAndWait(getToken().getImageAssetId()));
Image icon = i.getImage().getScaledInstance(20, 20, Image.SCALE_DEFAULT);
return new ThumbnailedBorder(icon, label);
} else {
return new ThumbnailedBorder(null, label);
}
}
protected class ThumbnailedBorder extends AbstractBorder {
private Image image;
private String label;
private Rectangle imageBounds;
//private final int X_OFFSET = 5;
public ThumbnailedBorder(Image image, String label) {
this.image = image;
this.label = label;
addMouseListener(new MouseHandler());
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
//((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
//TODO: change magic numbers to final fields
// match line color to default titledborder line color
g.setColor(new Color(165, 163, 151));
if (image == null && label == null) {
g.drawRoundRect(2, 2, c.getWidth() - 3, c.getHeight() - 3, 6, 6);
} else {
g.drawRoundRect(2, 12, c.getWidth() - 5, c.getHeight() - 13, 6, 6);
// clear the left and right handside of the image to show space between border line and image
g.setColor(c.getBackground());
g.fillRect(8, 0, 24, 20);
g.drawImage(image, 10, 2, null);
int strx = image != null ? 30 : 5;
// clear the left and right of the label
FontMetrics metrics = g.getFontMetrics();
int stringHeight = metrics.getHeight();
int stringWidth = metrics.stringWidth(label);
g.fillRect(strx, 0, stringWidth + 5, stringHeight);
// set the area for mouse listener
if (image != null) {
imageBounds = new Rectangle(10, 2, image.getWidth(null) + stringWidth, image.getHeight(null));
// display impersonated image if impersonated
if (getToken() != null && getToken().isBeingImpersonated()) {
g.drawImage(AppStyle.impersonatePanelImage, (int) imageBounds.getMaxX() + 5, 4, null);
}
}
g.setColor(Color.BLACK);
g.drawString(label, strx + 3, (20 - stringHeight) / 2 + stringHeight - 2);
}
}
public Insets getBorderInsets(Component component) {
return new Insets(5, 5, 5, 5);
}
public boolean isBorderOpaque() {
return true;
}
private class MouseHandler extends MouseAdapter {
public void mouseReleased(MouseEvent event) {
Token token = getToken();
if (imageBounds != null && imageBounds.contains(event.getPoint())) {
if (SwingUtilities.isLeftMouseButton(event) && event.getClickCount() == 2 && !SwingUtil.isShiftDown(event)) {
// open edit token dialog
EditTokenDialog tokenPropertiesDialog = MapTool.getFrame().getTokenPropertiesDialog();
tokenPropertiesDialog.showDialog(token);
// update token in the renderer if it is changed
if (tokenPropertiesDialog.isTokenSaved()) {
ZoneRenderer renderer = MapTool.getFrame().getCurrentZoneRenderer();
renderer.repaint();
renderer.flush(token);
MapTool.serverCommand().putToken(renderer.getZone().getId(), token);
renderer.getZone().putToken(token);
}
} else if (SwingUtilities.isRightMouseButton(event)) {
// open token popup menu
Set<GUID> GUIDSet = new HashSet<GUID>();
GUIDSet.add(tokenId);
ZoneRenderer renderer = MapTool.getFrame().getCurrentZoneRenderer();
new TokenPopupMenu(GUIDSet, event.getX(), event.getY(), renderer, token).showPopup(AbstractButtonGroup.this);
} else if (SwingUtilities.isLeftMouseButton(event) && SwingUtil.isShiftDown(event)) {
// impersonate token toggle
if (token.isBeingImpersonated()) {
MapTool.getFrame().getCommandPanel().quickCommit("/im");
} else {
MapTool.getFrame().getCommandPanel().quickCommit("/im " + tokenId, false);
}
}
}
}
}
public MouseAdapter getMouseAdapter() {
return new MouseHandler();
}
}
public static void clearHotkeys(AbstractMacroPanel panel, String macroGroup) {
for (int areaGroupCount = 0; areaGroupCount < panel.getComponentCount(); areaGroupCount++) {
AreaGroup area = (AreaGroup) panel.getComponent(areaGroupCount);
for (ButtonGroup group : area.getButtonGroups()) {
if (macroGroup.equals(group.getMacroGroup())) {
for (MacroButton nextButton : group.getButtons()) {
nextButton.clearHotkey();
}
}
}
}
}
}