Package org.gephi.ui.components

Source Code of org.gephi.ui.components.JDropDownToggleButton$Model

/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org

This file is part of Gephi.

Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.ui.components;

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 javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import org.openide.util.ImageUtilities;

/**
*
* @author Mathieu Bastian
*/
public class JDropDownToggleButton extends JToggleButton {

    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
    /**
     * Use this property name to assign or remove popup menu to/from buttons created by this factory,
     * e.g. <code>dropDownButton.putClientProperty( PROP_DROP_DOWN_MENU, new JPopupMenu() )</code>
     * The property value must be <code>JPopupMenu</code>, removing this property removes the arrow from the button.
     */
    public static final String PROP_DROP_DOWN_MENU = "dropDownMenu";
    private PopupMenuListener menuListener;

    /** Creates a new instance of DropDownToggleButton */
    public JDropDownToggleButton(Icon icon, JPopupMenu popup) {
        assert null != icon;

        putClientProperty(PROP_DROP_DOWN_MENU, popup);

        setIcon(icon);

        resetIcons();

        addPropertyChangeListener(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(JDropDownToggleButton.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 (!mouseInButton) {
                        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(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);
            arrow = new ImageIcon(ImageUtilities.icon2Image(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);
    }

    private class Model extends JToggleButton.ToggleButtonModel {

        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);
        }
    }

    /**
     * Creates JToggleButton with a small arrow that shows the provided popup menu when clicked.
     *
     * @param icon The default icon, cannot be null
     * @param dropDownMenu Popup menu to display when the arrow is clicked. If this parameter is null
     * then the button doesn't show any arrow and behaves like a regular JToggleButton. It is possible to add
     * the popup menu later using PROP_DROP_DOWN_MENU client property.
     * @return A toggle-button that is capable of displaying an 'arrow' in its icon to open a popup menu.
     */
    public static JToggleButton createDropDownToggleButton(Icon icon, JPopupMenu dropDownMenu) {
        return new JDropDownToggleButton(icon, dropDownMenu);
    }
}
TOP

Related Classes of org.gephi.ui.components.JDropDownToggleButton$Model

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.