 /* Last change: Mon 15 Sep 1997 */
 /*--------------------------------------------------------------------------*
  *                                                         
  *
  *   cpick.java -- pick a color and display it
  *
  *   Author: Stephen Kalb
  *
  *   1996 Oct 29:  kalb      Original
  *            30:            mouse control
  *        Nov 06:            Change 'step' from 0x10 to 0x33
  *        Dec 11:            Choose colors by name
  *   1997 Sep 15:            Random color
  *   1999 Sep 09:            Start with light gray
  *   2000 Sep 29:            Increment colors by 0x11, not 0x33
  *
  *-------------------------------------------------------------------------*/

/*
(javac "cpick.java") ; To compile
*/

import java.awt.*;
import java.applet.*;
import java.util.*;


/*-----------------------------------------------------------------*/

public class cpick extends Applet
{
    final int firstVal  = 0x00; 
    final int lastVal   = 0xff;

    TextField mainText    = new TextField( "0", 10 );
    Choice    colorNames  = new Choice();
    Hashtable colorValues = new Hashtable();

    Rectangle mainRect  = null;
    Rectangle rRect     = null;
    Rectangle gRect     = null;
    Rectangle bRect     = null;

    Color     mainColor = new Color( 0xffffff );

    int       red       = 0xff; 
    int       green     = 0xff; 
    int       blue      = 0xff; 

    int       step      = 0x11;

    public void init( )
    {
        int gutter = 10;

        initNames();

        resize( 500, 500 );
        setLayout( null );

        rRect = new Rectangle( 50, 50, 50, 50 );
        gRect = toRightOf( rRect, gutter ); 
        bRect = toRightOf( gRect, gutter ); 

        mainRect = below( rRect, gutter );
        mainRect.width = mainRect.height = bRect.x + bRect.width - rRect.x ;

        Rectangle r = below( mainRect, gutter );

        r = addAt( mainText, r.x, r.y );
        r = below( r, gutter );
        
        addAt( colorNames, r.x, r.y );
    }
    
    public void paint( Graphics g )
    {
        // mainColor was some how changed: update squares:

        red   = mainColor.getRed();
        green = mainColor.getGreen();
        blue  = mainColor.getBlue();

        colorIn( g, rRect, new Color( red, 0, 0 ));
        colorIn( g, gRect, new Color( 0, green, 0 ));
        colorIn( g, bRect, new Color( 0, 0, blue ));

        colorIn( g, mainRect, mainColor );

        mainText.setText( 
            Integer.toHexString( mainColor.getRGB()).substring( 2 ));
    }
    
    public void colorIn( Graphics g, Rectangle r, Color c )
    {
        g.setColor( c );
        g.fillRect( r.x, r.y, r.width, r.height );
    }
    
    public boolean keyUp( Event e, int c )
    {
        if( e.target == mainText && ( c == '\n' || c == '\r' ))
        {
            try
            {
                mainColor = 
                    new Color( Integer.parseInt( mainText.getText(), 0x10 ));
            }
            catch( NumberFormatException ex )
            {
                showStatus( "Enter hex number, up to 6 digits." );
            }
            
            repaint();
            return( true );
        }

        return( false );
    }

    public boolean mouseDown( Event e, int x, int y )
    {
        boolean changed = false;
        int amount = e.shiftDown() ? -step : step;

        if( rRect.inside( x, y ))
        {
            red = wrapAdd( red, amount );
            changed = true;
        }
        else if( gRect.inside( x, y ))
        {
            green = wrapAdd( green, amount );
            changed = true;
        }
        else if( bRect.inside( x, y ))
        {
            blue = wrapAdd( blue, amount );
            changed = true;
        }

        if( changed )
        {
            mainColor = new Color( red, green, blue );
            repaint();
            return( true );
        }

        return( false );
    }

    public boolean action( Event e, Object arg )
    {
        if( e.target == colorNames )
        {
            String name = colorNames.getSelectedItem();

            if( name.equals( "hazarda" ))
            {
                mainColor = randomColor();
            }
            else
            {
                mainColor = ( Color )colorValues.get( name );
            }
            
            repaint();
            return( true );
        }

        return( false );
    }
    
    private void initNames()
    {
        String first = "helgriza";

        addName( "rugxa",       Color.red    );
        addName( "orangxa",     Color.orange );
        addName( "flava",       Color.yellow );
        addName( "verda",       Color.green  );
        addName( "helblua",     Color.cyan   );
        addName( "blua",        Color.blue   );
        addName( "fuksina",     Color.magenta );
        addName( "roza",        Color.pink   );

        addName( "nigra",       Color.black  );
        addName( "malhelgriza", Color.darkGray );
        addName( "griza",       Color.gray   );
        addName( "helgriza",    Color.lightGray );
        addName( "blanka",      Color.white  );
        addName( "hazarda",     Color.white  );

        colorNames.select( first );
        mainColor = ( Color )colorValues.get( first );
    }

    /** Return a random color
     */

    private final int MAXRGB = 0xffffff;

    public Color randomColor()
    {
        Random rand = new Random();
        int rgb     = rand.nextInt() % MAXRGB;

        return( new Color( rgb )); 
    }

    public String addName( String name, Color value )
    {
        colorNames.addItem( name );
        colorValues.put( name, value );

        return( name );
    }
    

    private Rectangle addAt( Component c, int x, int y )
    {
        /*   Position Component c at position x,y, using its
         *   preferred size.     
         *
         *   Returns: the resulting Rectangle
         */

        add( c );
        Dimension d = c.preferredSize(); 
        c.reshape( x, y, d.width, d.height );

        return( new Rectangle( x, y, d.width,  d.height ));
    }


    private Rectangle toRightOf( Rectangle r, int gutter )
    {
        return( new Rectangle( 
            r.x + r.width + gutter, 
            r.y, 
            r.width, 
            r.height ));
    }
    
    private Rectangle below( Rectangle r, int gutter )
    {
        return( new Rectangle( 
            r.x, 
            r.y + r.height + gutter, 
            r.width, 
            r.height ));
    }

    private int wrapAdd( int num, int amount )
    {
        int n = num + amount;
        
        if( n > lastVal )
        {
            n = firstVal;
        }
        else if( n < firstVal )
        {
            n = lastVal;
        }

        return( n );
    }
}

/*-----------------------------------------------------------------*/
/*                                  ~stavros/11.476 A 37  21:14:25 */
