javax.swing.plaf.basic.BasicArrowButton.java Source code

Java tutorial

Introduction

Here is the source code for javax.swing.plaf.basic.BasicArrowButton.java

Source

/*
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package javax.swing.plaf.basic;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;

import javax.swing.*;
import javax.swing.plaf.UIResource;
import sun.swing.SwingUtilities2;

/**
 * JButton object that draws a scaled Arrow in one of the cardinal directions.
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases. The current serialization support is
 * appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans&trade;
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @author David Kloba
 */
@SuppressWarnings("serial") // Same-version serialization only
public class BasicArrowButton extends JButton implements SwingConstants {
    /**
     * The direction of the arrow. One of
     * {@code SwingConstants.NORTH}, {@code SwingConstants.SOUTH},
     * {@code SwingConstants.EAST} or {@code SwingConstants.WEST}.
     */
    protected int direction;

    private Color shadow;
    private Color darkShadow;
    private Color highlight;

    /**
     * Creates a {@code BasicArrowButton} whose arrow
     * is drawn in the specified direction and with the specified
     * colors.
     *
     * @param direction the direction of the arrow; one of
     *        {@code SwingConstants.NORTH}, {@code SwingConstants.SOUTH},
     *        {@code SwingConstants.EAST} or {@code SwingConstants.WEST}
     * @param background the background color of the button
     * @param shadow the color of the shadow
     * @param darkShadow the color of the dark shadow
     * @param highlight the color of the highlight
     * @since 1.4
     */
    public BasicArrowButton(int direction, Color background, Color shadow, Color darkShadow, Color highlight) {
        super();
        setRequestFocusEnabled(false);
        setDirection(direction);
        setBackground(background);
        this.shadow = shadow;
        this.darkShadow = darkShadow;
        this.highlight = highlight;
    }

    /**
     * Creates a {@code BasicArrowButton} whose arrow
     * is drawn in the specified direction.
     *
     * @param direction the direction of the arrow; one of
     *        {@code SwingConstants.NORTH}, {@code SwingConstants.SOUTH},
     *        {@code SwingConstants.EAST} or {@code SwingConstants.WEST}
     */
    public BasicArrowButton(int direction) {
        this(direction, UIManager.getColor("control"), UIManager.getColor("controlShadow"),
                UIManager.getColor("controlDkShadow"), UIManager.getColor("controlLtHighlight"));
    }

    /**
     * Returns the direction of the arrow.
     *
     * @return the direction of the arrow
     */
    public int getDirection() {
        return direction;
    }

    /**
     * Sets the direction of the arrow.
     *
     * @param direction the direction of the arrow; one of
     *        of {@code SwingConstants.NORTH},
     *        {@code SwingConstants.SOUTH},
     *        {@code SwingConstants.EAST} or {@code SwingConstants.WEST}
     */
    public void setDirection(int direction) {
        this.direction = direction;
    }

    public void paint(Graphics g) {
        Color origColor;
        boolean isPressed, isEnabled;
        int w, h, size;

        w = getSize().width;
        h = getSize().height;
        origColor = g.getColor();
        isPressed = getModel().isPressed();
        isEnabled = isEnabled();

        g.setColor(getBackground());
        g.fillRect(1, 1, w - 2, h - 2);

        /// Draw the proper Border
        if (getBorder() != null && !(getBorder() instanceof UIResource)) {
            paintBorder(g);
        } else if (isPressed) {
            g.setColor(shadow);
            g.drawRect(0, 0, w - 1, h - 1);
        } else {
            // Using the background color set above
            g.drawLine(0, 0, 0, h - 1);
            g.drawLine(1, 0, w - 2, 0);

            g.setColor(highlight); // inner 3D border
            g.drawLine(1, 1, 1, h - 3);
            g.drawLine(2, 1, w - 3, 1);

            g.setColor(shadow); // inner 3D border
            g.drawLine(1, h - 2, w - 2, h - 2);
            g.drawLine(w - 2, 1, w - 2, h - 3);

            g.setColor(darkShadow); // black drop shadow  __|
            g.drawLine(0, h - 1, w - 1, h - 1);
            g.drawLine(w - 1, h - 1, w - 1, 0);
        }

        // If there's no room to draw arrow, bail
        if (h < 5 || w < 5) {
            g.setColor(origColor);
            return;
        }

        if (isPressed) {
            g.translate(1, 1);
        }

        // Draw the arrow
        size = Math.min((h - 4) / 3, (w - 4) / 3);
        size = Math.max(size, 2);
        paintTriangle(g, (w - size) / 2, (h - size) / 2, size, direction, isEnabled);

        // Reset the Graphics back to it's original settings
        if (isPressed) {
            g.translate(-1, -1);
        }
        g.setColor(origColor);

    }

