package ui.beans;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.MenuElement;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import ui.TypeCheckerEventListener;
public class MenuButton extends JComponent {
private Font font;
private String text;
private Dimension size;
private Point pos;
private int margin;
private float inborder;
private Color textColor;
private Color markerColor;
private ActionListener listener;
private JPopupMenu menu = null;
public MenuButton () {
this.font = new JComboBox ().getFont();
this.text = new String("");
setDefaultColors ();
this.margin = 1;
this.inborder = 0.2f;
calcPreferredSize();
addMouseListener(new MouseAdapter () {
public void mousePressed(MouseEvent evt) {
handleMouseClicked (evt);
}
});
listener = new ActionListener () {
public void actionPerformed (ActionEvent event) {
handleMenuAction ((JMenuItem)event.getSource());
}
};
}
public void setDefaultColors() {
this.textColor = new Color (0.0f, 0.0f, 0.0f);
this.markerColor = new Color (0.5f, 0.5f, 0.5f);
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
calcPreferredSize();
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
calcPreferredSize();
}
public Color getTextColor() {
return textColor;
}
public void setTextColor(Color textColor) {
this.textColor = textColor;
}
public Color getMarkerColor () {
return markerColor;
}
public void setMarkerColor(Color markerColor) {
this.markerColor = markerColor;
}
public int getMargin() {
return margin;
}
public void setMargin(int margin) {
this.margin = margin;
}
public void setInborder (float inborder) {
this.inborder = inborder;
}
public float getInborder() {
return inborder;
}
public JPopupMenu getMenu() {
return this.menu;
}
public int getNeededWidth () {
FontMetrics fm = getFontMetrics (this.font);
int width = fm.stringWidth(this.text);
int addSize = fm.getHeight () - 2*margin;
if (this.text.length() != 0)
addSize += fm.getAscent () + 2*margin;
return (width + addSize);
}
public int getNeededHeight () {
FontMetrics fm = getFontMetrics (this.font);
return fm.getHeight();
}
private void installElementListener (MenuElement element) {
if (element instanceof JMenuItem) {
JMenuItem item = (JMenuItem)element;
item.addActionListener(listener);
}
else {
MenuElement[] subElements = element.getSubElements();
for (MenuElement e : subElements) {
installElementListener (e);
}
}
}
private void uninstallElementListener (MenuElement element) {
if (element instanceof JMenuItem) {
JMenuItem item = (JMenuItem)element;
item.removeActionListener(listener);
}
else {
MenuElement[] subElements = element.getSubElements();
for (MenuElement e : subElements) {
uninstallElementListener (e);
}
}
}
public void setMenu(JPopupMenu menu) {
if (this.menu != null) {
uninstallElementListener(menu);
}
this.menu = menu;
this.menu.addPopupMenuListener(new PopupMenuListener () {
public void popupMenuCanceled (PopupMenuEvent e) { }
public void popupMenuWillBecomeInvisible (PopupMenuEvent e) {
fireMenuClosed ();
}
public void popupMenuWillBecomeVisible (PopupMenuEvent e) { }
});
installElementListener(menu);
}
public void setInborder(int inborder) {
this.inborder = inborder;
}
public void addMenuButtonListener(MenuButtonListener listener) {
listenerList.add(MenuButtonListener.class, listener);
}
private void handleMenuAction (JMenuItem item) {
setText (item.getText());
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MenuButtonListener.class) {
// Lazily create the event:
((MenuButtonListener)listeners[i+1]).menuItemActivated(this, item);
}
}
}
private void fireMenuClosed () {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==MenuButtonListener.class) {
((MenuButtonListener)listeners[i+1]).menuClosed(this);
}
}
}
private void handleMouseClicked (MouseEvent evt) {
if (this.menu == null) {
return;
}
this.menu.show(this, this.pos.x, this.pos.y);
}
private void calcPreferredSize() {
FontMetrics fm = getFontMetrics (this.font);
int width = fm.stringWidth(text) + fm.getHeight() + fm.getAscent();
int height = fm.getHeight();
this.setPreferredSize(new Dimension (width, height));
this.setMinimumSize(new Dimension (width, height));
}
@Override
public Dimension getPreferredSize () {
FontMetrics fm = getFontMetrics (this.font);
int width = fm.stringWidth(text) + fm.getHeight() + fm.getAscent();
int height = fm.getHeight();
return new Dimension (width, height);
}
@Override
public Dimension getMinimumSize() {
FontMetrics fm = getFontMetrics (this.font);
int width = fm.stringWidth(text) + fm.getHeight() + fm.getAscent();
int height = fm.getHeight();
return new Dimension (width, height);
}
@Override
public Dimension getMaximumSize() {
FontMetrics fm = getFontMetrics (this.font);
int width = fm.stringWidth(text) + fm.getHeight() + fm.getAscent();
int height = fm.getHeight();
return new Dimension (width, height);
}
public void paintComponent (Graphics g) {
Graphics2D g2d = (Graphics2D)g.create();
// draw the text
FontMetrics fm = getFontMetrics (font);
g2d.setColor(new Color(0.0f, 0.0f, 0.0f));
int vcenter = getHeight () / 2 + fm.getAscent() / 3;
g2d.setColor(this.textColor);
g2d.drawString(text, 0, vcenter);
int width = fm.stringWidth(text);
if (this.text.length() != 0) {
this.pos = new Point(width + fm.getAscent() + 2*margin, margin);
}
else {
this.pos = new Point(width, margin);
}
size = new Dimension (getHeight () - 1 - 2*margin, getHeight() - 1 - 2*margin);
int inborder = (int)((float)size.width * this.inborder);
// draw the marker
g2d.setColor(this.markerColor);
g2d.drawRect(pos.x, pos.y, size.width, size.height);
Polygon poly = new Polygon ();
poly.addPoint(pos.x + inborder, pos.y + inborder);
poly.addPoint(pos.x + size.width - inborder, pos.y + inborder);
poly.addPoint(pos.x + size.width / 2, pos.y + size.height - inborder);
g2d.fill(poly);
}
}