/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. * * Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common * Development and Distribution License("CDDL") (collectively, the * "License"). You may not use this file except in compliance with the * License. You can obtain a copy of the License at * http://www.netbeans.org/cddl-gplv2.html * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the * specific language governing permissions and limitations under the * License. When distributing the software, include this License Header * Notice in each file and include the License file at * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the GPL Version 2 section of the License file that * accompanied this code. If applicable, add the following below the * License Header, with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Contributor(s): * * The Original Software is NetBeans. The Initial Developer of the Original * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun * Microsystems, Inc. All Rights Reserved. * * If you wish your version of this file to be governed by only the CDDL * or only the GPL Version 2, indicate your decision by adding * "[Contributor] elects to include this software in this distribution * under the [CDDL or GPL Version 2] license." If you do not indicate a * single choice of license, a recipient has the option to distribute * your version of this file under either the CDDL, the GPL Version 2 or * to extend the choice of license to its licensees as provided above. * However, if you add GPL Version 2 code and therefore, elected the GPL * Version 2 license, then the option applies only if the new code is * made subject to such option by the copyright holder. */ package org.openide.awt; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.DefaultButtonModel; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JPopupMenu; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; /** * JButton with a small arrow that displays popup menu when clicked. * * @author S. Aubrecht * @since 6.11 */ class DropDownButton extends JButton { private boolean mouseInButton = false; private boolean mouseInArrowArea = false; private Map<String,Icon> regIcons = new HashMap<String,Icon>( 5 ); private Map<String,Icon> arrowIcons = new HashMap<String,Icon>( 5 ); private static final String ICON_NORMAL = "normal"; //NOI18N private static final String ICON_PRESSED = "pressed"; //NOI18N private static final String ICON_ROLLOVER = "rollover"; //NOI18N private static final String ICON_ROLLOVER_SELECTED = "rolloverSelected"; //NOI18N private static final String ICON_SELECTED = "selected"; //NOI18N private static final String ICON_DISABLED = "disabled"; //NOI18N private static final String ICON_DISABLED_SELECTED = "disabledSelected"; //NOI18N private static final String ICON_ROLLOVER_LINE = "rolloverLine"; //NOI18N private static final String ICON_ROLLOVER_SELECTED_LINE = "rolloverSelectedLine"; //NOI18N private PopupMenuListener menuListener; /** Creates a new instance of MenuToggleButton */ public DropDownButton( Icon icon, JPopupMenu popup ) { assert null != icon; putClientProperty( DropDownButtonFactory.PROP_DROP_DOWN_MENU, popup ); setIcon( icon ); //<modified for OJ> setDisabledIcon(ImageUtilities.createDisabledIcon(icon)); resetIcons(); addPropertyChangeListener( DropDownButtonFactory.PROP_DROP_DOWN_MENU,new PropertyChangeListener() { public void propertyChange( PropertyChangeEvent e ) { resetIcons(); } }); addMouseMotionListener( new MouseMotionAdapter() { @Override public void mouseMoved( MouseEvent e ) { if( null != getPopupMenu() ) { mouseInArrowArea = isInArrowArea( e.getPoint() ); updateRollover( _getRolloverIcon(), _getRolloverSelectedIcon() ); } } }); addMouseListener( new MouseAdapter() { private boolean popupMenuOperation = false; @Override public void mousePressed( MouseEvent e ) { popupMenuOperation = false; JPopupMenu menu = getPopupMenu(); if ( menu != null && getModel() instanceof Model ) { Model model = (Model) getModel(); if ( !model._isPressed() ) { if( isInArrowArea( e.getPoint() ) && menu.getComponentCount() > 0 ) { model._press(); menu.addPopupMenuListener( getMenuListener() ); menu.show( DropDownButton.this, 0, getHeight() ); popupMenuOperation = true; } } else { model._release(); menu.removePopupMenuListener( getMenuListener() ); popupMenuOperation = true; } } } @Override public void mouseReleased(MouseEvent e) { // If we done something with the popup menu, we should consume // the event, otherwise the button's action will be triggered. if (popupMenuOperation) { popupMenuOperation = false; e.consume(); } } @Override public void mouseEntered( MouseEvent e ) { mouseInButton = true; if( hasPopupMenu() ) { mouseInArrowArea = isInArrowArea( e.getPoint() ); updateRollover( _getRolloverIcon(), _getRolloverSelectedIcon() ); } } @Override public void mouseExited( MouseEvent e ) { mouseInButton = false; mouseInArrowArea = false; if( hasPopupMenu() ) { updateRollover( _getRolloverIcon(), _getRolloverSelectedIcon() ); } } }); setModel( new Model() ); } private PopupMenuListener getMenuListener() { if( null == menuListener ) { menuListener = new PopupMenuListener() { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { // If inside the button let the button's mouse listener // deal with the state. The popup menu will be hidden and // we should not show it again. if( getModel() instanceof Model ) { ((Model)getModel())._release(); } JPopupMenu menu = getPopupMenu(); if( null != menu ) { menu.removePopupMenuListener( this ); } } public void popupMenuCanceled(PopupMenuEvent e) { } }; } return menuListener; } private void updateRollover( Icon rollover, Icon rolloverSelected ) { super.setRolloverIcon( rollover ); super.setRolloverSelectedIcon( rolloverSelected ); } private void resetIcons() { Icon icon = regIcons.get( ICON_NORMAL ); if( null != icon ) setIcon( icon ); icon = regIcons.get( ICON_PRESSED ); if( null != icon ) setPressedIcon( icon ); icon = regIcons.get( ICON_ROLLOVER ); if( null != icon ) setRolloverIcon( icon ); icon = regIcons.get( ICON_ROLLOVER_SELECTED ); if( null != icon ) setRolloverSelectedIcon( icon ); icon = regIcons.get( ICON_SELECTED ); if( null != icon ) setSelectedIcon( icon ); icon = regIcons.get( ICON_DISABLED ); if( null != icon ) setDisabledIcon( icon ); icon = regIcons.get( ICON_DISABLED_SELECTED ); if( null != icon ) setDisabledSelectedIcon( icon ); } private Icon _getRolloverIcon() { Icon icon = null; icon = arrowIcons.get( mouseInArrowArea ? ICON_ROLLOVER : ICON_ROLLOVER_LINE ); if( null == icon ) { Icon orig = regIcons.get( ICON_ROLLOVER ); if( null == orig ) orig = regIcons.get( ICON_NORMAL ); icon = new IconWithArrow( orig, !mouseInArrowArea ); arrowIcons.put( mouseInArrowArea ? ICON_ROLLOVER : ICON_ROLLOVER_LINE, icon ); } return icon; } private Icon _getRolloverSelectedIcon() { Icon icon = null; icon = arrowIcons.get( mouseInArrowArea ? ICON_ROLLOVER_SELECTED : ICON_ROLLOVER_SELECTED_LINE ); if( null == icon ) { Icon orig = regIcons.get( ICON_ROLLOVER_SELECTED ); if( null == orig ) orig = regIcons.get( ICON_ROLLOVER ); if( null == orig ) orig = regIcons.get( ICON_NORMAL ); icon = new IconWithArrow( orig, !mouseInArrowArea ); arrowIcons.put( mouseInArrowArea ? ICON_ROLLOVER_SELECTED : ICON_ROLLOVER_SELECTED_LINE, icon ); } return icon; } JPopupMenu getPopupMenu() { Object menu = getClientProperty( DropDownButtonFactory.PROP_DROP_DOWN_MENU ); if( menu instanceof JPopupMenu ) { return (JPopupMenu)menu; } return null; } boolean hasPopupMenu() { return null != getPopupMenu(); } private boolean isInArrowArea( Point p ) { return p.getLocation().x >= getWidth() - IconWithArrow.getArrowAreaWidth() - getInsets().right; } @Override public void setIcon(Icon icon) { assert null != icon; Icon arrow = updateIcons( icon, ICON_NORMAL ); arrowIcons.remove( ICON_ROLLOVER_LINE ); arrowIcons.remove( ICON_ROLLOVER_SELECTED_LINE ); arrowIcons.remove( ICON_ROLLOVER ); arrowIcons.remove( ICON_ROLLOVER_SELECTED ); super.setIcon( hasPopupMenu() ? arrow : icon ); } private Icon updateIcons( Icon orig, String iconType ) { Icon arrow = null; if( null == orig ) { regIcons.remove( iconType ); arrowIcons.remove( iconType ); } else { regIcons.put( iconType, orig ); //<modified for OJ> arrow = new ImageIcon(ImageUtilities.icon2Image(new IconWithArrow( orig, false ))); arrow = new IconWithArrow( orig, false ); arrowIcons.put( iconType, arrow ); } return arrow; } @Override public void setPressedIcon(Icon icon) { Icon arrow = updateIcons( icon, ICON_PRESSED ); super.setPressedIcon( hasPopupMenu() ? arrow : icon ); } @Override public void setSelectedIcon(Icon icon) { Icon arrow = updateIcons( icon, ICON_SELECTED ); super.setSelectedIcon( hasPopupMenu() ? arrow : icon ); } @Override public void setRolloverIcon(Icon icon) { Icon arrow = updateIcons( icon, ICON_ROLLOVER ); arrowIcons.remove( ICON_ROLLOVER_LINE ); arrowIcons.remove( ICON_ROLLOVER_SELECTED_LINE ); super.setRolloverIcon( hasPopupMenu() ? arrow : icon ); } @Override public void setRolloverSelectedIcon(Icon icon) { Icon arrow = updateIcons( icon, ICON_ROLLOVER_SELECTED ); arrowIcons.remove( ICON_ROLLOVER_SELECTED_LINE ); super.setRolloverSelectedIcon( hasPopupMenu() ? arrow : icon ); } @Override public void setDisabledIcon(Icon icon) { //TODO use 'disabled' arrow icon Icon arrow = updateIcons( icon, ICON_DISABLED ); super.setDisabledIcon( hasPopupMenu() ? arrow : icon ); } @Override public void setDisabledSelectedIcon(Icon icon) { //TODO use 'disabled' arrow icon Icon arrow = updateIcons( icon, ICON_DISABLED_SELECTED ); super.setDisabledSelectedIcon( hasPopupMenu() ? arrow : icon ); } @Override public void setText( String text ) { //does nothing Logger.getLogger(DropDownToggleButton.class.getName()).log(Level.FINER, "DropDownButton cannot display text."); //NOI18N } @Override public String getText() { return null; } private class Model extends DefaultButtonModel { private boolean _pressed = false; @Override public void setPressed(boolean b) { if( mouseInArrowArea || _pressed ) return; super.setPressed( b ); } public void _press() { if((isPressed()) || !isEnabled()) { return; } stateMask |= PRESSED + ARMED; fireStateChanged(); _pressed = true; } public void _release() { _pressed = false; mouseInArrowArea = false; setArmed( false ); setPressed( false ); setRollover( false ); setSelected( false ); } public boolean _isPressed() { return _pressed; } @Override protected void fireStateChanged() { if( _pressed ) return; super.fireStateChanged(); } @Override public void setArmed(boolean b) { if( _pressed ) return; super.setArmed(b); } @Override public void setEnabled(boolean b) { if( _pressed ) return; super.setEnabled(b); } @Override public void setSelected(boolean b) { if( _pressed ) return; super.setSelected(b); } @Override public void setRollover(boolean b) { if( _pressed ) return; super.setRollover(b); } } }