46 |
import java.awt.Graphics; |
import java.awt.Graphics; |
47 |
import java.awt.Insets; |
import java.awt.Insets; |
48 |
import java.awt.Rectangle; |
import java.awt.Rectangle; |
49 |
import java.awt.event.KeyEvent; |
import java.awt.event.ActionEvent; |
|
import java.awt.event.MouseEvent; |
|
50 |
import java.awt.event.ItemEvent; |
import java.awt.event.ItemEvent; |
51 |
import java.awt.event.ItemListener; |
import java.awt.event.ItemListener; |
52 |
|
import java.awt.event.KeyEvent; |
53 |
|
import java.awt.event.MouseEvent; |
54 |
|
import java.beans.PropertyChangeEvent; |
55 |
|
import java.beans.PropertyChangeListener; |
56 |
import java.util.ArrayList; |
import java.util.ArrayList; |
57 |
|
|
58 |
|
import javax.swing.AbstractAction; |
59 |
|
import javax.swing.ActionMap; |
60 |
import javax.swing.ButtonModel; |
import javax.swing.ButtonModel; |
61 |
import javax.swing.Icon; |
import javax.swing.Icon; |
62 |
|
import javax.swing.InputMap; |
63 |
import javax.swing.JCheckBoxMenuItem; |
import javax.swing.JCheckBoxMenuItem; |
64 |
import javax.swing.JComponent; |
import javax.swing.JComponent; |
65 |
import javax.swing.JMenu; |
import javax.swing.JMenu; |
78 |
import javax.swing.event.MenuKeyEvent; |
import javax.swing.event.MenuKeyEvent; |
79 |
import javax.swing.event.MenuKeyListener; |
import javax.swing.event.MenuKeyListener; |
80 |
import javax.swing.event.MouseInputListener; |
import javax.swing.event.MouseInputListener; |
81 |
|
import javax.swing.plaf.ActionMapUIResource; |
82 |
|
import javax.swing.plaf.ComponentInputMapUIResource; |
83 |
import javax.swing.plaf.ComponentUI; |
import javax.swing.plaf.ComponentUI; |
84 |
import javax.swing.plaf.MenuItemUI; |
import javax.swing.plaf.MenuItemUI; |
85 |
|
|
177 |
private int defaultAcceleratorLabelGap = 10; |
private int defaultAcceleratorLabelGap = 10; |
178 |
|
|
179 |
/** |
/** |
180 |
* Number of spaces between the text and the arrow icon. |
* The gap between different menus on the MenuBar. |
181 |
*/ |
*/ |
182 |
private int defaultTextArrowIconGap = 10; |
private int MenuGap = 10; |
183 |
|
|
184 |
|
/** A PropertyChangeListener to make UI updates after property changes **/ |
185 |
|
PropertyChangeHandler propertyChangeListener; |
186 |
|
|
187 |
|
/** |
188 |
|
* A class to handle PropertChangeEvents for the JMenuItem |
189 |
|
* @author Anthony Balkissoon abalkiss at redhat dot com. |
190 |
|
*/ |
191 |
|
class PropertyChangeHandler implements PropertyChangeListener |
192 |
|
{ |
193 |
|
/** |
194 |
|
* This method is called when a property of the menuItem is changed. |
195 |
|
* Currently it is only used to update the accelerator key bindings. |
196 |
|
* |
197 |
|
* @param e |
198 |
|
* the PropertyChangeEvent |
199 |
|
*/ |
200 |
|
public void propertyChange(PropertyChangeEvent e) |
201 |
|
{ |
202 |
|
if (e.getPropertyName() == "accelerator") |
203 |
|
{ |
204 |
|
InputMap map = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW); |
205 |
|
if (map != null) |
206 |
|
map.remove((KeyStroke)e.getOldValue()); |
207 |
|
else |
208 |
|
map = new ComponentInputMapUIResource(menuItem); |
209 |
|
map.put((KeyStroke)e.getNewValue(), "doClick"); |
210 |
|
} |
211 |
|
} |
212 |
|
} |
213 |
|
|
214 |
|
/** |
215 |
|
* A class to handle accelerator keys. This is the Action we will |
216 |
|
* perform when the accelerator key for this JMenuItem is pressed. |
217 |
|
* @author Anthony Balkissoon abalkiss at redhat dot com |
218 |
|
* |
219 |
|
*/ |
220 |
|
class ClickAction extends AbstractAction |
221 |
|
{ |
222 |
|
/** |
223 |
|
* This is what is done when the accelerator key for the JMenuItem is |
224 |
|
* pressed. |
225 |
|
*/ |
226 |
|
public void actionPerformed(ActionEvent event) |
227 |
|
{ |
228 |
|
doClick(MenuSelectionManager.defaultManager()); |
229 |
|
} |
230 |
|
} |
231 |
|
|
232 |
/** |
/** |
233 |
* Creates a new BasicMenuItemUI object. |
* Creates a new BasicMenuItemUI object. |
238 |
menuDragMouseListener = createMenuDragMouseListener(menuItem); |
menuDragMouseListener = createMenuDragMouseListener(menuItem); |
239 |
menuKeyListener = createMenuKeyListener(menuItem); |
menuKeyListener = createMenuKeyListener(menuItem); |
240 |
itemListener = new ItemHandler(); |
itemListener = new ItemHandler(); |
241 |
|
propertyChangeListener = new PropertyChangeHandler(); |
242 |
} |
} |
243 |
|
|
244 |
/** |
/** |
377 |
JMenuItem m = (JMenuItem) c; |
JMenuItem m = (JMenuItem) c; |
378 |
Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m, |
Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m, |
379 |
defaultTextIconGap); |
defaultTextIconGap); |
380 |
|
|
381 |
// if menu item has accelerator then take accelerator's size into account |
// if menu item has accelerator then take accelerator's size into account |
382 |
// when calculating preferred size. |
// when calculating preferred size. |
383 |
KeyStroke accelerator = m.getAccelerator(); |
KeyStroke accelerator = m.getAccelerator(); |
399 |
|
|
400 |
if (checkIcon != null) |
if (checkIcon != null) |
401 |
{ |
{ |
402 |
d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap; |
d.width += checkIcon.getIconWidth() + defaultTextIconGap; |
403 |
|
|
404 |
if (checkIcon.getIconHeight() > d.height) |
if (checkIcon.getIconHeight() > d.height) |
405 |
d.height = checkIcon.getIconHeight(); |
d.height = checkIcon.getIconHeight(); |
407 |
|
|
408 |
if (arrowIcon != null && (c instanceof JMenu)) |
if (arrowIcon != null && (c instanceof JMenu)) |
409 |
{ |
{ |
410 |
d.width = d.width + arrowIcon.getIconWidth() + defaultTextArrowIconGap; |
int pWidth = m.getParent().getWidth(); |
411 |
|
if (!((JMenu)c).isTopLevelMenu() && d.width < pWidth) |
412 |
|
d.width = pWidth |
413 |
|
- m.getInsets().left - m.getInsets().right; |
414 |
|
else |
415 |
|
d.width += arrowIcon.getIconWidth() + MenuGap; |
416 |
|
|
417 |
if (arrowIcon.getIconHeight() > d.height) |
if (arrowIcon.getIconHeight() > d.height) |
418 |
d.height = arrowIcon.getIconHeight(); |
d.height = arrowIcon.getIconHeight(); |
419 |
} |
} |
420 |
|
|
421 |
return d; |
return d; |
422 |
} |
} |
423 |
|
|
475 |
|
|
476 |
menuItem.setHorizontalTextPosition(SwingConstants.TRAILING); |
menuItem.setHorizontalTextPosition(SwingConstants.TRAILING); |
477 |
menuItem.setHorizontalAlignment(SwingConstants.LEADING); |
menuItem.setHorizontalAlignment(SwingConstants.LEADING); |
|
menuItem.setOpaque(true); |
|
478 |
} |
} |
479 |
|
|
480 |
/** |
/** |
482 |
*/ |
*/ |
483 |
protected void installKeyboardActions() |
protected void installKeyboardActions() |
484 |
{ |
{ |
485 |
// FIXME: Need to implement |
InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW); |
486 |
|
if (focusedWindowMap == null) |
487 |
|
focusedWindowMap = new ComponentInputMapUIResource(menuItem); |
488 |
|
focusedWindowMap.put(menuItem.getAccelerator(), "doClick"); |
489 |
|
SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap); |
490 |
|
|
491 |
|
ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem); |
492 |
|
if (UIActionMap == null) |
493 |
|
UIActionMap = new ActionMapUIResource(); |
494 |
|
UIActionMap.put("doClick", new ClickAction()); |
495 |
|
SwingUtilities.replaceUIActionMap(menuItem, UIActionMap); |
496 |
} |
} |
497 |
|
|
498 |
/** |
/** |
505 |
menuItem.addMenuDragMouseListener(menuDragMouseListener); |
menuItem.addMenuDragMouseListener(menuDragMouseListener); |
506 |
menuItem.addMenuKeyListener(menuKeyListener); |
menuItem.addMenuKeyListener(menuKeyListener); |
507 |
menuItem.addItemListener(itemListener); |
menuItem.addItemListener(itemListener); |
508 |
|
menuItem.addPropertyChangeListener(propertyChangeListener); |
509 |
} |
} |
510 |
|
|
511 |
/** |
/** |
523 |
installDefaults(); |
installDefaults(); |
524 |
installComponents(menuItem); |
installComponents(menuItem); |
525 |
installListeners(); |
installListeners(); |
526 |
|
installKeyboardActions(); |
527 |
} |
} |
528 |
|
|
529 |
/** |
/** |
552 |
*/ |
*/ |
553 |
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) |
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) |
554 |
{ |
{ |
555 |
Dimension size = getPreferredSize(menuItem); |
// Menu item is considered to be highlighted when it is selected. |
556 |
Color foreground = g.getColor(); |
// But we don't want to paint the background of JCheckBoxMenuItems |
557 |
g.setColor(bgColor); |
ButtonModel mod = menuItem.getModel(); |
558 |
g.drawRect(0, 0, size.width, size.height); |
if ((menuItem.isSelected() && checkIcon == null) || (mod != null && |
559 |
g.setColor(foreground); |
mod.isArmed()) |
560 |
|
&& (menuItem.getParent() instanceof MenuElement)) |
561 |
|
{ |
562 |
|
if (menuItem.isContentAreaFilled()) |
563 |
|
{ |
564 |
|
g.setColor(selectionBackground); |
565 |
|
g.fillRect(0, 0, menuItem.getWidth(), menuItem.getHeight()); |
566 |
|
} |
567 |
|
} |
568 |
|
|
569 |
} |
} |
570 |
|
|
571 |
/** |
/** |
602 |
int horAlign = m.getHorizontalAlignment(); |
int horAlign = m.getHorizontalAlignment(); |
603 |
int vertTextPos = m.getVerticalTextPosition(); |
int vertTextPos = m.getVerticalTextPosition(); |
604 |
int horTextPos = m.getHorizontalTextPosition(); |
int horTextPos = m.getHorizontalTextPosition(); |
605 |
|
|
606 |
Font f = m.getFont(); |
Font f = m.getFont(); |
607 |
g.setFont(f); |
g.setFont(f); |
608 |
FontMetrics fm = g.getFontMetrics(f); |
FontMetrics fm = g.getFontMetrics(f); |
620 |
br.width += insets.right + insets.left; |
br.width += insets.right + insets.left; |
621 |
br.height += insets.top + insets.bottom; |
br.height += insets.top + insets.bottom; |
622 |
|
|
|
// Menu item is considered to be highlighted when it is selected. |
|
|
// But we don't want to paint the background of JCheckBoxMenuItems |
|
|
ButtonModel mod = m.getModel(); |
|
|
if ((m.isSelected() && checkIcon == null) || (mod != null && |
|
|
mod.isArmed()) |
|
|
&& (m.getParent() instanceof MenuElement)) |
|
|
{ |
|
|
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); |
|
|
} |
|
|
} |
|
|
|
|
623 |
// If this menu item is a JCheckBoxMenuItem then paint check icon |
// If this menu item is a JCheckBoxMenuItem then paint check icon |
624 |
if (checkIcon != null) |
if (checkIcon != null) |
625 |
{ |
{ |
769 |
* Uninstalls any keyboard actions. |
* Uninstalls any keyboard actions. |
770 |
*/ |
*/ |
771 |
protected void uninstallKeyboardActions() |
protected void uninstallKeyboardActions() |
772 |
{ |
{ |
773 |
// FIXME: need to implement |
SwingUtilities.replaceUIInputMap(menuItem, |
774 |
|
JComponent.WHEN_IN_FOCUSED_WINDOW, null); |
775 |
} |
} |
776 |
|
|
777 |
/** |
/** |
783 |
menuItem.removeMenuDragMouseListener(menuDragMouseListener); |
menuItem.removeMenuDragMouseListener(menuDragMouseListener); |
784 |
menuItem.removeMenuKeyListener(menuKeyListener); |
menuItem.removeMenuKeyListener(menuKeyListener); |
785 |
menuItem.removeItemListener(itemListener); |
menuItem.removeItemListener(itemListener); |
786 |
|
menuItem.removePropertyChangeListener(propertyChangeListener); |
787 |
} |
} |
788 |
|
|
789 |
/** |
/** |