Brought to you by EarthWeb
ITKnowledge Logo Login Graphic Click Here!
Click Here!
ITKnowledge
Find:
 
EXPERT SEARCH ----- nav

EarthWeb Direct

EarthWeb Direct

EarthWeb sites: other sites

Previous Table of Contents Next


Listing 5.3 The ChaserLightsBorder Class

package com.foley.borders;

import java.awt.Insets;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Color;

import javax.swing.JComponent;

import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

/**
 * ChaserLightsBorder is a concrete AnimatedBorder.  It
 * paints the border as a chase light.
 *
 * @see AnimatedBorder
 * @see Border
 * @author Mike Foley
 **/
public class ChaserLightsBorder extends AnimatedBorder {

    /**
     * The index of the next ‘light’ to be out
     * when drawing the border.
     **/
    private int currentLightIndex = 0;

    /**
     * The number of ‘lights’ to be on in a row
     **/
    private int onLightCount = 5;

    /**
     * The first off light index for this cycle.
     **/
    private int firstOffLightIndex = 0;

    /**
     * The color to draw on ‘lights’
     **/
    private Color onLightColor = Color.yellow;

    /**
     * The color to draw off ‘lights’
     **/
    private Color offLightColor = Color.white;

    /**
     * The direction of light travel.  True = forward.
     **/
    private boolean direction = true;

    /**
     * Bound property names.
     **/
    public static final String DIRECTION_PROPERTY = “DirectionProperty”;
public static final String ONLIGHTCOLOR_PROPERTY =
                                                “OnLightColorProperty”;
    public static final String OFFLIGHTCOLOR_PROPERTY =
                                                “OffLightColorProperty”;
    /**
     * Constructor.
     * Create insets from the raw parameter and call our
     * constructor taking Insets to do the work.
     *
     * @param c The component we border.
     * @param top The top border width.
     * @param left The left border width.
     * @param bottom The bottom border width.
     * @param right The right border width.
     **/
    public ChaserLightsBorder( JComponent c, int top, int left,
                           int bottom, int right ) {
        this( c, new Insets( top, left, bottom, right ) );
    }

    /**
     * Constructor.
     * Call our super.  We don’t do any additional processing.
     *
     * @param c The component we border.
     * @param insets The border size.
     **/
    public ChaserLightsBorder( JComponent c, Insets insets ) {
        super( c, insets );
    }

    /**
     * Set the on light count of the chaser lights.
     * This value is one greater than the number of lights
     * on before the off light.  A value of two will give
     * every other light being off.  A value of one will give
     * all lights on, not very good.
     *
     * This is a bound property.
     *
     * @param onLightCount The new on light count.
     **/
    public void setOnLightCount( int onLightCount ) {

        if( onLightCount < 1 )
throw new IllegalArgumentException(
                      “Negative or zero onLightCount given” );

        Integer old = new Integer( this.onLightCount );
        this.onLightCount = onLightCount;

        changes.firePropertyChange( ONLIGHTCOUNT_PROPERTY,
                            old, new Integer( this.onLightCount ) );
    } // setOnLightCount

    /**
* @return The number of lights - 1 in a row between the off light.
     **/
    public int getOnLightCount() {
        return( this.onLightCount );
    }

    /**
     * Set the direction of the chaser lights.  True means
     * forward.
     * This is a bound property.
     *
     * @param direction The new direction of the chaser lights.
     **/
    public void setDirection( boolean direction ) {

        Boolean old = new Boolean( this.direction );
        this.direction = direction;

        changes.firePropertyChange( DIRECTION_PROPERTY,
                            old, new Boolean( this.direction ) );
    } // setDirection

    /**
     * @return The direction the chaser lights are going.
     **/
    public boolean getDirection() {
        return( this.direction );
    }

    /**
     * Set the color for ‘on’ lights.
     * This is a bound property.
     *
     * @param onLightColor The new color for ‘on’ lights.
     **/
    public void setOnLightColor( Color onLightColor ) {

        Color old = this.onLightColor;
        this.onLightColor = onLightColor;

        changes.firePropertyChange( ONLIGHTCOLOR_PROPERTY,
                            old, this.onLightColor );

    } // setOnLightColor

