Package com.alee.laf.button

Source Code of com.alee.laf.button.WebButtonUI

/*
* This file is part of WebLookAndFeel library.
*
* WebLookAndFeel library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* WebLookAndFeel library 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WebLookAndFeel library.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.alee.laf.button;

import com.alee.extended.painter.Painter;
import com.alee.extended.painter.PainterSupport;
import com.alee.extended.panel.WebButtonGroup;
import com.alee.global.StyleConstants;
import com.alee.laf.WebLookAndFeel;
import com.alee.utils.*;
import com.alee.utils.laf.ShapeProvider;
import com.alee.utils.ninepatch.NinePatchIcon;
import com.alee.utils.swing.AncestorAdapter;
import com.alee.utils.swing.BorderMethods;
import com.alee.utils.swing.WebTimer;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;

/**
* @author Mikle Garin
*/

public class WebButtonUI extends BasicButtonUI implements ShapeProvider, SwingConstants, BorderMethods
{
    /**
     * todo 1. Properly check situations when button sides are painted within multi-row/column WebButtonGroup
     * todo 2. Properly paint side-borders when grouped buttons are rollover decorated only
     */

    protected static final Stroke defaultInnerShade = new BasicStroke ( 3f );

    protected Color topBgColor = WebButtonStyle.topBgColor;
    protected Color bottomBgColor = WebButtonStyle.bottomBgColor;
    protected Color topSelectedBgColor = WebButtonStyle.topSelectedBgColor;
    protected Color bottomSelectedBgColor = WebButtonStyle.bottomSelectedBgColor;
    protected Color selectedForeground = WebButtonStyle.selectedForeground;
    protected boolean rolloverShine = WebButtonStyle.rolloverShine;
    protected Color shineColor = WebButtonStyle.shineColor;
    protected boolean rolloverDarkBorderOnly = WebButtonStyle.rolloverDarkBorderOnly;
    protected int round = WebButtonStyle.round;
    protected boolean drawShade = WebButtonStyle.drawShade;
    protected boolean rolloverShadeOnly = WebButtonStyle.rolloverShadeOnly;
    protected boolean showDisabledShade = WebButtonStyle.showDisabledShade;
    protected int shadeWidth = WebButtonStyle.shadeWidth;
    protected Insets margin = WebButtonStyle.margin;
    protected Color shadeColor = WebButtonStyle.shadeColor;
    protected int innerShadeWidth = WebButtonStyle.innerShadeWidth;
    protected Color innerShadeColor = WebButtonStyle.innerShadeColor;
    protected Color defaultButtonShadeColor = WebButtonStyle.defaultButtonShadeColor;
    protected int leftRightSpacing = WebButtonStyle.leftRightSpacing;
    protected boolean shadeToggleIcon = WebButtonStyle.shadeToggleIcon;
    protected float shadeToggleIconTransparency = WebButtonStyle.shadeToggleIconTransparency;
    protected boolean drawFocus = WebButtonStyle.drawFocus;
    protected boolean rolloverDecoratedOnly = WebButtonStyle.rolloverDecoratedOnly;
    protected boolean animate = WebButtonStyle.animate;
    protected boolean undecorated = WebButtonStyle.undecorated;
    protected Painter painter = WebButtonStyle.painter;
    protected boolean moveIconOnPress = WebButtonStyle.moveIconOnPress;

    protected boolean drawTop = true;
    protected boolean drawLeft = true;
    protected boolean drawBottom = true;
    protected boolean drawRight = true;

    protected boolean drawTopLine = false;
    protected boolean drawLeftLine = false;
    protected boolean drawBottomLine = false;
    protected boolean drawRightLine = false;

    protected Color transparentShineColor = new Color ( shineColor.getRed (), shineColor.getGreen (), shineColor.getBlue (), 0 );

    protected boolean rollover = false;
    protected float transparency = 0f;

    protected Point mousePoint = null;
    protected WebTimer animator = null;
    protected AbstractButton button = null;

    // Cached old values from button to restore on LAF change.
    protected boolean oldFocusPainted;
    protected boolean oldContentAreaFilled;
    protected boolean oldBorderPainted;
    protected boolean oldFocusable;

    protected MouseAdapter mouseAdapter;
    protected AncestorListener ancestorListener;
    protected PropertyChangeListener propertyChangeListener;

    @SuppressWarnings ( "UnusedParameters" )
    public static ComponentUI createUI ( final JComponent c )
    {
        return new WebButtonUI ();
    }

