0001: /*
0002: * @(#)MetalJideSplitButtonUI.java
0003: *
0004: * Copyright 2002 - 2004 JIDE Software Inc. All rights reserved.
0005: */
0006:
0007: package com.jidesoft.plaf.metal;
0008:
0009: import com.jidesoft.icons.IconsFactory;
0010: import com.jidesoft.plaf.UIDefaultsLookup;
0011: import com.jidesoft.plaf.basic.LazyActionMap;
0012: import com.jidesoft.plaf.basic.ThemePainter;
0013: import com.jidesoft.plaf.basic.UIAction;
0014: import com.jidesoft.swing.*;
0015:
0016: import javax.swing.*;
0017: import javax.swing.event.MouseInputListener;
0018: import javax.swing.plaf.ComponentUI;
0019: import javax.swing.plaf.basic.BasicGraphicsUtils;
0020: import javax.swing.plaf.basic.BasicHTML;
0021: import javax.swing.text.View;
0022: import java.awt.*;
0023: import java.awt.event.ActionEvent;
0024: import java.awt.event.MouseEvent;
0025: import java.beans.PropertyChangeEvent;
0026: import java.beans.PropertyChangeListener;
0027: import java.util.ArrayList;
0028:
0029: /**
0030: * MetalJideSplitButtonUI implementation
0031: */
0032: public class MetalJideSplitButtonUI extends MetalMenuUI {
0033:
0034: protected ThemePainter _painter;
0035:
0036: protected Color _shadowColor;
0037: protected Color _darkShadowColor;
0038: protected Color _highlight;
0039: protected Color _lightHighlightColor;
0040:
0041: private int _splitButtonMargin = 12;
0042: private int _splitButtonMarginOnMenu = 18;
0043:
0044: protected PropertyChangeListener _propertyChangeListener;
0045:
0046: @Override
0047: protected String getPropertyPrefix() {
0048: return "JideSplitButton";
0049: }
0050:
0051: public static ComponentUI createUI(JComponent c) {
0052: return new MetalJideSplitButtonUI();
0053: }
0054:
0055: @Override
0056: protected void installDefaults() {
0057: _painter = (ThemePainter) UIDefaultsLookup.get("Theme.painter");
0058:
0059: _shadowColor = UIDefaultsLookup.getColor("controlShadow");
0060: _darkShadowColor = UIDefaultsLookup.getColor("controlDkShadow");
0061: _highlight = UIDefaultsLookup.getColor("controlHighlight");
0062: _lightHighlightColor = UIDefaultsLookup
0063: .getColor("controlLtHighlight");
0064:
0065: super .installDefaults();
0066: }
0067:
0068: @Override
0069: protected void uninstallDefaults() {
0070: _painter = null;
0071:
0072: _shadowColor = null;
0073: _highlight = null;
0074: _lightHighlightColor = null;
0075: _darkShadowColor = null;
0076:
0077: super .uninstallDefaults();
0078: }
0079:
0080: @Override
0081: protected void installListeners() {
0082: if (_propertyChangeListener == null)
0083: _propertyChangeListener = createSplitButtonPropertyChangeListener(menuItem);
0084:
0085: if (_propertyChangeListener != null)
0086: menuItem.addPropertyChangeListener(_propertyChangeListener);
0087: super .installListeners();
0088: }
0089:
0090: @Override
0091: protected void uninstallListeners() {
0092: super .uninstallListeners();
0093: if (_propertyChangeListener != null)
0094: menuItem
0095: .removePropertyChangeListener(_propertyChangeListener);
0096:
0097: _propertyChangeListener = null;
0098: }
0099:
0100: protected PropertyChangeListener createSplitButtonPropertyChangeListener(
0101: JComponent c) {
0102: return new PropertyChangeHandler();
0103: }
0104:
0105: /**
0106: * Returns the ui that is of type <code>klass</code>, or null if
0107: * one can not be found.
0108: */
0109: static Object getUIOfType(ComponentUI ui, Class klass) {
0110: if (klass.isInstance(ui)) {
0111: return ui;
0112: }
0113: return null;
0114: }
0115:
0116: /**
0117: * Returns the InputMap for condition <code>condition</code>. Called as
0118: * part of <code>installKeyboardActions</code>.
0119: */
0120: public InputMap getInputMap(int condition, JComponent c) {
0121: if (condition == JComponent.WHEN_FOCUSED) {
0122: MetalJideSplitButtonUI ui = (MetalJideSplitButtonUI) getUIOfType(
0123: ((JideSplitButton) c).getUI(),
0124: MetalJideSplitButtonUI.class);
0125: if (ui != null) {
0126: return (InputMap) UIDefaultsLookup.get(ui
0127: .getPropertyPrefix()
0128: + ".focusInputMap");
0129: }
0130: }
0131: return null;
0132: }
0133:
0134: @Override
0135: protected void installKeyboardActions() {
0136: super .installKeyboardActions();
0137: AbstractButton b = menuItem;
0138:
0139: LazyActionMap.installLazyActionMap(b,
0140: MetalJideSplitButtonUI.class,
0141: "JideSplitButton.actionMap");
0142:
0143: InputMap km = getInputMap(JComponent.WHEN_FOCUSED, b);
0144:
0145: SwingUtilities
0146: .replaceUIInputMap(b, JComponent.WHEN_FOCUSED, km);
0147: }
0148:
0149: @Override
0150: protected void uninstallKeyboardActions() {
0151: AbstractButton b = menuItem;
0152: SwingUtilities.replaceUIInputMap(b,
0153: JComponent.WHEN_IN_FOCUSED_WINDOW, null);
0154: SwingUtilities.replaceUIInputMap(b, JComponent.WHEN_FOCUSED,
0155: null);
0156: SwingUtilities.replaceUIActionMap(b, null);
0157: super .uninstallKeyboardActions();
0158: }
0159:
0160: @Override
0161: protected MouseInputListener createMouseInputListener(JComponent c) {
0162: return new MouseInputHandler();
0163: }
0164:
0165: @Override
0166: protected void paintBackground(Graphics g, JMenuItem menuItem,
0167: Color bgColor) {
0168: ButtonModel model = menuItem.getModel();
0169: int menuWidth = 0;
0170: int menuHeight = 0;
0171: if (JideSwingUtilities.getOrientationOf(menuItem) == SwingConstants.HORIZONTAL) {
0172: menuWidth = menuItem.getWidth();
0173: menuHeight = menuItem.getHeight();
0174: } else {
0175: menuWidth = menuItem.getHeight();
0176: menuHeight = menuItem.getWidth();
0177: }
0178:
0179: if (!((JMenu) menuItem).isTopLevelMenu()) {
0180: super .paintBackground(g, menuItem, bgColor);
0181: if (menuItem.isEnabled()) {
0182: if (model.isArmed() || model.isPressed()
0183: || isMouseOver()) {
0184: g.setColor(selectionForeground);
0185: g.drawLine(menuWidth - _splitButtonMarginOnMenu, 0,
0186: menuWidth - _splitButtonMarginOnMenu,
0187: menuHeight - 2);
0188: JideSwingUtilities.paintArrow(g,
0189: selectionForeground, menuWidth
0190: - _splitButtonMarginOnMenu / 2 - 2,
0191: menuHeight / 2 - 3, 7,
0192: SwingConstants.VERTICAL);
0193: } else {
0194: g.setColor(menuItem.getForeground());
0195: g.drawLine(menuWidth - _splitButtonMarginOnMenu, 0,
0196: menuWidth - _splitButtonMarginOnMenu,
0197: menuHeight - 2);
0198: JideSwingUtilities.paintArrow(g, menuItem
0199: .getForeground(), menuWidth
0200: - _splitButtonMarginOnMenu / 2 - 2,
0201: menuHeight / 2 - 3, 7,
0202: SwingConstants.VERTICAL);
0203: }
0204: } else {
0205: g
0206: .setColor(UIDefaultsLookup
0207: .getColor("controlDkShadow"));
0208: g.drawLine(menuWidth - _splitButtonMarginOnMenu, 0,
0209: menuWidth - _splitButtonMarginOnMenu,
0210: menuHeight - 2);
0211: JideSwingUtilities.paintArrow(g, UIDefaultsLookup
0212: .getColor("controlDkShadow"), menuWidth
0213: - _splitButtonMarginOnMenu / 2 - 2,
0214: menuHeight / 2 - 3, 7, SwingConstants.VERTICAL);
0215: }
0216: return;
0217: }
0218:
0219: if (menuItem.isOpaque()) {
0220: if (menuItem.getParent() != null) {
0221: g.setColor(menuItem.getParent().getBackground());
0222: } else {
0223: g.setColor(menuItem.getBackground());
0224: }
0225: g.fillRect(0, 0, menuWidth, menuHeight);
0226: }
0227:
0228: JideSplitButton b = (JideSplitButton) menuItem;
0229: if (menuItem instanceof ButtonStyle
0230: && ((ButtonStyle) menuItem).getButtonStyle() == ButtonStyle.TOOLBAR_STYLE) {
0231: if ((menuItem instanceof JMenu && model.isSelected())) {
0232: // Draw a dark shadow border without bottom
0233: getPainter().paintSelectedMenu(menuItem, g,
0234: new Rectangle(0, 0, menuWidth, menuHeight),
0235: JideSwingUtilities.getOrientationOf(menuItem),
0236: ThemePainter.STATE_SELECTED);
0237: } else if (model.isArmed() || model.isPressed()) {
0238: Rectangle rect = new Rectangle(0, 0, menuWidth
0239: - _splitButtonMargin, menuHeight);
0240: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0241: getPainter().paintButtonBackground(
0242: menuItem,
0243: g,
0244: rect,
0245: JideSwingUtilities
0246: .getOrientationOf(menuItem),
0247: ThemePainter.STATE_PRESSED);
0248: }
0249: rect = new Rectangle(menuWidth - _splitButtonMargin - 1
0250: + getOffset(), 0, _splitButtonMargin
0251: - getOffset(), menuHeight);
0252: getPainter().paintButtonBackground(menuItem, g, rect,
0253: JideSwingUtilities.getOrientationOf(menuItem),
0254: ThemePainter.STATE_ROLLOVER);
0255: } else if (model instanceof SplitButtonModel
0256: && ((DefaultSplitButtonModel) model)
0257: .isButtonSelected()) {
0258: if ((isMouseOver() || b.hasFocus())
0259: && model.isEnabled()) {
0260: Rectangle rect = new Rectangle(menuWidth
0261: - _splitButtonMargin - 1 + getOffset(), 0,
0262: _splitButtonMargin - getOffset(),
0263: menuHeight);
0264: getPainter().paintButtonBackground(
0265: menuItem,
0266: g,
0267: rect,
0268: JideSwingUtilities
0269: .getOrientationOf(menuItem),
0270: ThemePainter.STATE_ROLLOVER);
0271: rect = new Rectangle(0, 0, menuWidth
0272: - _splitButtonMargin, menuHeight);
0273: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0274: getPainter().paintButtonBackground(
0275: menuItem,
0276: g,
0277: rect,
0278: JideSwingUtilities
0279: .getOrientationOf(menuItem),
0280: ThemePainter.STATE_PRESSED);
0281: }
0282: } else {
0283: Rectangle rect = new Rectangle(menuWidth
0284: - _splitButtonMargin - 1 + getOffset(), 0,
0285: _splitButtonMargin - getOffset(),
0286: menuHeight);
0287: getPainter().paintButtonBackground(
0288: menuItem,
0289: g,
0290: rect,
0291: JideSwingUtilities
0292: .getOrientationOf(menuItem),
0293: ThemePainter.STATE_DEFAULT);
0294: rect = new Rectangle(0, 0, menuWidth
0295: - _splitButtonMargin, menuHeight);
0296: getPainter().paintButtonBackground(
0297: menuItem,
0298: g,
0299: rect,
0300: JideSwingUtilities
0301: .getOrientationOf(menuItem),
0302: ThemePainter.STATE_SELECTED);
0303: }
0304: } else {
0305: if ((isMouseOver() || b.hasFocus())
0306: && model.isEnabled()) {
0307: if (isAlwaysDropdown(menuItem)) {
0308: Rectangle rect = new Rectangle(0, 0, menuWidth,
0309: menuHeight);
0310: getPainter().paintButtonBackground(
0311: menuItem,
0312: g,
0313: rect,
0314: JideSwingUtilities
0315: .getOrientationOf(menuItem),
0316: ThemePainter.STATE_ROLLOVER);
0317: } else {
0318: // Draw a line border with background
0319: Rectangle rect = new Rectangle(0, 0, menuWidth
0320: - _splitButtonMargin, menuHeight);
0321: if (((JideSplitButton) menuItem)
0322: .isButtonEnabled()) {
0323: getPainter()
0324: .paintButtonBackground(
0325: menuItem,
0326: g,
0327: rect,
0328: JideSwingUtilities
0329: .getOrientationOf(menuItem),
0330: ThemePainter.STATE_ROLLOVER);
0331: }
0332: rect = new Rectangle(menuWidth
0333: - _splitButtonMargin - 1 + getOffset(),
0334: 0, _splitButtonMargin - getOffset(),
0335: menuHeight);
0336: getPainter().paintButtonBackground(
0337: menuItem,
0338: g,
0339: rect,
0340: JideSwingUtilities
0341: .getOrientationOf(menuItem),
0342: ThemePainter.STATE_ROLLOVER);
0343: }
0344: }
0345: }
0346: } else if (menuItem instanceof ButtonStyle
0347: && ((ButtonStyle) menuItem).getButtonStyle() == ButtonStyle.FLAT_STYLE) {
0348: if ((menuItem instanceof JMenu && model.isSelected())) {
0349: // Draw a dark shadow border without bottom
0350: getPainter().paintSelectedMenu(menuItem, g,
0351: new Rectangle(0, 0, menuWidth, menuHeight),
0352: JideSwingUtilities.getOrientationOf(menuItem),
0353: ThemePainter.STATE_SELECTED);
0354: } else if (model.isArmed() || model.isPressed()) {
0355: Rectangle rect = new Rectangle(0, 0, menuWidth
0356: - _splitButtonMargin, menuHeight);
0357: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0358: JideSwingUtilities.paintBackground(g, rect,
0359: _highlight, _highlight);
0360: }
0361: rect = new Rectangle(menuWidth - _splitButtonMargin
0362: + getOffset(), 0, _splitButtonMargin
0363: - getOffset(), menuHeight);
0364: JideSwingUtilities.paintBackground(g, rect, _highlight,
0365: _highlight);
0366:
0367: if (!b.isOpaque()) {
0368: rect = new Rectangle(0, 0, menuWidth
0369: - _splitButtonMargin, menuHeight);
0370: paintSunkenBorder(g, rect);
0371: rect = new Rectangle(menuWidth - _splitButtonMargin
0372: + getOffset(), 0, _splitButtonMargin
0373: - getOffset(), menuHeight);
0374: paintRaisedBorder(g, rect);
0375: }
0376: } else if (model instanceof SplitButtonModel
0377: && ((DefaultSplitButtonModel) model)
0378: .isButtonSelected()) {
0379: if ((isMouseOver() || b.hasFocus())
0380: && model.isEnabled()) {
0381: Rectangle rect = new Rectangle(menuWidth
0382: - _splitButtonMargin + getOffset(), 0,
0383: _splitButtonMargin - getOffset(),
0384: menuHeight);
0385: JideSwingUtilities.paintBackground(g, rect,
0386: _highlight, _highlight);
0387: rect = new Rectangle(0, 0, menuWidth
0388: - _splitButtonMargin, menuHeight);
0389: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0390: JideSwingUtilities.paintBackground(g, rect,
0391: _highlight, _highlight);
0392: }
0393: if (!b.isOpaque()) {
0394: rect = new Rectangle(0, 0, menuWidth
0395: - _splitButtonMargin, menuHeight);
0396: paintSunkenBorder(g, rect);
0397: rect = new Rectangle(menuWidth
0398: - _splitButtonMargin + getOffset(), 0,
0399: _splitButtonMargin - getOffset(),
0400: menuHeight);
0401: paintRaisedBorder(g, rect);
0402: }
0403: } else {
0404: Rectangle rect = null;
0405: if (b.isOpaque()) {
0406: rect = new Rectangle(menuWidth
0407: - _splitButtonMargin + getOffset(), 0,
0408: _splitButtonMargin - getOffset(),
0409: menuHeight);
0410: JideSwingUtilities.paintBackground(g, rect,
0411: _highlight, _highlight);
0412: }
0413: rect = new Rectangle(0, 0, menuWidth
0414: - _splitButtonMargin, menuHeight);
0415: JideSwingUtilities.paintBackground(g, rect,
0416: _highlight, _highlight);
0417:
0418: if (!b.isOpaque()) {
0419: rect = new Rectangle(0, 0, menuWidth
0420: - _splitButtonMargin, menuHeight);
0421: paintSunkenBorder(g, rect);
0422: // rect = new Rectangle(menuWidth - _splitButtonMargin + getOffset(), 0, _splitButtonMargin - getOffset(), menuHeight);
0423: // paintRaisedBorder(g, rect);
0424: }
0425: }
0426:
0427: } else {
0428: if ((isMouseOver() || b.hasFocus())
0429: && model.isEnabled()) {
0430: // Draw a line border with background
0431: Rectangle rect = new Rectangle(0, 0, menuWidth
0432: - _splitButtonMargin, menuHeight);
0433: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0434: JideSwingUtilities.paintBackground(g, rect,
0435: _highlight, _highlight);
0436: }
0437: rect = new Rectangle(menuWidth - _splitButtonMargin
0438: - getOffset(), 0, _splitButtonMargin
0439: - getOffset(), menuHeight);
0440: JideSwingUtilities.paintBackground(g, rect,
0441: _highlight, _highlight);
0442:
0443: rect = new Rectangle(0, 0, menuWidth
0444: - _splitButtonMargin, menuHeight);
0445: paintRaisedBorder(g, rect);
0446: rect = new Rectangle(menuWidth - _splitButtonMargin
0447: + getOffset(), 0, _splitButtonMargin
0448: - getOffset(), menuHeight);
0449: paintRaisedBorder(g, rect);
0450: } else {
0451: if (b.isOpaque()) {
0452: Rectangle rect = new Rectangle(0, 0, menuWidth
0453: - _splitButtonMargin, menuHeight);
0454: if (((JideSplitButton) menuItem)
0455: .isButtonEnabled()) {
0456: getPainter()
0457: .paintButtonBackground(
0458: menuItem,
0459: g,
0460: rect,
0461: JideSwingUtilities
0462: .getOrientationOf(menuItem),
0463: ThemePainter.STATE_DEFAULT);
0464: }
0465: rect = new Rectangle(menuWidth
0466: - _splitButtonMargin - 1 + getOffset(),
0467: 0, _splitButtonMargin - getOffset(),
0468: menuHeight);
0469: getPainter().paintButtonBackground(
0470: menuItem,
0471: g,
0472: rect,
0473: JideSwingUtilities
0474: .getOrientationOf(menuItem),
0475: ThemePainter.STATE_DEFAULT);
0476: }
0477: }
0478: }
0479: } else if (menuItem instanceof ButtonStyle
0480: && ((ButtonStyle) menuItem).getButtonStyle() == ButtonStyle.TOOLBOX_STYLE) {
0481: if ((menuItem instanceof JMenu && model.isSelected())) {
0482: // Draw a dark shadow border without bottom
0483: getPainter().paintSelectedMenu(menuItem, g,
0484: new Rectangle(0, 0, menuWidth, menuHeight),
0485: JideSwingUtilities.getOrientationOf(menuItem),
0486: ThemePainter.STATE_SELECTED);
0487: } else if (model.isArmed() || model.isPressed()) {
0488: Rectangle rect = new Rectangle(0, 0, menuWidth
0489: - _splitButtonMargin, menuHeight);
0490: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0491: getPainter().paintButtonBackground(
0492: menuItem,
0493: g,
0494: rect,
0495: JideSwingUtilities
0496: .getOrientationOf(menuItem),
0497: ThemePainter.STATE_PRESSED);
0498: }
0499: rect = new Rectangle(menuWidth - _splitButtonMargin
0500: + getOffset(), 0, _splitButtonMargin
0501: - getOffset(), menuHeight);
0502: getPainter().paintButtonBackground(menuItem, g, rect,
0503: JideSwingUtilities.getOrientationOf(menuItem),
0504: ThemePainter.STATE_ROLLOVER);
0505:
0506: if (!b.isOpaque()) {
0507: rect = new Rectangle(0, 0, menuWidth
0508: - _splitButtonMargin, menuHeight);
0509: paintSunken2Border(g, rect);
0510: rect = new Rectangle(menuWidth - _splitButtonMargin
0511: + getOffset(), 0, _splitButtonMargin
0512: - getOffset(), menuHeight);
0513: paintRaisedBorder(g, rect);
0514: }
0515: } else if (model instanceof SplitButtonModel
0516: && ((DefaultSplitButtonModel) model)
0517: .isButtonSelected()) {
0518: if (isMouseOver() && model.isEnabled()) {
0519: Rectangle rect = new Rectangle(menuWidth
0520: - _splitButtonMargin + getOffset(), 0,
0521: _splitButtonMargin - getOffset(),
0522: menuHeight);
0523: getPainter().paintButtonBackground(
0524: menuItem,
0525: g,
0526: rect,
0527: JideSwingUtilities
0528: .getOrientationOf(menuItem),
0529: ThemePainter.STATE_ROLLOVER);
0530: rect = new Rectangle(0, 0, menuWidth
0531: - _splitButtonMargin, menuHeight);
0532: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0533: getPainter().paintButtonBackground(
0534: menuItem,
0535: g,
0536: rect,
0537: JideSwingUtilities
0538: .getOrientationOf(menuItem),
0539: ThemePainter.STATE_PRESSED);
0540: }
0541: if (!b.isOpaque()) {
0542: rect = new Rectangle(0, 0, menuWidth
0543: - _splitButtonMargin, menuHeight);
0544: paintSunken2Border(g, rect);
0545: rect = new Rectangle(menuWidth
0546: - _splitButtonMargin + getOffset(), 0,
0547: _splitButtonMargin - getOffset(),
0548: menuHeight);
0549: paintRaisedBorder(g, rect);
0550: }
0551: } else {
0552: Rectangle rect = null;
0553: if (b.isOpaque()) {
0554: rect = new Rectangle(menuWidth
0555: - _splitButtonMargin + getOffset(), 0,
0556: _splitButtonMargin - getOffset(),
0557: menuHeight);
0558: getPainter().paintButtonBackground(
0559: menuItem,
0560: g,
0561: rect,
0562: JideSwingUtilities
0563: .getOrientationOf(menuItem),
0564: ThemePainter.STATE_DEFAULT);
0565: }
0566: rect = new Rectangle(0, 0, menuWidth
0567: - _splitButtonMargin, menuHeight);
0568: getPainter().paintButtonBackground(
0569: menuItem,
0570: g,
0571: rect,
0572: JideSwingUtilities
0573: .getOrientationOf(menuItem),
0574: ThemePainter.STATE_SELECTED);
0575:
0576: if (!b.isOpaque()) {
0577: rect = new Rectangle(0, 0, menuWidth
0578: - _splitButtonMargin, menuHeight);
0579: paintSunken2Border(g, rect);
0580: rect = new Rectangle(menuWidth
0581: - _splitButtonMargin + getOffset(), 0,
0582: _splitButtonMargin - getOffset(),
0583: menuHeight);
0584: paintRaisedBorder(g, rect);
0585: }
0586: }
0587:
0588: } else {
0589: if (isMouseOver() && model.isEnabled()) {
0590: // Draw a line border with background
0591: Rectangle rect = new Rectangle(0, 0, menuWidth
0592: - _splitButtonMargin, menuHeight);
0593: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0594: getPainter().paintButtonBackground(
0595: menuItem,
0596: g,
0597: rect,
0598: JideSwingUtilities
0599: .getOrientationOf(menuItem),
0600: ThemePainter.STATE_ROLLOVER);
0601: }
0602: rect = new Rectangle(menuWidth - _splitButtonMargin
0603: - getOffset(), 0, _splitButtonMargin
0604: - getOffset(), menuHeight);
0605: getPainter().paintButtonBackground(
0606: menuItem,
0607: g,
0608: rect,
0609: JideSwingUtilities
0610: .getOrientationOf(menuItem),
0611: ThemePainter.STATE_ROLLOVER);
0612:
0613: rect = new Rectangle(0, 0, menuWidth
0614: - _splitButtonMargin, menuHeight);
0615: paintRaised2Border(g, rect);
0616: rect = new Rectangle(menuWidth - _splitButtonMargin
0617: + getOffset(), 0, _splitButtonMargin
0618: - getOffset(), menuHeight);
0619: paintRaised2Border(g, rect);
0620: } else {
0621: if (b.isOpaque()) {
0622: Rectangle rect = new Rectangle(0, 0, menuWidth
0623: - _splitButtonMargin, menuHeight);
0624: if (((JideSplitButton) menuItem)
0625: .isButtonEnabled()) {
0626: getPainter()
0627: .paintButtonBackground(
0628: menuItem,
0629: g,
0630: rect,
0631: JideSwingUtilities
0632: .getOrientationOf(menuItem),
0633: ThemePainter.STATE_DEFAULT);
0634: }
0635: rect = new Rectangle(menuWidth
0636: - _splitButtonMargin - 1 + getOffset(),
0637: 0, _splitButtonMargin - getOffset(),
0638: menuHeight);
0639: getPainter().paintButtonBackground(
0640: menuItem,
0641: g,
0642: rect,
0643: JideSwingUtilities
0644: .getOrientationOf(menuItem),
0645: ThemePainter.STATE_DEFAULT);
0646: } else {
0647: Rectangle rect = new Rectangle(0, 0, menuWidth
0648: - _splitButtonMargin, menuHeight);
0649: paintRaisedBorder(g, rect);
0650: rect = new Rectangle(menuWidth
0651: - _splitButtonMargin + getOffset(), 0,
0652: _splitButtonMargin - getOffset(),
0653: menuHeight);
0654: paintRaisedBorder(g, rect);
0655: }
0656: }
0657: }
0658: }
0659:
0660: if (menuItem.isEnabled()) {
0661: JideSwingUtilities.paintArrow(g, menuItem.getForeground(),
0662: menuWidth - 10, menuHeight / 2 - 1, 5,
0663: SwingConstants.HORIZONTAL);
0664: } else {
0665: JideSwingUtilities.paintArrow(g, UIDefaultsLookup
0666: .getColor("controlDkShadow"), menuWidth - 10,
0667: menuHeight / 2 - 1, 5, SwingConstants.HORIZONTAL);
0668: }
0669: }
0670:
0671: private void paintSunkenBorder(Graphics g, Rectangle b) {
0672: Color old = g.getColor();
0673: g.setColor(_shadowColor); // inner 3D border
0674: g.drawLine(b.x, b.y, b.x + b.width - 1, b.y);
0675: g.drawLine(b.x, b.y, b.x, b.y + b.height - 1);
0676:
0677: g.setColor(_lightHighlightColor); // black drop shadow __|
0678: g.drawLine(b.x, b.y + b.height - 1, b.x + b.width - 1, b.y
0679: + b.height - 1);
0680: g.drawLine(b.x + b.width - 1, b.y, b.x + b.width - 1, b.y
0681: + b.height - 1);
0682: g.setColor(old);
0683: }
0684:
0685: private void paintSunken2Border(Graphics g, Rectangle b) {
0686: Color old = g.getColor();
0687: g.setColor(_darkShadowColor); // inner 3D border
0688: g.drawLine(b.x, b.y, b.x + b.width - 2, b.y);
0689: g.drawLine(b.x, b.y, b.x, b.y + b.height - 2);
0690:
0691: g.setColor(_shadowColor); // inner 3D border
0692: g.drawLine(b.x + 1, b.y + 1, b.x + b.width - 3, b.y + 1);
0693: g.drawLine(b.x + 1, b.y + 1, b.x + 1, b.y + b.height - 3);
0694:
0695: g.setColor(_lightHighlightColor); // black drop shadow __|
0696: g.drawLine(b.x, b.y + b.height - 1, b.x + b.width - 1, b.y
0697: + b.height - 1);
0698: g.drawLine(b.x + b.width - 1, b.x, b.x + b.width - 1, b.y
0699: + b.height - 1);
0700: g.setColor(old);
0701: }
0702:
0703: private void paintRaised2Border(Graphics g, Rectangle b) {
0704: Color old = g.getColor();
0705: g.setColor(_lightHighlightColor); // inner 3D border
0706: g.drawLine(b.x, b.y, b.x + b.width - 1, b.y);
0707: g.drawLine(b.x, b.y, b.x, b.y + b.height - 1);
0708:
0709: g.setColor(_shadowColor); // gray drop shadow __|
0710: g.drawLine(b.x + 1, b.y + b.height - 2, b.x + b.width - 2, b.y
0711: + b.height - 2);
0712: g.drawLine(b.x + b.width - 2, 1, b.x + b.width - 2, b.y
0713: + b.height - 2);
0714:
0715: g.setColor(_darkShadowColor); // black drop shadow __|
0716: g.drawLine(b.x, b.y + b.height - 1, b.x + b.width - 1, b.y
0717: + b.height - 1);
0718: g.drawLine(b.x + b.width - 1, b.y, b.x + b.width - 1, b.y
0719: + b.height - 1);
0720: g.setColor(old);
0721: }
0722:
0723: private void paintRaisedBorder(Graphics g, Rectangle b) {
0724: Color old = g.getColor();
0725: g.setColor(_lightHighlightColor); // inner 3D border
0726: g.drawLine(b.x, b.y, b.x + b.width - 1, b.y);
0727: g.drawLine(b.x, b.y, b.x, b.y + b.height - 1);
0728:
0729: g.setColor(_shadowColor); // black drop shadow __|
0730: g.drawLine(b.x, b.y + b.height - 1, b.x + b.width - 1, b.y
0731: + b.height - 1);
0732: g.drawLine(b.x + b.width - 1, b.y, b.x + b.width - 1, b.y
0733: + b.height - 1);
0734: g.setColor(old);
0735: }
0736:
0737: @Override
0738: protected void paintText(Graphics g, JMenuItem menuItem,
0739: Rectangle textRect, String text) {
0740: ButtonModel model = menuItem.getModel();
0741: FontMetrics fm = g.getFontMetrics();
0742: int mnemIndex = menuItem.getDisplayedMnemonicIndex();
0743:
0744: if (!model.isEnabled()
0745: || !((JideSplitButton) menuItem).isButtonEnabled()) {
0746: // *** paint the text disabled
0747: if (UIDefaultsLookup.get("MenuItem.disabledForeground") instanceof Color) {
0748: g.setColor(UIDefaultsLookup
0749: .getColor("MenuItem.disabledForeground"));
0750: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text,
0751: mnemIndex, textRect.x, textRect.y
0752: + fm.getAscent());
0753: } else {
0754: g.setColor(menuItem.getBackground().brighter());
0755: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text,
0756: mnemIndex, textRect.x, textRect.y
0757: + fm.getAscent());
0758: g.setColor(menuItem.getBackground().darker());
0759: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text,
0760: mnemIndex, textRect.x - 1, textRect.y
0761: + fm.getAscent() - 1);
0762: }
0763: } else {
0764: // *** paint the text normally
0765: if (model.isArmed()
0766: || (menuItem instanceof JMenu && model.isSelected())) {
0767: g.setColor(selectionForeground); // Uses protected field.
0768: }
0769: BasicGraphicsUtils.drawStringUnderlineCharAt(g, text,
0770: mnemIndex, textRect.x, textRect.y + fm.getAscent());
0771: }
0772: }
0773:
0774: protected class MouseInputHandler implements MouseInputListener {
0775: public void mouseClicked(MouseEvent e) {
0776: cancelMenuIfNecessary(e);
0777: }
0778:
0779: /**
0780: * Invoked when the mouse has been clicked on the menu. This
0781: * method clears or sets the selection path of the
0782: * MenuSelectionManager.
0783: *
0784: * @param e the mouse event
0785: */
0786: public void mousePressed(MouseEvent e) {
0787: JMenu menu = (JMenu) menuItem;
0788: if (!menu.isEnabled())
0789: return;
0790:
0791: setMouseOver(true);
0792:
0793: if (!SwingUtilities.isLeftMouseButton(e)) {
0794: return;
0795: }
0796: if (isClickOnButton(e, menu)) {
0797: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0798: // click button
0799: menu.getModel().setArmed(true);
0800: menu.getModel().setPressed(true);
0801: }
0802: if (!menu.hasFocus() && menu.isRequestFocusEnabled()) {
0803: menu.requestFocus();
0804: }
0805: } else {
0806: downButtonPressed(menu);
0807: }
0808: }
0809:
0810: private boolean isClickOnButton(MouseEvent e, JMenu menu) {
0811: if (((JideSplitButton) menu).isAlwaysDropdown()) {
0812: return false;
0813: }
0814:
0815: boolean clickOnDropDown = false;
0816: int size = ((JMenu) menuItem).isTopLevelMenu() ? _splitButtonMargin
0817: : _splitButtonMarginOnMenu;
0818: if (JideSwingUtilities.getOrientationOf(menuItem) == SwingConstants.HORIZONTAL) {
0819: if (e.getPoint().getX() < menu.getWidth() - size) {
0820: clickOnDropDown = true;
0821: }
0822: } else {
0823: if (e.getPoint().getY() < menu.getHeight() - size) {
0824: clickOnDropDown = true;
0825: }
0826: }
0827: return clickOnDropDown;
0828: }
0829:
0830: /**
0831: * Invoked when the mouse has been released on the menu. Delegates the
0832: * mouse event to the MenuSelectionManager.
0833: *
0834: * @param e the mouse event
0835: */
0836: public void mouseReleased(MouseEvent e) {
0837: if (!isMouseOver()) {
0838: // these two lines order matters. In this order, it would not trigger actionPerformed.
0839: menuItem.getModel().setArmed(false);
0840: menuItem.getModel().setPressed(false);
0841: }
0842: cancelMenuIfNecessary(e);
0843: }
0844:
0845: private void cancelMenuIfNecessary(MouseEvent e) {
0846: JMenu menu = (JMenu) menuItem;
0847: if (!menu.isEnabled())
0848: return;
0849: if (isClickOnButton(e, menu)) {
0850: if (((JideSplitButton) menuItem).isButtonEnabled()) {
0851: // click button
0852: // these two lines order matters. In this order, it would trigger actionPerformed.
0853: if (SwingUtilities.isLeftMouseButton(e)) {
0854: menu.getModel().setPressed(false);
0855: menu.getModel().setArmed(false);
0856: } else {
0857: menu.getModel().setArmed(false);
0858: menu.getModel().setPressed(false);
0859: }
0860:
0861: MenuSelectionManager manager = MenuSelectionManager
0862: .defaultManager();
0863: MenuElement[] menuElements = manager
0864: .getSelectedPath();
0865: for (int i = menuElements.length - 1; i >= 0; i--) {
0866: MenuElement menuElement = menuElements[i];
0867: if (menuElement instanceof JPopupMenu
0868: && ((JPopupMenu) menuElement)
0869: .isAncestorOf(menu)) {
0870: menu.getModel().setRollover(false);
0871: setMouseOver(false);
0872: manager.clearSelectedPath();
0873: }
0874: }
0875: }
0876: } else {
0877: // MenuSelectionManager manager =
0878: // MenuSelectionManager.defaultManager();
0879: // manager.processMouseEvent(e);
0880: // if (!e.isConsumed())
0881: // manager.clearSelectedPath();
0882: }
0883: }
0884:
0885: /**
0886: * Invoked when the cursor enters the menu. This method sets the selected
0887: * path for the MenuSelectionManager and handles the case
0888: * in which a menu item is used to pop up an additional menu, as in a
0889: * hierarchical menu system.
0890: *
0891: * @param e the mouse event; not used
0892: */
0893: public void mouseEntered(MouseEvent e) {
0894: JMenu menu = (JMenu) menuItem;
0895: if (!menu.isEnabled())
0896: return;
0897:
0898: MenuSelectionManager manager = MenuSelectionManager
0899: .defaultManager();
0900: MenuElement selectedPath[] = manager.getSelectedPath();
0901: if (!menu.isTopLevelMenu()) {
0902: if (!(selectedPath.length > 0 && selectedPath[selectedPath.length - 1] == menu
0903: .getPopupMenu())) {
0904: if (menu.getDelay() == 0) {
0905: appendPath(getPath(), menu.getPopupMenu());
0906: } else {
0907: manager.setSelectedPath(getPath());
0908: setupPostTimer(menu);
0909: }
0910: }
0911: } else {
0912: if (selectedPath.length > 0
0913: && selectedPath[0] == menu.getParent()) {
0914: MenuElement newPath[] = new MenuElement[3];
0915: // A top level menu's parent is by definition
0916: // a JMenuBar
0917: newPath[0] = (MenuElement) menu.getParent();
0918: newPath[1] = menu;
0919: newPath[2] = menu.getPopupMenu();
0920: manager.setSelectedPath(newPath);
0921: }
0922: }
0923:
0924: if (!SwingUtilities.isLeftMouseButton(e)) {
0925: setMouseOver(true);
0926: }
0927: menuItem.repaint();
0928: }
0929:
0930: public void mouseExited(MouseEvent e) {
0931: setMouseOver(false);
0932: menuItem.repaint();
0933: }
0934:
0935: /**
0936: * Invoked when a mouse button is pressed on the menu and then dragged.
0937: * Delegates the mouse event to the MenuSelectionManager.
0938: *
0939: * @param e the mouse event
0940: * @see java.awt.event.MouseMotionListener#mouseDragged
0941: */
0942: public void mouseDragged(MouseEvent e) {
0943: JMenu menu = (JMenu) menuItem;
0944: if (!menu.isEnabled())
0945: return;
0946: MenuSelectionManager.defaultManager().processMouseEvent(e);
0947: }
0948:
0949: public void mouseMoved(MouseEvent e) {
0950: }
0951: }
0952:
0953: @Override
0954: public Dimension getMinimumSize(JComponent c) {
0955: if (!(c instanceof JMenu) || !((JMenu) c).isTopLevelMenu()) {
0956: return super .getMinimumSize(c);
0957: }
0958:
0959: Dimension d = getPreferredSize(c);
0960: View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0961: if (v != null) {
0962: if (JideSwingUtilities.getOrientationOf(c) == SwingConstants.HORIZONTAL)
0963: d.width -= v.getPreferredSpan(View.X_AXIS)
0964: - v.getMinimumSpan(View.X_AXIS);
0965: else
0966: // TODO: not sure if this is correct
0967: d.height -= v.getPreferredSpan(View.X_AXIS)
0968: - v.getMinimumSpan(View.X_AXIS);
0969: }
0970:
0971: int size = ((JMenu) menuItem).isTopLevelMenu() ? _splitButtonMargin
0972: : _splitButtonMarginOnMenu;
0973: d.width += size;
0974:
0975: return d;
0976: }
0977:
0978: @Override
0979: public Dimension getPreferredSize(JComponent c) {
0980: if (!(c instanceof JMenu) || !((JMenu) c).isTopLevelMenu()) {
0981: return super .getPreferredSize(c);
0982: }
0983:
0984: AbstractButton b = (AbstractButton) c;
0985:
0986: boolean isHorizontal = true;
0987: if (JideSwingUtilities.getOrientationOf(c) == SwingConstants.VERTICAL) {
0988: isHorizontal = false;
0989: }
0990:
0991: // JDK PORTING HINT
0992: // JDK1.3: No getIconTextGap, use defaultTextIconGap
0993: Dimension d = BasicGraphicsUtils.getPreferredButtonSize(b,
0994: defaultTextIconGap);
0995: // d.width += b.getMargin().left + b.getMargin().right;
0996: // d.height += b.getMargin().bottom + b.getMargin().top;
0997:
0998: int size = ((JMenu) menuItem).isTopLevelMenu() ? _splitButtonMargin
0999: : _splitButtonMarginOnMenu;
1000: d.width += size;
1001:
1002: if (isHorizontal)
1003: return d;
1004: else
1005: return new Dimension(d.height, d.width); // swap width and height
1006: }
1007:
1008: @Override
1009: public Dimension getMaximumSize(JComponent c) {
1010: if (!(c instanceof JMenu) || !((JMenu) c).isTopLevelMenu()) {
1011: return super .getMaximumSize(c);
1012: }
1013:
1014: Dimension d = getPreferredSize(c);
1015: View v = (View) c.getClientProperty(BasicHTML.propertyKey);
1016: if (v != null) {
1017: d.width += v.getMaximumSpan(View.X_AXIS)
1018: - v.getPreferredSpan(View.X_AXIS);
1019: }
1020: boolean isHorizontal = true;
1021: if (JideSwingUtilities.getOrientationOf(c) == SwingConstants.VERTICAL) {
1022: isHorizontal = false;
1023: }
1024:
1025: int size = ((JMenu) menuItem).isTopLevelMenu() ? _splitButtonMargin
1026: : _splitButtonMarginOnMenu;
1027: if (isHorizontal)
1028: d.width += size;
1029: else
1030: d.height += size;
1031: return d;
1032: }
1033:
1034: protected void paintIcon(JMenuItem b, Graphics g) {
1035: ButtonModel model = b.getModel();
1036:
1037: // Paint the Icon
1038: if (b.getIcon() != null) {
1039: // rotate back since we don't want to paint icon in a rotated way.
1040: if (JideSwingUtilities.getOrientationOf(b) == SwingConstants.VERTICAL) {
1041: ((Graphics2D) g).translate(0, b.getWidth() - 1);
1042: ((Graphics2D) g).rotate(-Math.PI / 2);
1043: }
1044: Icon icon;
1045: if (!model.isEnabled()) {
1046: icon = b.getDisabledIcon();
1047: if (icon == null) {
1048: icon = b.getIcon();
1049: if (icon instanceof ImageIcon) {
1050: icon = IconsFactory
1051: .createGrayImage(((ImageIcon) icon)
1052: .getImage());
1053: } else {
1054: icon = IconsFactory.createGrayImage(b, icon);
1055: }
1056: }
1057: } else if (model.isPressed() && model.isArmed()) {
1058: icon = b.getPressedIcon();
1059: if (icon == null) {
1060: // Use default icon
1061: icon = b.getIcon();
1062: }
1063: } else {
1064: icon = b.getIcon();
1065: }
1066:
1067: if (icon != null) {
1068: icon.paintIcon(b, g, iconRect.x, iconRect.y);
1069: // if (model.isRollover() && !model.isPressed() && !model.isSelected()) {
1070: // icon.paintIcon(b, g, iconRect.x, iconRect.y);
1071: // }
1072: // else {
1073: // icon.paintIcon(b, g, iconRect.x, iconRect.y);
1074: // }
1075: }
1076:
1077: if (JideSwingUtilities.getOrientationOf(b) == SwingConstants.VERTICAL) {
1078: ((Graphics2D) g).rotate(Math.PI / 2);
1079: ((Graphics2D) g).translate(0, -b.getHeight() + 1);
1080: }
1081: }
1082: }
1083:
1084: protected int getOffset() {
1085: return 0;
1086: }
1087:
1088: protected boolean isAlwaysDropdown(JMenuItem menuItem) {
1089: if (menuItem instanceof JideSplitButton) {
1090: return ((JideSplitButton) menuItem).isAlwaysDropdown();
1091: } else {
1092: return false;
1093: }
1094: }
1095:
1096: /**
1097: * Actions for Buttons. Two type of action are supported:
1098: * pressed: Moves the button to a pressed state
1099: * released: Disarms the button.
1100: */
1101: private static class Actions extends UIAction {
1102: private static final String PRESS = "pressed";
1103: private static final String RELEASE = "released";
1104: private static final String DOWN_PRESS = "downPressed";
1105: private static final String DOWN_RELEASE = "downReleased";
1106:
1107: Actions(String name) {
1108: super (name);
1109: }
1110:
1111: public void actionPerformed(ActionEvent e) {
1112: AbstractButton b = (AbstractButton) e.getSource();
1113: String key = getName();
1114:
1115: // if isAlwaysDropDown it true, treat PRESS as DOWN_PRESS
1116: if (PRESS.equals(key)
1117: && ((JideSplitButton) b).isAlwaysDropdown()) {
1118: key = DOWN_PRESS;
1119: }
1120:
1121: if (PRESS.equals(key)) {
1122: ButtonModel model = b.getModel();
1123: model.setArmed(true);
1124: model.setPressed(true);
1125: if (!b.hasFocus()) {
1126: b.requestFocus();
1127: }
1128: } else if (RELEASE.equals(key)) {
1129: ButtonModel model = b.getModel();
1130: model.setPressed(false);
1131: model.setArmed(false);
1132: } else if (DOWN_PRESS.equals(key)) {
1133: downButtonPressed((JMenu) b);
1134: } else if (DOWN_RELEASE.equals(key)) {
1135: }
1136: }
1137:
1138: @Override
1139: public boolean isEnabled(Object sender) {
1140: if (sender != null
1141: && (sender instanceof AbstractButton)
1142: && !((AbstractButton) sender).getModel()
1143: .isEnabled()) {
1144: return false;
1145: } else {
1146: return true;
1147: }
1148: }
1149: }
1150:
1151: /**
1152: * Populates Buttons actions.
1153: */
1154: public static void loadActionMap(LazyActionMap map) {
1155: map.put(new Actions(Actions.PRESS));
1156: map.put(new Actions(Actions.RELEASE));
1157: map.put(new Actions(Actions.DOWN_PRESS));
1158: map.put(new Actions(Actions.DOWN_RELEASE));
1159: }
1160:
1161: protected static void downButtonPressed(JMenu menu) {
1162: MenuSelectionManager manager = MenuSelectionManager
1163: .defaultManager();
1164: if (menu.isTopLevelMenu()) {
1165: if (menu.isSelected()) {
1166: manager.clearSelectedPath();
1167: } else {
1168: Container cnt = menu.getParent();
1169: if (cnt != null && cnt instanceof MenuElement) {
1170: ArrayList parents = new ArrayList();
1171: while (cnt instanceof MenuElement) {
1172: parents.add(0, cnt);
1173: cnt = cnt.getParent();
1174: }
1175:
1176: MenuElement me[] = new MenuElement[parents.size() + 1];
1177: for (int i = 0; i < parents.size(); i++) {
1178: Container container = (Container) parents
1179: .get(i);
1180: me[i] = (MenuElement) container;
1181: }
1182: me[parents.size()] = menu;
1183: manager.setSelectedPath(me);
1184: } else {
1185: MenuElement me[] = new MenuElement[1];
1186: me[0] = menu;
1187: manager.setSelectedPath(me);
1188: }
1189: }
1190: }
1191:
1192: MenuElement selectedPath[] = manager.getSelectedPath();
1193: if (selectedPath.length > 0
1194: && selectedPath[selectedPath.length - 1] != menu
1195: .getPopupMenu()) {
1196: if (menu.isTopLevelMenu() || menu.getDelay() == 0) {
1197: appendPath(selectedPath, menu.getPopupMenu());
1198: } else {
1199: // setupPostTimer(menu); // TODO
1200: }
1201: }
1202: }
1203:
1204: private class PropertyChangeHandler implements
1205: PropertyChangeListener {
1206: public void propertyChange(PropertyChangeEvent e) {
1207: String prop = e.getPropertyName();
1208: if (prop.equals(ButtonStyle.BUTTON_STYLE_PROPERTY)) {
1209: AbstractButton b = (AbstractButton) e.getSource();
1210: b.repaint();
1211: }
1212: }
1213: }
1214:
1215: }
|