import java.awt.*;

import java.util.*;

public class PaintAll
{

/** More capable version of Graphics.draw3DRect () method,
 * this allows line thickness other than one pixel,
 * and draws either inside or outside the stated boundaries.
 * @param g -- Graphics context for the draw operations.
 * @param BC -- Border Color, will be shifted brighter and darker.
 * @param x -- x coordinate of top left corner.
 * @param y -- y coordinate of top left corner.
 * @param width -- width of rectangle.
 * @param height -- height of rectangle.
 * @param Thickness -- Thickness  of rectangle.
 * @param Outside -- true for rectangle Outside stated boundaries.
 * @param Raised -- true for Raised rectangle.
 */

    public static void paint3DRect (Graphics g, Color BC, int x, int y, int width, int height, int Thickness, boolean Outside, boolean Raised) {

	if (Outside) {
	    x -= Thickness;
	    y -= Thickness;
	    width += (2*Thickness);
	    height += (2*Thickness);
	}

// Top and Left

        if (Raised)
            g.setColor (BC.brighter ());
	else
            g.setColor (BC.darker ());

        for(int ii=0; ii < Thickness; ++ii) {
            g.drawLine (x+ii, y+ii, x+width-ii, y+ii);
            g.drawLine (x+ii, y+ii, x+ii, y+height-ii);
        }
        
// Bottom and Right

	x--;
	y--;

	if (Raised)
            g.setColor (BC.darker ());
	else
            g.setColor (BC.brighter ());

        for(int ii=0; ii < Thickness; ++ii) {
	    g.drawLine (x+ii, y+height-ii, x+width-ii, y+height-ii);
	    g.drawLine (x+width-ii, y+ii, x+width-ii, y+height-ii);
        }
    }

/* Helper for doPaint */

    protected static void myBasicPaint (Graphics g, Component comp, boolean edge) {
        Dimension tb = comp.getSize ();

        if (null != comp.getFont ())
            g.setFont (comp.getFont ());

        Color BG = comp.getBackground ();
        if (null != BG) {
	    g.setColor (BG);
            g.fillRect (0, 0, tb.width, tb.height);
        }

        Color FG = comp.getForeground ();
        if (null != FG)
            g.setColor (FG);
        else
            g.setColor (Color.black);

        if (edge)
	    g.drawRect (0, 0, tb.width-1, tb.height-1);
    }

/** Avoid buggy printAll by doing it ourselves.
 * Instead of saying myTopComponent.printAll (Graphics g),
 * say PaintAll.doPaint (Graphics g, Component myTopComponent);
 * it is not beautiful but it does work. */

    public static void doPaint (Graphics g, Component aComp) {

        if (!aComp.isShowing ())
            return;

        Dimension tb = aComp.getSize ();

/** Our own Container expansion,
 * again to keep control for the peer-based children.
 * Recursively call doPaint () for each child,
 * each with a separate Graphics.
 *
 * Not sure if we are safe calling update for the Container,
 * any extension of Container that does some custom painting,
 * and then calls super.paint for painting the children,
 * will escape our control (as will the children)
 *
 * If not we can just use myBasicPaint instead.
 * This means we omit any custom painting by subclasses,
 * which is probably why they are a subclass,
 * so nice if we don't have to do that. */

        if (aComp instanceof Container) {

            //myBasicPaint (g, aComp, false);
	    aComp.update (g);

            Component [] children = ((Container)aComp).getComponents ();
            for (int kk = 0; kk < children.length; kk++) {
                if (children [kk].isShowing ()) {
                    Point cp = children [kk].location ();
                    Dimension ctb = children [kk].getSize ();
	            Graphics cg = g.create (cp.x, cp.y, ctb.width, ctb.height);
                    doPaint (cg, children [kk]);
                    cg.dispose ();
                }
            }
        }

/* Simulate the peer-based classes,
 * because they don't "really" paint to g,
 * they just use g to know what the peer should do,
 * so nothing would show up for them.
 * These are all pretty sloppy... */

        else if (aComp instanceof Label) {
            myBasicPaint (g, aComp, false);
            String s = ((Label)aComp).getText ();
            if (null != s)
                g.drawString (s, 2, tb.height/2);
        }

        else if (aComp instanceof Button) {
            myBasicPaint (g, aComp, true);
            String s = ((Button)aComp).getLabel ();
            if (null != s)
                g.drawString (s, 2, tb.height/2);
        }

        else if (aComp instanceof Checkbox) {
            myBasicPaint (g, aComp, false);
            if (((Checkbox)aComp).getState ())
                g.fillOval (2, tb.height/3,
                  tb.height/2, tb.height/2);
            else
                g.drawOval (2, tb.height/3,
                  tb.height/2, tb.height/2);
            String s = ((Checkbox)aComp).getLabel ();
            if (null != s)
                g.drawString (s, tb.height, tb.height/2);
        }

        else if (aComp instanceof Choice) {
            myBasicPaint (g, aComp, true);
            String s = ((Choice)aComp).getSelectedItem ();
            if (null != s)
                g.drawString (s, 2, tb.height/2);
        }

        else if (aComp instanceof TextField) {
            myBasicPaint (g, aComp, true);
            String s = ((TextField)aComp).getText ();
            if (null != s)
                g.drawString (s, 2, tb.height/2);
        }

        else if (aComp instanceof TextArea) {
            myBasicPaint (g, aComp, true);
            StringTokenizer spec = new StringTokenizer
              (((TextArea)aComp).getText (), "\n");

            for (int nn = 0;
              0 < spec.countTokens ();
              nn++)
                g.drawString (spec.nextToken (), 2, (1+nn) * 12);
        }

/* Here we should test else if (null != aComp.getPeer ())
 * and just do myBasicPaint (g, aComp, true) as better than nothing,
 * but "getPeer () is deprecated" so not doing this test... */

/* Don't know how so hope it does alright for itself.
 * Anything purely Java should be fine. */

        else
            aComp.update (g);
    }

/** Produce an HTML <TABLE> representing the widget tree.
 * Use try / catch to invoke each aComp.doWeb (PrintStream fos),
 * use our own recursion where it fails for a Container,
 * use toString where it fails for an individual.
 * Just a reminder for now... */

 //  public static void doWeb (PrintStream fos, Component aComp) { }
}
/* <IMG SRC="/cgi-bin/counter">*/