    @Override
    public void installUI ( final JComponent c )
    {
        super.installUI ( c );

        // Saving button to local variable
        button = ( AbstractButton ) c;

        // Saving old button settings
        oldFocusPainted = button.isFocusPainted ();
        oldContentAreaFilled = button.isContentAreaFilled ();
        oldBorderPainted = button.isBorderPainted ();
        oldFocusable = button.isFocusable ();

        // Default settings
        SwingUtils.setOrientation ( button );
        button.setFocusPainted ( false );
        button.setContentAreaFilled ( false );
        button.setBorderPainted ( false );
        button.setFocusable ( true );
        LookAndFeel.installProperty ( button, WebLookAndFeel.OPAQUE_PROPERTY, Boolean.FALSE );
        PainterSupport.installPainter ( button, this.painter );

        // Updating border
        updateBorder ();

        // Rollover listener
        mouseAdapter = new MouseAdapter ()
        {
            @Override
            public void mouseEntered ( final MouseEvent e )
            {
                rollover = true;
                button.getModel ().setRollover ( true );
                mousePoint = e.getPoint ();

                stopAnimator ();
                if ( painter == null &&
                        animate && ( rolloverShine || rolloverDecoratedOnly || rolloverShadeOnly ) )
                {
                    animator = new WebTimer ( "WebButtonUI.fadeInTimer", StyleConstants.fastAnimationDelay, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            transparency += 0.075f;
                            if ( transparency >= 1f )
                            {
                                transparency = 1f;
                                animator.stop ();
                            }
                            updateTransparentShineColor ();
                            if ( c.isEnabled () )
                            {
                                c.repaint ();
                            }
                        }
                    } );
                    animator.start ();
                }
                else
                {
                    transparency = 1f;
                    updateTransparentShineColor ();
                    c.repaint ();
                }

                refresh ( c );
            }

            @Override
            public void mouseExited ( final MouseEvent e )
            {
                mousePoint = e.getPoint ();

                stopAnimator ();
                if ( painter == null &&
                        animate && ( rolloverShine || rolloverDecoratedOnly || rolloverShadeOnly ) )
                {
                    animator = new WebTimer ( "WebButtonUI.fadeOutTimer", StyleConstants.fastAnimationDelay, new ActionListener ()
                    {
                        @Override
                        public void actionPerformed ( final ActionEvent e )
                        {
                            transparency -= 0.075f;
                            if ( transparency <= 0f )
                            {
                                rollover = false;
                                button.getModel ().setRollover ( false );
                                transparency = 0f;
                                mousePoint = null;
                                animator.stop ();
                            }
                            updateTransparentShineColor ();
                            if ( c.isEnabled () )
                            {
                                c.repaint ();
                            }
                        }
                    } );
                    animator.start ();
                }
                else
                {
                    rollover = false;
                    button.getModel ().setRollover ( false );
                    transparency = 0f;
                    mousePoint = null;
                    updateTransparentShineColor ();
                    c.repaint ();
                }

                refresh ( c );
            }

            @Override
            public void mouseReleased ( final MouseEvent e )
            {
                // Fix for highlight stuck
                if ( !c.isShowing () || windowLostFocus () )
                {
                    mousePoint = null;
                    c.repaint ();
                }
            }

            private boolean windowLostFocus ()
            {
                final Window wa = SwingUtils.getWindowAncestor ( c );
                return wa == null || !wa.isVisible () || !wa.isActive ();
            }

            private void stopAnimator ()
            {
                if ( animator != null )
                {
                    animator.stop ();
                }
            }

            @Override
            public void mouseDragged ( final MouseEvent e )
            {
                mousePoint = e.getPoint ();
                if ( painter == null && rolloverShine )
                {
                    refresh ( c );
                }
            }

            @Override
            public void mouseMoved ( final MouseEvent e )
            {
                mousePoint = e.getPoint ();
                if ( painter == null && rolloverShine )
                {
                    refresh ( c );
                }
            }

