BasicMenuItemUI.java [plain text]
package javax.swing.plaf.basic;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.MenuDragMouseEvent;
import javax.swing.event.MenuDragMouseListener;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuItemUI;
public class BasicMenuItemUI extends MenuItemUI
{
protected Font acceleratorFont;
protected Color acceleratorForeground;
protected Color acceleratorSelectionForeground;
protected Icon arrowIcon;
protected Icon checkIcon;
protected int defaultTextIconGap = 4;
protected Color disabledForeground;
protected MenuDragMouseListener menuDragMouseListener;
protected JMenuItem menuItem;
protected MenuKeyListener menuKeyListener;
protected MouseInputListener mouseInputListener;
protected boolean oldBorderPainted;
protected Color selectionBackground;
protected Color selectionForeground;
private String acceleratorDelimiter;
private PropertyChangeListener propertyChangeListener;
private int defaultAcceleratorLabelGap = 4;
public BasicMenuItemUI()
{
mouseInputListener = createMouseInputListener(menuItem);
menuDragMouseListener = createMenuDragMouseListener(menuItem);
menuKeyListener = createMenuKeyListener(menuItem);
propertyChangeListener = new PropertyChangeHandler();
}
protected MenuDragMouseListener createMenuDragMouseListener(JComponent c)
{
return new MenuDragMouseHandler();
}
protected MenuKeyListener createMenuKeyListener(JComponent c)
{
return new MenuKeyHandler();
}
protected MouseInputListener createMouseInputListener(JComponent c)
{
return new MouseInputHandler();
}
public static ComponentUI createUI(JComponent c)
{
return new BasicMenuItemUI();
}
protected void doClick(MenuSelectionManager msm)
{
menuItem.doClick();
msm.clearSelectedPath();
}
public Dimension getMaximumSize(JComponent c)
{
return null;
}
public Dimension getMinimumSize(JComponent c)
{
return null;
}
public MenuElement[] getPath()
{
ArrayList path = new ArrayList();
if (menuItem instanceof JMenu)
path.add(((JMenu) menuItem).getPopupMenu());
Component c = menuItem;
while (c instanceof MenuElement)
{
path.add(0, (MenuElement) c);
if (c instanceof JPopupMenu)
c = ((JPopupMenu) c).getInvoker();
else
c = c.getParent();
}
MenuElement[] pathArray = new MenuElement[path.size()];
path.toArray(pathArray);
return pathArray;
}
protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
Icon arrowIcon,
int defaultTextIconGap)
{
JMenuItem m = (JMenuItem) c;
Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m,
defaultTextIconGap);
KeyStroke accelerator = m.getAccelerator();
Rectangle rect;
if (accelerator != null)
{
rect = getAcceleratorRect(accelerator,
m.getToolkit().getFontMetrics(acceleratorFont));
d.width = d.width + rect.width + defaultAcceleratorLabelGap;
if (d.height < rect.height)
d.height = rect.height;
}
if (checkIcon != null)
{
d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap;
if (checkIcon.getIconHeight() > d.height)
d.height = checkIcon.getIconHeight();
}
if (arrowIcon != null && (c instanceof JMenu))
{
d.width = d.width + arrowIcon.getIconWidth() + defaultTextIconGap;
if (arrowIcon.getIconHeight() > d.height)
d.height = arrowIcon.getIconHeight();
}
return d;
}
public Dimension getPreferredSize(JComponent c)
{
return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap);
}
protected String getPropertyPrefix()
{
return null;
}
protected void installComponents(JMenuItem menuItem)
{
}
protected void installDefaults()
{
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
menuItem.setBackground(defaults.getColor("MenuItem.background"));
menuItem.setBorder(defaults.getBorder("MenuItem.border"));
menuItem.setFont(defaults.getFont("MenuItem.font"));
menuItem.setForeground(defaults.getColor("MenuItem.foreground"));
menuItem.setMargin(defaults.getInsets("MenuItem.margin"));
menuItem.setOpaque(true);
acceleratorFont = defaults.getFont("MenuItem.acceleratorFont");
acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground");
acceleratorSelectionForeground = defaults.getColor("MenuItem.acceleratorSelectionForeground");
selectionBackground = defaults.getColor("MenuItem.selectionBackground");
selectionForeground = defaults.getColor("MenuItem.selectionForeground");
acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter");
menuItem.setHorizontalTextPosition(SwingConstants.TRAILING);
menuItem.setHorizontalAlignment(SwingConstants.LEADING);
}
protected void installKeyboardActions()
{
}
protected void installListeners()
{
menuItem.addMouseListener(mouseInputListener);
menuItem.addMouseMotionListener(mouseInputListener);
menuItem.addMenuDragMouseListener(menuDragMouseListener);
menuItem.addMenuKeyListener(menuKeyListener);
menuItem.addPropertyChangeListener(propertyChangeListener);
}
public void installUI(JComponent c)
{
super.installUI(c);
menuItem = (JMenuItem) c;
installDefaults();
installComponents(menuItem);
installListeners();
}
public void paint(Graphics g, JComponent c)
{
paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(),
c.getForeground(), defaultTextIconGap);
}
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor)
{
Dimension size = getPreferredSize(menuItem);
Color foreground = g.getColor();
g.setColor(bgColor);
g.drawRect(0, 0, size.width, size.height);
g.setColor(foreground);
}
protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon,
Icon arrowIcon, Color background,
Color foreground, int defaultTextIconGap)
{
JMenuItem m = (JMenuItem) c;
Rectangle tr = new Rectangle(); Rectangle ir = new Rectangle(); Rectangle vr = new Rectangle(); Rectangle br = new Rectangle(); Rectangle ar = new Rectangle(); Rectangle cr = new Rectangle();
int vertAlign = m.getVerticalAlignment();
int horAlign = m.getHorizontalAlignment();
int vertTextPos = m.getVerticalTextPosition();
int horTextPos = m.getHorizontalTextPosition();
Font f = m.getFont();
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
SwingUtilities.calculateInnerArea(m, br);
SwingUtilities.calculateInsetArea(br, m.getInsets(), vr);
paintBackground(g, m, m.getBackground());
Insets insets = m.getInsets();
br.x -= insets.left;
br.y -= insets.top;
br.width += insets.right + insets.left;
br.height += insets.top + insets.bottom;
if (m.getModel().isArmed()
&& (m.getParent() instanceof MenuElement || m.getModel().isPressed()))
{
if (m.isContentAreaFilled())
{
g.setColor(selectionBackground);
g.fillRect(br.x, br.y, br.width, br.height);
}
}
else
{
if (m.isContentAreaFilled())
{
g.setColor(m.getBackground());
g.fillRect(br.x, br.y, br.width, br.height);
}
}
if (checkIcon != null)
{
SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign,
horAlign, vertTextPos, horTextPos,
vr, cr, tr, defaultTextIconGap);
checkIcon.paintIcon(m, g, cr.x, cr.y);
vr.x = cr.x + cr.width + defaultTextIconGap;
}
if (arrowIcon != null && (c instanceof JMenu))
{
if (! ((JMenu) c).isTopLevelMenu())
{
int width = arrowIcon.getIconWidth();
int height = arrowIcon.getIconHeight();
arrowIcon.paintIcon(m, g, vr.width - width + defaultTextIconGap,
vr.y + 2);
}
}
Icon i = m.getIcon();
SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i,
vertAlign, horAlign, vertTextPos,
horTextPos, vr, ir, tr,
defaultTextIconGap);
if (i != null)
i.paintIcon(c, g, ir.x, ir.y);
paintText(g, m, tr, m.getText());
String acceleratorText = "";
if (m.getAccelerator() != null)
{
acceleratorText = getAcceleratorText(m.getAccelerator());
fm = g.getFontMetrics(acceleratorFont);
ar.width = fm.stringWidth(acceleratorText);
ar.x = br.width - ar.width;
vr.x = br.width - ar.width;
SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null,
vertAlign, horAlign, vertTextPos,
horTextPos, vr, ir, ar,
defaultTextIconGap);
paintAccelerator(g, m, ar, acceleratorText);
}
}
protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect,
String text)
{
Font f = menuItem.getFont();
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
if (text != null && ! text.equals(""))
{
if (menuItem.isEnabled())
g.setColor(menuItem.getForeground());
else
g.setColor(Color.gray);
int mnemonicIndex = menuItem.getDisplayedMnemonicIndex();
if (mnemonicIndex != -1)
BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex,
textRect.x,
textRect.y
+ fm.getAscent());
else
BasicGraphicsUtils.drawString(g, text, 0, textRect.x,
textRect.y + fm.getAscent());
}
}
protected void uninstallComponents(JMenuItem menuItem)
{
}
protected void uninstallDefaults()
{
menuItem.setForeground(null);
menuItem.setBackground(null);
menuItem.setBorder(null);
menuItem.setMargin(null);
menuItem.setBackground(null);
menuItem.setBorder(null);
menuItem.setFont(null);
menuItem.setForeground(null);
menuItem.setMargin(null);
acceleratorFont = null;
acceleratorForeground = null;
acceleratorSelectionForeground = null;
arrowIcon = null;
selectionBackground = null;
selectionForeground = null;
acceleratorDelimiter = null;
}
protected void uninstallKeyboardActions()
{
}
protected void uninstallListeners()
{
menuItem.removeMouseListener(mouseInputListener);
menuItem.removeMenuDragMouseListener(menuDragMouseListener);
menuItem.removeMenuKeyListener(menuKeyListener);
menuItem.removePropertyChangeListener(propertyChangeListener);
}
public void uninstallUI(JComponent c)
{
uninstallListeners();
uninstallDefaults();
uninstallComponents(menuItem);
menuItem = null;
}
public void update(Graphics g, JComponent c)
{
paint(g, c);
}
private String getAcceleratorText(KeyStroke accelerator)
{
String modifiersText = "";
int modifiers = accelerator.getModifiers();
char keyChar = accelerator.getKeyChar();
int keyCode = accelerator.getKeyCode();
if (modifiers != 0)
modifiersText = KeyEvent.getKeyModifiersText(modifiers)
+ acceleratorDelimiter;
if (keyCode == KeyEvent.VK_UNDEFINED)
return modifiersText + keyChar;
else
return modifiersText + KeyEvent.getKeyText(keyCode);
}
private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm)
{
int width = fm.stringWidth(getAcceleratorText(accelerator));
int height = fm.getHeight();
return new Rectangle(0, 0, width, height);
}
private void paintAccelerator(Graphics g, JMenuItem menuItem,
Rectangle acceleratorRect,
String acceleratorText)
{
g.setFont(acceleratorFont);
FontMetrics fm = g.getFontMetrics(acceleratorFont);
if (menuItem.isEnabled())
g.setColor(acceleratorForeground);
else
g.setColor(Color.gray);
BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x,
acceleratorRect.y + fm.getAscent());
}
protected class MouseInputHandler implements MouseInputListener
{
protected MouseInputHandler()
{
}
public void mouseClicked(MouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.processMouseEvent(e);
}
public void mouseDragged(MouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.processMouseEvent(e);
}
public void mouseEntered(MouseEvent e)
{
Component source = (Component) e.getSource();
if (source.getParent() instanceof MenuElement)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.setSelectedPath(getPath());
manager.processMouseEvent(e);
}
}
public void mouseExited(MouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.processMouseEvent(e);
}
public void mouseMoved(MouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.processMouseEvent(e);
}
public void mousePressed(MouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.processMouseEvent(e);
}
public void mouseReleased(MouseEvent e)
{
Rectangle size = menuItem.getBounds();
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0
&& e.getY() < size.height)
{
manager.clearSelectedPath();
menuItem.doClick();
}
else
manager.processMouseEvent(e);
}
}
protected class MenuDragMouseHandler implements MenuDragMouseListener
{
public void menuDragMouseDragged(MenuDragMouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.setSelectedPath(e.getPath());
}
public void menuDragMouseEntered(MenuDragMouseEvent e)
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.setSelectedPath(e.getPath());
}
public void menuDragMouseExited(MenuDragMouseEvent e)
{
}
public void menuDragMouseReleased(MenuDragMouseEvent e)
{
MenuElement[] path = e.getPath();
if (path[path.length - 1] instanceof JMenuItem)
((JMenuItem) path[path.length - 1]).doClick();
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
manager.clearSelectedPath();
}
}
protected class MenuKeyHandler implements MenuKeyListener
{
public void menuKeyPressed(MenuKeyEvent e)
{
}
public void menuKeyReleased(MenuKeyEvent e)
{
}
public void menuKeyTyped(MenuKeyEvent e)
{
}
}
protected class PropertyChangeHandler implements PropertyChangeListener
{
public void propertyChange(PropertyChangeEvent evt)
{
menuItem.revalidate();
menuItem.repaint();
}
}
}