    /**
     * Returns the preferred size of the {@code BasicArrowButton}.
     *
     * @return the preferred size
     */
    public Dimension getPreferredSize() {
        return new Dimension(16, 16);
    }

    /**
     * Returns the minimum size of the {@code BasicArrowButton}.
     *
     * @return the minimum size
     */
    public Dimension getMinimumSize() {
        return new Dimension(5, 5);
    }

    /**
     * Returns the maximum size of the {@code BasicArrowButton}.
     *
     * @return the maximum size
     */
    public Dimension getMaximumSize() {
        return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    /**
     * Returns whether the arrow button should get the focus.
     * {@code BasicArrowButton}s are used as a child component of
     * composite components such as {@code JScrollBar} and
     * {@code JComboBox}. Since the composite component typically gets the
     * focus, this method is overriden to return {@code false}.
     *
     * @return {@code false}
     */
    @SuppressWarnings("deprecation")
    public boolean isFocusTraversable() {
        return false;
    }

    /**
     * Paints a triangle.
     *
     * @param g the {@code Graphics} to draw to
     * @param x the x coordinate
     * @param y the y coordinate
     * @param size the size of the triangle to draw
     * @param direction the direction in which to draw the arrow;
     *        one of {@code SwingConstants.NORTH},
     *        {@code SwingConstants.SOUTH}, {@code SwingConstants.EAST} or
     *        {@code SwingConstants.WEST}
     * @param isEnabled whether or not the arrow is drawn enabled
     */
    public void paintTriangle(Graphics g, int x, int y, int size, int direction, boolean isEnabled) {
        if (SwingUtilities2.isScaledGraphics(g)) {
            paintScaledTriangle(g, x, y, size, direction, isEnabled);
        } else {
            paintUnscaledTriangle(g, x, y, size, direction, isEnabled);
        }
    }

    private void paintUnscaledTriangle(Graphics g, int x, int y, int size, int direction, boolean isEnabled) {
        Color oldColor = g.getColor();
        int mid, i, j;

        j = 0;
        size = Math.max(size, 2);
        mid = (size / 2) - 1;

        g.translate(x, y);
        if (isEnabled)
            g.setColor(darkShadow);
        else
            g.setColor(shadow);

        switch (direction) {
        case NORTH:
            for (i = 0; i < size; i++) {
                g.drawLine(mid - i, i, mid + i, i);
            }
            if (!isEnabled) {
                g.setColor(highlight);
                g.drawLine(mid - i + 2, i, mid + i, i);
            }
            break;
        case SOUTH:
            if (!isEnabled) {
                g.translate(1, 1);
                g.setColor(highlight);
                for (i = size - 1; i >= 0; i--) {
                    g.drawLine(mid - i, j, mid + i, j);
                    j++;
                }
                g.translate(-1, -1);
                g.setColor(shadow);
            }

            j = 0;
            for (i = size - 1; i >= 0; i--) {
                g.drawLine(mid - i, j, mid + i, j);
                j++;
            }
            break;
        case WEST:
            for (i = 0; i < size; i++) {
                g.drawLine(i, mid - i, i, mid + i);
            }
            if (!isEnabled) {
                g.setColor(highlight);
                g.drawLine(i, mid - i + 2, i, mid + i);
            }
            break;
        case EAST:
            if (!isEnabled) {
                g.translate(1, 1);
                g.setColor(highlight);
                for (i = size - 1; i >= 0; i--) {
                    g.drawLine(j, mid - i, j, mid + i);
                    j++;
                }
                g.translate(-1, -1);
                g.setColor(shadow);
            }

            j = 0;
            for (i = size - 1; i >= 0; i--) {
                g.drawLine(j, mid - i, j, mid + i);
                j++;
            }
            break;
        }
        g.translate(-x, -y);
        g.setColor(oldColor);
    }

    private void paintScaledTriangle(Graphics g, double x, double y, double size, int direction,
            boolean isEnabled) {
        size = Math.max(size, 2);
        Path2D.Double path = new Path2D.Double();
        path.moveTo(-size, size / 2);
        path.lineTo(size, size / 2);
        path.lineTo(0, -size / 2);
        path.closePath();
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.rotate(Math.PI * (direction - 1) / 4);
        path.transform(affineTransform);

        Graphics2D g2d = (Graphics2D) g;
        double tx = x + size / 2;
        double ty = y + size / 2;
        g2d.translate(tx, ty);
        Color oldColor = g.getColor();
        if (!isEnabled) {
            g2d.translate(1, 0);
            g2d.setColor(highlight);
            g2d.fill(path);
            g2d.translate(-1, 0);
        }
        g2d.setColor(isEnabled ? darkShadow : shadow);
        g2d.fill(path);
        g2d.translate(-tx, -ty);
        g2d.setColor(oldColor);
    }
}