            private void refresh ( final JComponent c )
            {
                if ( c.isEnabled () )
                {
                    if ( animator == null || !animator.isRunning () )
                    {
                        c.repaint ();
                    }
                }
            }
        };
        c.addMouseListener ( mouseAdapter );
        c.addMouseMotionListener ( mouseAdapter );

        // Ancestor listener
        ancestorListener = new AncestorAdapter ()
        {
            @Override
            public void ancestorRemoved ( final AncestorEvent event )
            {
                rollover = false;
                button.getModel ().setRollover ( false );
                transparency = 0f;
                mousePoint = null;
                updateTransparentShineColor ();
                c.repaint ();
            }
        };
        c.addAncestorListener ( ancestorListener );

        // Orientation change listener
        propertyChangeListener = new PropertyChangeListener ()
        {
            @Override
            public void propertyChange ( final PropertyChangeEvent evt )
            {
                updateBorder ();
            }
        };
        c.addPropertyChangeListener ( WebLookAndFeel.ORIENTATION_PROPERTY, propertyChangeListener );
    }

    @Override
    public void uninstallUI ( final JComponent c )
    {
        PainterSupport.uninstallPainter ( button, this.painter );

        c.removeMouseListener ( mouseAdapter );
        c.removeMouseMotionListener ( mouseAdapter );
        c.removeAncestorListener ( ancestorListener );
        c.removePropertyChangeListener ( WebLookAndFeel.ORIENTATION_PROPERTY, propertyChangeListener );

        button.setBorderPainted ( oldBorderPainted );
        button.setContentAreaFilled ( oldContentAreaFilled );
        button.setFocusPainted ( oldFocusPainted );
        button.setFocusable ( oldFocusable );

        super.uninstallUI ( c );
    }

    @Override
    public Shape provideShape ()
    {
        if ( painter != null || undecorated )
        {
            return SwingUtils.size ( button );
        }
        else
        {
            return getButtonShape ( button, true );
        }
    }

    public Color getTopBgColor ()
    {
        return topBgColor;
    }

    public void setTopBgColor ( final Color topBgColor )
    {
        this.topBgColor = topBgColor;
    }

    public Color getBottomBgColor ()
    {
        return bottomBgColor;
    }

    public void setBottomBgColor ( final Color bottomBgColor )
    {
        this.bottomBgColor = bottomBgColor;
    }

    public Color getTopSelectedBgColor ()
    {
        return topSelectedBgColor;
    }

    public void setTopSelectedBgColor ( final Color topSelectedBgColor )
    {
        this.topSelectedBgColor = topSelectedBgColor;
    }

    public Color getBottomSelectedBgColor ()
    {
        return bottomSelectedBgColor;
    }

    public void setBottomSelectedBgColor ( final Color bottomSelectedBgColor )
    {
        this.bottomSelectedBgColor = bottomSelectedBgColor;
    }

    public Color getSelectedForeground ()
    {
        return selectedForeground;
    }

    public void setSelectedForeground ( final Color selectedForeground )
    {
        this.selectedForeground = selectedForeground;
    }

    public boolean isRolloverDarkBorderOnly ()
    {
        return rolloverDarkBorderOnly;
    }

    public void setRolloverDarkBorderOnly ( final boolean rolloverDarkBorderOnly )
    {
        this.rolloverDarkBorderOnly = rolloverDarkBorderOnly;
    }

    public boolean isRolloverShine ()
    {
        return rolloverShine;
    }

    public void setRolloverShine ( final boolean rolloverShine )
    {
        this.rolloverShine = rolloverShine;
    }

    public Color getShineColor ()
    {
        return shineColor;
    }

    public void setShineColor ( final Color shineColor )
    {
        this.shineColor = shineColor;
        updateTransparentShineColor ();
    }

    private void updateTransparentShineColor ()
    {
        transparentShineColor = new Color ( shineColor.getRed (), shineColor.getGreen (), shineColor.getBlue (),
                Math.round ( transparency * shineColor.getAlpha () ) );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void updateBorder ()
    {
        if ( button != null )
        {
            // Preserve old borders
            //            if ( SwingUtils.isPreserveBorders ( button ) )
            //            {
            //                return;
            //            }

            // Installing newly created border
            button.setBorder ( LafUtils.createWebBorder ( getBorderInsets () ) );
        }
    }

    /**
     * Returns component border insets used for WebLaF border.
     *
     * @return component border insets
     */
    protected Insets getBorderInsets ()
    {
        // Actual margin
        final boolean ltr = button.getComponentOrientation ().isLeftToRight ();
        final Insets m = new Insets ( margin.top, ( ltr ? margin.left : margin.right ) + leftRightSpacing, margin.bottom,
                ( ltr ? margin.right : margin.left ) + leftRightSpacing );

        // Applying border
        if ( painter != null )
        {
            // Painter borders
            final Insets pi = painter.getMargin ( button );
            m.top += pi.top;
            m.bottom += pi.bottom;
            m.left += ltr ? pi.left : pi.right;
            m.right += ltr ? pi.right : pi.left;
        }
        else if ( !undecorated )
        {
            // Styling borders
            final boolean actualDrawLeft = ltr ? drawLeft : drawRight;
            final boolean actualDrawLeftLine = ltr ? drawLeftLine : drawRightLine;
            final boolean actualDrawRight = ltr ? drawRight : drawLeft;
            final boolean actualDrawRightLine = ltr ? drawRightLine : drawLeftLine;
            m.top += ( drawTop ? ( shadeWidth + 1 ) : drawTopLine ? 1 : 0 ) + innerShadeWidth;
            m.left += ( actualDrawLeft ? ( shadeWidth + 1 ) : actualDrawLeftLine ? 1 : 0 ) + innerShadeWidth;
            m.bottom += ( drawBottom ? ( shadeWidth + 1 ) : drawBottomLine ? 1 : 0 ) + innerShadeWidth;
            m.right += ( actualDrawRight ? ( shadeWidth + 1 ) : actualDrawRightLine ? 1 : 0 ) + innerShadeWidth;
        }

        return m;
    }

    public boolean isDrawShade ()
    {
        return drawShade;
    }

    public void setDrawShade ( final boolean drawShade )
    {
        this.drawShade = drawShade;
    }

    public boolean isRolloverShadeOnly ()
    {
        return rolloverShadeOnly;
    }

    public void setRolloverShadeOnly ( final boolean rolloverShadeOnly )
    {
        this.rolloverShadeOnly = rolloverShadeOnly;
    }

    public boolean isShowDisabledShade ()
    {
        return showDisabledShade;
    }

    public void setShowDisabledShade ( final boolean showDisabledShade )
    {
        this.showDisabledShade = showDisabledShade;
    }

    public int getShadeWidth ()
    {
        return shadeWidth;
    }

    public void setShadeWidth ( final int shadeWidth )
    {
        this.shadeWidth = shadeWidth;
        updateBorder ();
    }

    public Insets getMargin ()
    {
        return margin;
    }

    public void setMargin ( final Insets margin )
    {
        this.margin = margin;
        updateBorder ();
    }

    public Color getShadeColor ()
    {
        return shadeColor;
    }

    public void setShadeColor ( final Color shadeColor )
    {
        this.shadeColor = shadeColor;
    }

    public int getInnerShadeWidth ()
    {
        return innerShadeWidth;
    }

    public void setInnerShadeWidth ( final int innerShadeWidth )
    {
        this.innerShadeWidth = innerShadeWidth;
        updateBorder ();
    }

    public Color getInnerShadeColor ()
    {
        return innerShadeColor;
    }

    public void setInnerShadeColor ( final Color innerShadeColor )
    {
        this.innerShadeColor = innerShadeColor;
    }

    public Color getDefaultButtonShadeColor ()
    {
        return defaultButtonShadeColor;
    }

    public void setDefaultButtonShadeColor ( final Color defaultButtonShadeColor )
    {
        this.defaultButtonShadeColor = defaultButtonShadeColor;
    }

    public int getLeftRightSpacing ()
    {
        return leftRightSpacing;
    }

    public void setLeftRightSpacing ( final int leftRightSpacing )
    {
        this.leftRightSpacing = leftRightSpacing;
        updateBorder ();
    }

    public int getRound ()
    {
        return round;
    }

    public void setRound ( final int round )
    {
        this.round = round;
    }

    public boolean isShadeToggleIcon ()
    {
        return shadeToggleIcon;
    }

    public void setShadeToggleIcon ( final boolean shadeToggleIcon )
    {
        this.shadeToggleIcon = shadeToggleIcon;
    }

    public float getShadeToggleIconTransparency ()
    {
        return shadeToggleIconTransparency;
    }

    public void setShadeToggleIconTransparency ( final float shadeToggleIconTransparency )
    {
        this.shadeToggleIconTransparency = shadeToggleIconTransparency;
    }

    public boolean isUndecorated ()
    {
        return undecorated;
    }

    public void setUndecorated ( final boolean undecorated )
    {
        this.undecorated = undecorated;
        updateBorder ();
    }

    public Painter getPainter ()
    {
        return painter;
    }

    public void setPainter ( final Painter painter )
    {
        PainterSupport.uninstallPainter ( button, this.painter );

        this.painter = painter;
        PainterSupport.installPainter ( button, this.painter );
        updateBorder ();
    }

    public boolean isMoveIconOnPress ()
    {
        return moveIconOnPress;
    }

    public void setMoveIconOnPress ( final boolean moveIconOnPress )
    {
        this.moveIconOnPress = moveIconOnPress;
    }

    public boolean isRolloverDecoratedOnly ()
    {
        return rolloverDecoratedOnly;
    }

    public void setRolloverDecoratedOnly ( final boolean rolloverDecoratedOnly )
    {
        this.rolloverDecoratedOnly = rolloverDecoratedOnly;
    }

    public boolean isAnimate ()
    {
        return animate;
    }

    public void setAnimate ( final boolean animate )
    {
        this.animate = animate;
    }

    public boolean isDrawFocus ()
    {
        return drawFocus;
    }

    public void setDrawFocus ( final boolean drawFocus )
    {
        this.drawFocus = drawFocus;
    }

    public boolean isDrawBottom ()
    {
        return drawBottom;
    }

    public void setDrawBottom ( final boolean drawBottom )
    {
        this.drawBottom = drawBottom;
        updateBorder ();
    }

    public boolean isDrawLeft ()
    {
        return drawLeft;
    }

    public void setDrawLeft ( final boolean drawLeft )
    {
        this.drawLeft = drawLeft;
        updateBorder ();
    }

    public boolean isDrawRight ()
    {
        return drawRight;
    }

    public void setDrawRight ( final boolean drawRight )
    {
        this.drawRight = drawRight;
        updateBorder ();
    }

    public boolean isDrawTop ()
    {
        return drawTop;
    }

    public void setDrawTop ( final boolean drawTop )
    {
        this.drawTop = drawTop;
        updateBorder ();
    }

    public void setDrawSides ( final boolean top, final boolean left, final boolean bottom, final boolean right )
    {
        this.drawTop = top;
        this.drawLeft = left;
        this.drawBottom = bottom;
        this.drawRight = right;
        updateBorder ();
    }

    public boolean isDrawTopLine ()
    {
        return drawTopLine;
    }

    public void setDrawTopLine ( final boolean drawTopLine )
    {
        this.drawTopLine = drawTopLine;
        updateBorder ();
    }

    public boolean isDrawLeftLine ()
    {
        return drawLeftLine;
    }

    public void setDrawLeftLine ( final boolean drawLeftLine )
    {
        this.drawLeftLine = drawLeftLine;
        updateBorder ();
    }

    public boolean isDrawBottomLine ()
    {
        return drawBottomLine;
    }

    public void setDrawBottomLine ( final boolean drawBottomLine )
    {
        this.drawBottomLine = drawBottomLine;
        updateBorder ();
    }

    public boolean isDrawRightLine ()
    {
        return drawRightLine;
    }

    public void setDrawRightLine ( final boolean drawRightLine )
    {
        this.drawRightLine = drawRightLine;
        updateBorder ();
    }

    public void setDrawLines ( final boolean top, final boolean left, final boolean bottom, final boolean right )
    {
        this.drawTopLine = top;
        this.drawLeftLine = left;
        this.drawBottomLine = bottom;
        this.drawRightLine = right;
        updateBorder ();
    }

    public boolean isRollover ()
    {
        return rollover;
    }

    @Override
    public void paint ( final Graphics g, final JComponent c )
    {
        final AbstractButton button = ( AbstractButton ) c;
        final ButtonModel buttonModel = button.getModel ();

        final Graphics2D g2d = ( Graphics2D ) g;
        final Object aa = GraphicsUtils.setupAntialias ( g2d );

        if ( painter != null || !undecorated )
        {
            if ( painter != null )
            {
                // Use background painter instead of default UI graphics
                painter.paint ( g2d, SwingUtils.size ( c ), c );
            }
            else if ( !undecorated )
            {
                final boolean pressed = buttonModel.isPressed () || buttonModel.isSelected ();
                final Shape borderShape = getButtonShape ( button, true );
                if ( isDrawButton ( c, buttonModel ) )
                {
                    // Rollover decorated only transparency
                    final boolean animatedTransparency = animate && rolloverDecoratedOnly && !pressed;
                    final Composite oldComposite = GraphicsUtils.setupAlphaComposite ( g2d, transparency, animatedTransparency );

                    // Shade
                    if ( drawShade && ( c.isEnabled () || isInButtonGroup ( button ) || showDisabledShade ) &&
                            ( !rolloverShadeOnly || rollover ) )
                    {
                        final boolean setInner = !animatedTransparency && rolloverShadeOnly;
                        final Composite oc = GraphicsUtils.setupAlphaComposite ( g2d, transparency, setInner );
                        if ( shadeWidth < 3 )
                        {
                            GraphicsUtils.drawShade ( g2d, borderShape, getShadeColor ( c ), shadeWidth );
                        }
                        else
                        {
                            // todo Properly paint shade color

                            final int w = button.getWidth ();
                            final int h = button.getHeight ();

                            // Changing line marks in case of RTL orientation
                            final boolean ltr = button.getComponentOrientation ().isLeftToRight ();
                            final boolean actualPaintLeft = ltr ? drawLeft : drawRight;
                            final boolean actualPaintRight = ltr ? drawRight : drawLeft;

                            // Retrieve shade 9-patch icon
                            final NinePatchIcon shade = NinePatchUtils.getShadeIcon ( shadeWidth, round * 2, transparency );

                            // Calculate shade bounds and paint it
                            final int x = actualPaintLeft ? 0 : -shadeWidth * 2;
                            final int width = w + ( actualPaintLeft ? 0 : shadeWidth * 2 ) + ( actualPaintRight ? 0 : shadeWidth * 2 );
                            final int y = drawTop ? 0 : -shadeWidth * 2;
                            final int height = h + ( drawTop ? 0 : shadeWidth * 2 ) + ( drawBottom ? 0 : shadeWidth * 2 );
                            shade.paintIcon ( g2d, x, y, width, height );
                        }
                        GraphicsUtils.restoreComposite ( g2d, oc, setInner );
                    }

                    // Background
                    g2d.setPaint ( new GradientPaint ( 0, drawTop ? shadeWidth : 0, getCurrentTopBgColor ( pressed ), 0,
                            button.getHeight () - ( drawBottom ? shadeWidth : 0 ), getCurrentBottomBgColor ( pressed ) ) );
                    g2d.fill ( getButtonShape ( button, false ) );

                    // Cursor-following highlight
                    if ( rolloverShine && mousePoint != null && c.isEnabled () )
                    {
                        final Shape oldClip = GraphicsUtils.intersectClip ( g2d, borderShape );
                        g2d.setPaint ( new RadialGradientPaint ( mousePoint.x, c.getHeight (), c.getWidth (), new float[]{ 0f, 1f },
                                new Color[]{ transparentShineColor, StyleConstants.transparent } ) );
                        g2d.fill ( borderShape );
                        GraphicsUtils.restoreClip ( g2d, oldClip );
                    }

                    // Inner shade
                    if ( pressed )
                    {
                        GraphicsUtils.drawShade ( g2d, borderShape, innerShadeColor, innerShadeWidth, borderShape );
                    }

                    // Default button inner shade
                    if ( isDefaultButton () )
                    {
                        final Shape oldClip = GraphicsUtils.setupClip ( g2d, borderShape );
                        final Stroke stroke = GraphicsUtils.setupStroke ( g2d, defaultInnerShade );
                        g2d.setPaint ( defaultButtonShadeColor );
                        g2d.draw ( borderShape );
                        GraphicsUtils.restoreStroke ( g2d, stroke );
                        GraphicsUtils.restoreClip ( g2d, oldClip );
                    }

                    // Border
                    g2d.setPaint ( c.isEnabled () ? rolloverDarkBorderOnly && rollover ? getBorderColor () :
                            !rolloverDarkBorderOnly ? StyleConstants.darkBorderColor : StyleConstants.borderColor :
                            StyleConstants.disabledBorderColor );
                    g2d.draw ( borderShape );

                    // Changing line marks in case of RTL orientation
                    final boolean ltr = button.getComponentOrientation ().isLeftToRight ();
                    final boolean actualDrawLeft = ltr ? drawLeft : drawRight;
                    final boolean actualDrawLeftLine = ltr ? drawLeftLine : drawRightLine;
                    final boolean actualDrawRight = ltr ? drawRight : drawLeft;
                    final boolean actualDrawRightLine = ltr ? drawRightLine : drawLeftLine;

                    // Side-border
                    if ( !drawTop && drawTopLine )
                    {
                        final int x = actualDrawLeft ? shadeWidth : 0;
                        g2d.setPaint ( c.isEnabled () || isAfterEnabledButton ( button ) ? StyleConstants.darkBorderColor :
                                StyleConstants.disabledBorderColor );
                        g2d.drawLine ( x, 0, x + c.getWidth () - ( actualDrawLeft ? shadeWidth : 0 ) -
                                ( actualDrawRight ? shadeWidth + 1 : 0 ), 0 );
                    }
                    if ( !actualDrawLeft && actualDrawLeftLine )
                    {
                        final int y = drawTop ? shadeWidth : 0;
                        g2d.setPaint ( c.isEnabled () || isAfterEnabledButton ( button ) ? StyleConstants.darkBorderColor :
                                StyleConstants.disabledBorderColor );
                        g2d.drawLine ( 0, y, 0, y + c.getHeight () - ( drawTop ? shadeWidth : 0 ) -
                                ( drawBottom ? shadeWidth + 1 : 0 ) );
                    }
                    if ( !drawBottom && drawBottomLine )
                    {
                        final int x = actualDrawLeft ? shadeWidth : 0;
                        g2d.setPaint ( c.isEnabled () || isBeforeEnabledButton ( button ) ? StyleConstants.darkBorderColor :
                                StyleConstants.disabledBorderColor );
                        g2d.drawLine ( x, c.getHeight () - 1, x + c.getWidth () - ( actualDrawLeft ? shadeWidth : 0 ) -
                                ( actualDrawRight ? shadeWidth + 1 : 0 ), c.getHeight () - 1 );
                    }
                    if ( !actualDrawRight && actualDrawRightLine )
                    {
                        final int y = drawTop ? shadeWidth : 0;
                        g2d.setPaint ( c.isEnabled () || isBeforeEnabledButton ( button ) ? StyleConstants.darkBorderColor :
                                StyleConstants.disabledBorderColor );
                        g2d.drawLine ( c.getWidth () - 1, y, c.getWidth () - 1, y + c.getHeight () - ( drawTop ? shadeWidth : 0 ) -
                                ( drawBottom ? shadeWidth + 1 : 0 ) );
                    }

                    GraphicsUtils.restoreComposite ( g2d, oldComposite, animatedTransparency );
                }
            }
        }

        // Special text and icon translation effect on button press
        if ( buttonModel.isPressed () && moveIconOnPress )
        {
            g2d.translate ( 1, 1 );
        }

        GraphicsUtils.restoreAntialias ( g2d, aa );

        // Default text and icon drawing
        final Map hints = SwingUtils.setupTextAntialias ( g2d );
        super.paint ( g, c );
        SwingUtils.restoreTextAntialias ( g2d, hints );
    }

    /**
     * Returns whether this button is default within its root pane or not.
     *
     * @return true if this button is default within its root pane, false otherwise
     */
    protected boolean isDefaultButton ()
    {
        return button instanceof JButton && ( ( JButton ) button ).isDefaultButton ();
    }

    /**
     * Returns current top background color.
     *
     * @param pressed whether button is pressed or not
     * @return current top background color
     */
    protected Color getCurrentTopBgColor ( final boolean pressed )
    {
        return pressed ? topSelectedBgColor : topBgColor;
    }

    /**
     * Returns current bottom background color.
     *
     * @param pressed whether button is pressed or not
     * @return current bottom background color
     */
    protected Color getCurrentBottomBgColor ( final boolean pressed )
    {
        return pressed ? bottomSelectedBgColor : bottomBgColor;
    }

    /**
     * Returns whether this button placed after another enabled button inside a WebButtonGroup container or not.
     * This check is required to paint button sides with proper colors.
     *
     * @param button this button
     * @return true if this button placed after another enabled button inside a WebButtonGroup container, false otherwise
     */
    protected boolean isAfterEnabledButton ( final AbstractButton button )
    {
        final Container container = button.getParent ();
        if ( container != null && container instanceof WebButtonGroup )
        {
            final int zOrder = container.getComponentZOrder ( button );
            if ( zOrder > 0 )
            {
                final WebButtonGroup group = ( WebButtonGroup ) container;
                final Component before = group.getComponent ( zOrder - 1 );
                if ( before instanceof WebButton )
                {
                    return before.isEnabled ();
                }
            }
        }
        return false;
    }

    /**
     * Returns whether this button placed before another enabled button inside a WebButtonGroup container or not.
     * This check is required to paint button sides with proper colors.
     *
     * @param button this button
     * @return true if this button placed before another enabled button inside a WebButtonGroup container, false otherwise
     */
    protected boolean isBeforeEnabledButton ( final AbstractButton button )
    {
        final Container container = button.getParent ();
        if ( container != null && container instanceof WebButtonGroup )
        {
            final int zOrder = container.getComponentZOrder ( button );
            if ( zOrder < container.getComponentCount () - 1 )
            {
                final WebButtonGroup group = ( WebButtonGroup ) container;
                final Component before = group.getComponent ( zOrder + 1 );
                if ( before instanceof WebButton )
                {
                    return before.isEnabled ();
                }
            }
        }
        return false;
    }

    /**
     * Returns whether this button is inside WebButtonGroup or not.
     *
     * @param button this button
     * @return true if this button is inside WebButtonGroup, false otherwise
     */
    protected boolean isInButtonGroup ( final AbstractButton button )
    {
        final Container container = button.getParent ();
        return container != null && container instanceof WebButtonGroup;
    }

    private Color getShadeColor ( final JComponent c )
    {
        return isFocusActive ( c ) ? StyleConstants.fieldFocusColor : shadeColor;
    }

    private boolean isFocusActive ( final JComponent c )
    {
        return c.isEnabled () && drawFocus && c.isFocusOwner ();
    }

    private boolean isDrawButton ( final JComponent c, final ButtonModel buttonModel )
    {
        return rolloverDecoratedOnly && rollover && c.isEnabled () ||
                animate && transparency > 0f && c.isEnabled () || !rolloverDecoratedOnly ||
                buttonModel.isSelected () || buttonModel.isPressed ();
    }

    @Override
    protected void paintText ( final Graphics g, final JComponent c, final Rectangle textRect, final String text )
    {
        final AbstractButton b = ( AbstractButton ) c;
        final ButtonModel model = b.getModel ();
        final FontMetrics fm = SwingUtils.getFontMetrics ( c, g );
        final int mnemonicIndex = b.getDisplayedMnemonicIndex ();

        // Drawing text
        if ( model.isEnabled () )
        {
            // Drawing normal text
            g.setColor ( model.isPressed () || model.isSelected () ? selectedForeground : b.getForeground () );
            SwingUtils.drawStringUnderlineCharAt ( g, text, mnemonicIndex, textRect.x + getTextShiftOffset (),
                    textRect.y + fm.getAscent () + getTextShiftOffset () );
        }
        else
        {
            // Drawing disabled text
            g.setColor ( b.getBackground ().brighter () );
            SwingUtils.drawStringUnderlineCharAt ( g, text, mnemonicIndex, textRect.x, textRect.y + fm.getAscent () );
            g.setColor ( b.getBackground ().darker () );
            SwingUtils.drawStringUnderlineCharAt ( g, text, mnemonicIndex, textRect.x - 1, textRect.y + fm.getAscent () - 1 );
        }
    }

    private Color getBorderColor ()
    {
        return ColorUtils.getIntermediateColor ( StyleConstants.borderColor, StyleConstants.darkBorderColor, transparency );
    }

    @Override
    protected void paintIcon ( final Graphics g, final JComponent c, final Rectangle iconRect )
    {
        final AbstractButton button = ( AbstractButton ) c;
        final ButtonModel buttonModel = button.getModel ();
        final Graphics2D g2d = ( Graphics2D ) g;

        final boolean shadeToggleIcon = this.shadeToggleIcon && button instanceof JToggleButton &&
                !buttonModel.isSelected ();
        final Composite old = GraphicsUtils.setupAlphaComposite ( g2d, shadeToggleIconTransparency, shadeToggleIcon );

        super.paintIcon ( g, c, iconRect );

        GraphicsUtils.restoreComposite ( g2d, old, shadeToggleIcon );
    }

    protected Shape getButtonShape ( final AbstractButton button, final boolean border )
    {
        // Changing line marks in case of RTL orientation
        final boolean ltr = button.getComponentOrientation ().isLeftToRight ();
        final boolean actualDrawLeft = ltr ? drawLeft : drawRight;
        final boolean actualDrawRight = ltr ? drawRight : drawLeft;

        // Determining border coordinates
        final int x = actualDrawLeft ? shadeWidth : -shadeWidth - round - 1;
        final int y = drawTop ? shadeWidth : -shadeWidth - round - 1;
        final int maxX = actualDrawRight ? button.getWidth () - shadeWidth - 1 : button.getWidth () + shadeWidth + round;
        final int maxY = drawBottom ? button.getHeight () - shadeWidth - 1 : button.getHeight () + shadeWidth + round;
        final int width = maxX - x;
        final int height = maxY - y;

        // Creating border shape
        if ( round > 0 )
        {
            return new RoundRectangle2D.Double ( x, y, width, height, round * 2 + ( border ? 0 : 1 ), round * 2 + ( border ? 0 : 1 ) );
        }
        else
        {
            return new Rectangle2D.Double ( x, y, width, height );
        }
    }

    @Override
    public Dimension getPreferredSize ( final JComponent c )
    {
        Dimension ps = super.getPreferredSize ( c );

        // Background painter preferred size
        if ( painter != null )
        {
            ps = SwingUtils.max ( ps, painter.getPreferredSize ( c ) );
        }

        return ps;
    }
}
TOP

Related Classes of com.alee.laf.button.WebButtonUI

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.