/*
* Copyright (C) 2014 Alec Dhuse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package co.foldingmap.GUISupport.components;
import co.foldingmap.GUISupport.Updateable;
import co.foldingmap.actions.Action;
import co.foldingmap.actions.Actions;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
/**
* A JButton that when clicked a popup menu appears.
*
* @author Alec
*/
public class PopupMenuButton extends JButton implements ActionListener, MouseListener {
public static final int LEFT_CLICK = MouseEvent.BUTTON1;
public static final int RIGHT_CLICK = MouseEvent.BUTTON3;
public static final String MENU_ACTIVATION = "Menu Activation";
protected Actions actions;
private ArrayList<MenuActionPair> menuActions;
protected ArrayList<Updateable> objectUpdates;
protected int menuActivation;
protected long lastActionTime;
protected JPopupMenu popupMenu;
/**
*
* @param icon
* The Icon to be displayed in the button.
* @param actions
* The actions class, used to execute actions for the menu items.
* @param menuActivation
* Specifies which mouse button will activate the menu.
*/
public PopupMenuButton(Icon icon, Actions actions, int menuActivation) {
super(icon);
this.actions = actions;
this.menuActivation = menuActivation;
this.objectUpdates = new ArrayList<Updateable>();
init();
}
/**
* Used to trigger the actions for each MenuItem.
*
* @param ae
*/
@Override
public void actionPerformed(ActionEvent ae) {
//Prevent duplicate clicks
if (!(lastActionTime == ae.getWhen())) {
for (MenuActionPair map: menuActions) {
if (map.menuItem == ae.getSource()) {
actions.performAction(map.action);
lastActionTime = ae.getWhen();
break;
}
}
}
//call updates
for (Updateable u: objectUpdates) u.update();
}
/**
* Adds a JMenuItem to the popup menu.
*
* @param menuItem
* @param action
*/
public void add(JMenuItem menuItem, Action action) {
menuActions.add(new MenuActionPair(menuItem, action));
popupMenu.add(menuItem);
menuItem.addActionListener(this);
}
/**
* Override for the parent Keylistener, adds the listener to sub objects
* as well.
*
* @param kl
*/
@Override
public void addKeyListener(KeyListener kl) {
super.addKeyListener(kl);
popupMenu.addKeyListener(kl);
}
/**
* Adds an object to call an update on after a MenuItem has been selected
* and its action run.
*
* @param update
*/
public void addUpdate(Updateable update) {
this.objectUpdates.add(update);
}
public void hidePopup() {
popupMenu.setVisible(false);
}
private void init() {
menuActions = new ArrayList<MenuActionPair>();
popupMenu = new JPopupMenu();
lastActionTime = 0;
this.addMouseListener(this);
}
@Override
public void mouseClicked(MouseEvent me) {
int x = 0;
int y = 0;
hidePopup();
if (me.getButton() == this.menuActivation) {
this.fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, MENU_ACTIVATION));
//show popup
if (this.getParent() instanceof JToolBar) {
JToolBar parent = (JToolBar) this.getParent();
if (parent.getOrientation() == SwingConstants.HORIZONTAL) {
x = 0;
y = parent.getY() + parent.getHeight() - 10;
} else if (parent.getOrientation() == SwingConstants.VERTICAL) {
x = this.getX() + parent.getWidth();
y = me.getY() - 16;
}
} else {
x = this.getX() - 150;
y = this.getY() + 15;
}
popupMenu.show(this, x, y);
}
}
@Override
public void mousePressed(MouseEvent me) {
}
@Override
public void mouseReleased(MouseEvent me) {
}
@Override
public void mouseEntered(MouseEvent me) {
}
@Override
public void mouseExited(MouseEvent me) {
}
public void removeAllMenuItems() {
menuActions.clear();
popupMenu.removeAll();
}
public void setActions(Actions actions) {
this.actions = actions;
}
}
class MenuActionPair {
JMenuItem menuItem;
Action action;
public MenuActionPair(JMenuItem menuItem, Action action) {
this.menuItem = menuItem;
this.action = action;
}
}