    /**
     * @return The color for ‘on’ lights.
     **/
    public Color getOnLightColor() {
        return( this.onLightColor );
    }

    /**
     * Set the color for ‘off’ lights.
     * This is a bound property.
     *
     * @param offLightColor The new color for ‘off’ lights.
     **/
    public void setOffLightColor( Color offLightColor ) {

        Color old = this.offLightColor;
        this.offLightColor = offLightColor;

        changes.firePropertyChange( OFFLIGHTCOLOR_PROPERTY,
                            old, this.offLightColor );

    } // setOffLightColor

    /**
     * @return The color for ‘off’ lights.
     **/
    public Color getOffLightColor() {
        return( this.offLightColor );
    }

    /**
     * Paint the border.
     * Get the color at the current color index.  Then update the index.
     * The index is wrapped, so that the array of colors repeat every
     * length of the array.
     *
     * @param c The bordered component.
     * @param g The graphics to paint with.
     * @param x The X location of the bordered component.
     * @param y The Y location of the bordered component.
     * @param width The width of the bordered component.
     * @param height The height of the bordered component.
     **/
    public void paintBorder( Component c, Graphics g, int x,
                             int y, int width, int height ) {

        //
        // Save the current color so we can restore at end of method.
        //
        Color oldColor = g.getColor();

        g.translate( x, y );

        //
        // Get our size.
        //
        Insets insets = getBorderInsets( c );

        //
        // Paint the border.
        // Set the current light index.  Start at 0.
        //
        currentLightIndex = 0;

        //
        // Top
        int xpos = 0;
        int ypos = 0;
        if( 0 < insets.top ) {
            do {
                setGraphicsColor( g );
                g.fillOval( xpos, ypos, insets.top, insets.top );
                xpos += insets.top + 1;
            } while( xpos < width );
        }

        //
        // Right
        xpos = width - insets.right;
        ypos = insets.top;
        if( 0 < insets.right ) {
            do {
                setGraphicsColor( g );
                g.fillOval( xpos, ypos, insets.right, insets.right );
                ypos += insets.right + 1;
            } while( ypos < height - 2 * insets.bottom );
        }

        //
        // Bottom
        xpos = width - insets.right;
        ypos = height - insets.bottom;
        if( 0 < insets.bottom ) {
            do {
                setGraphicsColor( g );
                g.fillOval( xpos, ypos, insets.bottom, insets.bottom );
                xpos -= insets.bottom + 1;
            } while( 0 < xpos );
        }

        //
        // Left
        xpos = 0;
        ypos = height - 2 * insets.bottom;
        if( 0 < insets.left ) {
            do {
                setGraphicsColor( g );
                g.fillOval( xpos, ypos, insets.left, insets.left );
                ypos -= insets.left + 1;
            } while( 0 < ypos - insets.top );
        }

        //
        // Update the light off index.  If going forward, increment
        // else decrement.  Wrap the index as required.
        //
        if( direction ) {
            firstOffLightIndex += 1;
            firstOffLightIndex %= onLightCount;
        } else {
            firstOffLightIndex -= 1;
            if( firstOffLightIndex < 0 )
                firstOffLightIndex = onLightCount - 1;
        }

        //
        // Restore the Graphics object’s state.
        //
        g.translate( -x, -y );
        g.setColor( oldColor );

    } // paintBorder

    /**
     * Set the color to draw the next light with.
     * We update the currentLight Index.  This index
     * must be reset each cycle.
     *
     * @param g The graphics used to paint.
     **/
    private void setGraphicsColor( Graphics g ) {

        if( currentLightIndex % onLightCount == firstOffLightIndex ) {
            g.setColor( offLightColor );
        } else {
            g.setColor( onLightColor );
        }

        //
        // Update the currentLightIndex, wrap if required
        //
        currentLightIndex += 1;

    }

} // ChaserLightsBorder

Very interesting visual effects can be created by using animated borders. However, creating a thread for each border makes the cost of these borders rather high. If multiple animated borders are to be used in an application or applet, a single thread should be used to control the animation in all of the animated borders.


Previous Table of Contents Next
HomeAbout UsSearchSubscribeAdvertising InfoContact UsFAQs
Use of this site is subject to certain Terms & Conditions.
Copyright (c) 1996-1999 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.