/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.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 com.t3.client.AppStyle;
import com.t3.client.TabletopTool;
import com.t3.client.ui.TokenPopupMenu;
import com.t3.client.ui.macrobuttons.buttons.MacroButton;
import com.t3.client.ui.macrobuttons.panels.AbstractMacroPanel;
import com.t3.client.ui.token.EditTokenDialog;
import com.t3.client.ui.zone.ZoneRenderer;
import com.t3.guid.GUID;
import com.t3.model.MacroButtonProperties;
import com.t3.model.Token;
import com.t3.swing.SwingUtil;
import com.t3.util.ImageManager;
import com.t3.util.guidreference.NullHelper;
import com.t3.util.guidreference.TokenReference;
public abstract class AbstractButtonGroup extends JPanel implements DropTargetListener, MouseListener {
protected DropTarget dt;
private TokenReference token;
private List<Token> tokenList;
private List<MacroButtonProperties> propertiesList;
private AbstractMacroPanel panel;
private String panelClass = "";
private String groupLabel = "";
private String groupClass = "";
private String macroGroup = "";
private AreaGroup area;
@Override
public void dragEnter(DropTargetDragEvent event) {
//System.out.println("BG: drag enter");
}
@Override
public void dragOver(DropTargetDragEvent event) {
//System.out.println("BG: drag over");
}
@Override
public void dropActionChanged(DropTargetDragEvent event) {
//System.out.println("BG: drag action changed");
}
@Override
public void dragExit(DropTargetEvent event) {
//System.out.println("BG: drag exit");
}
@Override
public void drop(DropTargetDropEvent event) {
//System.out.println("BG: drop!");
}
public Token getToken() {
return NullHelper.value(token);
}
public TokenReference getTokenReference(){
return this.token;
}
public void setTokenReference(TokenReference token){
this.token=token;
}
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){
this.propertiesList = propertiesList;
}
public String getMacroGroup(){
return macroGroup;
}
public void setMacroGroup(String group){
this.macroGroup=group;
}
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.
@Override
public void mouseClicked(MouseEvent event) {
}
@Override
public void mousePressed(MouseEvent event) {
}
@Override
public void mouseReleased(MouseEvent event) {
Token token = getToken();
if (SwingUtilities.isRightMouseButton(event)) {
if (getPanelClass()=="CampaignPanel" && !TabletopTool.getPlayer().isGM()) {
return;
}
// open button group menu
new ButtonGroupPopupMenu(getPanelClass(),area,getMacroGroup(),token).show(this, event.getX(), event.getY());
}
}
@Override
public void mouseEntered(MouseEvent event) {
}
@Override
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());
}
@Override
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);
}
}
@Override
public Insets getBorderInsets(Component component) {
return new Insets(5, 5, 5, 5);
}
@Override
public boolean isBorderOpaque() {
return true;
}
private class MouseHandler extends MouseAdapter {
@Override
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 = TabletopTool.getFrame().getTokenPropertiesDialog();
tokenPropertiesDialog.showDialog(token);
// update token in the renderer if it is changed
if (tokenPropertiesDialog.isTokenSaved()) {
ZoneRenderer renderer = TabletopTool.getFrame().getCurrentZoneRenderer();
renderer.repaint();
renderer.flush(token);
TabletopTool.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(NullHelper.getId(AbstractButtonGroup.this.token));
ZoneRenderer renderer = TabletopTool.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()) {
TabletopTool.getFrame().getCommandPanel().quickCommit("/im");
} else {
TabletopTool.getFrame().getCommandPanel().quickCommit("/im " + NullHelper.value(AbstractButtonGroup.this.token), 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();
}
}
}
}
}
}