001: /*
002: * Copyright (c) 2001-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.looks.common;
032:
033: import java.awt.Color;
034: import java.awt.Dimension;
035: import java.awt.Graphics;
036: import java.awt.event.MouseAdapter;
037: import java.awt.event.MouseEvent;
038: import java.awt.event.MouseListener;
039:
040: import javax.swing.*;
041: import javax.swing.plaf.ComponentUI;
042: import javax.swing.plaf.UIResource;
043: import javax.swing.plaf.basic.BasicMenuUI;
044:
045: /**
046: * An implementation of <code>MenuUI</code> used by the JGoodies Windows
047: * and Plastic looks. Unlike it's superclass, it aligns submenu items.
048: *
049: * @author Karsten Lentzsch
050: * @version $Revision: 1.6 $
051: */
052:
053: public class ExtBasicMenuUI extends BasicMenuUI {
054:
055: private static final String MENU_PROPERTY_PREFIX = "Menu";
056: private static final String SUBMENU_PROPERTY_PREFIX = "MenuItem";
057:
058: // May be changed to SUBMENU_PROPERTY_PREFIX later
059: private String propertyPrefix = MENU_PROPERTY_PREFIX;
060:
061: private MenuItemRenderer renderer;
062: private MouseListener mouseListener;
063:
064: public static ComponentUI createUI(JComponent b) {
065: return new ExtBasicMenuUI();
066: }
067:
068: // Install and Uninstall ************************************************
069:
070: protected void installDefaults() {
071: super .installDefaults();
072: if (arrowIcon == null || arrowIcon instanceof UIResource) {
073: arrowIcon = UIManager.getIcon("Menu.arrowIcon");
074: }
075: renderer = new MenuItemRenderer(menuItem, false,
076: acceleratorFont, selectionForeground,
077: disabledForeground, acceleratorForeground,
078: acceleratorSelectionForeground);
079: Integer gap = (Integer) UIManager.get(getPropertyPrefix()
080: + ".textIconGap");
081: defaultTextIconGap = gap != null ? gap.intValue() : 2;
082: LookAndFeel.installBorder(menuItem, getPropertyPrefix()
083: + ".border");
084: }
085:
086: protected void uninstallDefaults() {
087: super .uninstallDefaults();
088: renderer = null;
089: }
090:
091: protected String getPropertyPrefix() {
092: return propertyPrefix;
093: }
094:
095: protected Dimension getPreferredMenuItemSize(JComponent c,
096: Icon aCheckIcon, Icon anArrowIcon, int textIconGap) {
097:
098: if (isSubMenu(menuItem)) {
099: ensureSubMenuInstalled();
100: return renderer.getPreferredMenuItemSize(c, aCheckIcon,
101: anArrowIcon, textIconGap);
102: }
103: return super .getPreferredMenuItemSize(c, aCheckIcon,
104: anArrowIcon, textIconGap);
105: }
106:
107: protected void paintMenuItem(Graphics g, JComponent c,
108: Icon aCheckIcon, Icon anArrowIcon, Color background,
109: Color foreground, int textIconGap) {
110: if (isSubMenu(menuItem)) {
111: renderer.paintMenuItem(g, c, aCheckIcon, anArrowIcon,
112: background, foreground, textIconGap);
113: } else {
114: super .paintMenuItem(g, c, aCheckIcon, anArrowIcon,
115: background, foreground, textIconGap);
116: }
117: }
118:
119: /**
120: * Checks if we have already detected the correct menu type,
121: * menu in menu bar vs. sub menu; reinstalls if necessary.
122: */
123: private void ensureSubMenuInstalled() {
124: if (propertyPrefix.equals(SUBMENU_PROPERTY_PREFIX))
125: return;
126:
127: ButtonModel model = menuItem.getModel();
128:
129: //save values of armed and selected properties.
130: //they will be resetted in #ununinstallDefaults().
131: boolean oldArmed = model.isArmed();
132: boolean oldSelected = model.isSelected();
133:
134: uninstallRolloverListener();
135: uninstallDefaults();
136: propertyPrefix = SUBMENU_PROPERTY_PREFIX;
137: installDefaults();
138:
139: //restore values of armed and selected properties
140: model.setArmed(oldArmed);
141: model.setSelected(oldSelected);
142: }
143:
144: // Rollover Listener ****************************************************
145:
146: protected void installListeners() {
147: super .installListeners();
148: mouseListener = new RolloverHandler();
149: menuItem.addMouseListener(mouseListener);
150: }
151:
152: protected void uninstallListeners() {
153: super .uninstallListeners();
154: uninstallRolloverListener();
155: }
156:
157: private void uninstallRolloverListener() {
158: if (mouseListener != null) {
159: menuItem.removeMouseListener(mouseListener);
160: mouseListener = null;
161: }
162: }
163:
164: // Helper Code **********************************************************
165:
166: private boolean isSubMenu(JMenuItem aMenuItem) {
167: return !((JMenu) aMenuItem).isTopLevelMenu();
168: }
169:
170: private static final class RolloverHandler extends MouseAdapter {
171:
172: public void mouseEntered(MouseEvent e) {
173: AbstractButton b = (AbstractButton) e.getSource();
174: b.getModel().setRollover(true);
175: }
176:
177: public void mouseExited(MouseEvent e) {
178: AbstractButton b = (AbstractButton) e.getSource();
179: b.getModel().setRollover(false);
180: }
181:
182: }
183:
184: }
|