/*
 * Filename: OOPDraw2.java
 * Written By: Sunit Katkar
 * E-Mail:sunitkatkar@hotmail.com
 * Home-Page : http://www.vidyut.com/sunit
 * Java Page : www.vidyut.com/sunit/JavaPage.html
 ******************************************************************
 * Description:
 * A very simple vector drawing example. I have used the OO concept
 * of Polymorphism to declare on abstract Shape class and then derived 
 * line, rectangle and oval shape classes. The shapes are stored in a
 * Vector so that they remain on screen as new shapes are drawn.
 * An offscreen image technique is used to avoid flicker.
****************************************************************

 * Copyright (c) 1997 Sunit Katkar All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * for NON-COMMERCIAL or COMMERCIAL purposes and without fee
 * is hereby granted.
 *
 * Whew ! That was too much legalese..even to have copied and pasted
 * from some other place... PLEASE DO NOT BLAME ME in any way
 * if your system crashes because of this code, or if anything else
 * bad happens. In short "DO WHAT YOU WANT BUT DONT BLAME ME !"
 *****************************************************************/
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.lang.*;

//base class cShape

class cShape extends Object

{

// Data members    

}
// Base class cShape ends
 

//Class cLine for drawing lines is
//derived from our 'base' class cShape
class cLine extends cShape
{

      cLine() //Constructor
      {
      }

       void setStart(Point pt)
       {
           ptStart = pt;
       }
     void setEnd(Point pt)
     {
        ptEnd = pt;
     }

     Point getStart()
     {
        return ptStart;
     }

    Point getEnd()
    {
        return ptEnd;
    }
    //Drawing routine
     void Draw(Graphics g)
     {
         g.setColor(clrFront); //Set default color -you may ignore colors
         g.drawLine(ptStart.x,ptStart.y,ptEnd.x,ptEnd.y);
     }
}
// Class cLine ends

//Class cOval for drawing ovals is derived
//from our 'base class' cShape

class cOval extends cShape

{

        cOval() //Constructor

        {

        }

        void setStart(Point pt)

        {

            ptStart = pt;

        }

        void setEnd(Point pt)

        {

            ptEnd = pt;

        }

        void setWidth(int w)

        {

            nwidth = w;

        }

        void setHeight(int h)

        {

            nheight = h;

        }

        Point getStart()

        {

            return ptStart;

        }

        Point getEnd()

        {

            return new Point(0,0);

        }

        int getWidth()

        {

            return nwidth;

        }

        int getHeight()

        {

            return nheight;

        }

        //Drawing routine

        void Draw(Graphics g)

        {

            g.setColor(Color.green.darker()); //Set default color

            g.drawOval(ptStart.x, ptStart.y, nwidth, nheight);

        }

}    

// Class cOval ends 

//Class cRect for drawing Rects is derived
//from our 'base class' cShape

class cRect extends cShape

{

        cRect() //Constructor

        {

        }

        void setStart(Point pt)

        {

            ptStart = pt;

        }

        void setEnd(Point pt)

        {

            ptEnd = pt;

        }

        void setWidth(int w)

        {

            nwidth = w;

        }

        void setHeight(int h)

        {

            nheight = h;

        }

        Point getStart()

        {

            return ptStart;

        }

        Point getEnd()

        {

            return new Point(0,0);

        }

        int getWidth()

        {

            return nwidth;

        }

        int getHeight()

        {

            return nheight;

        }



        //Drawing routine

        void Draw(Graphics g)

        {

            g.setColor(Color.blue.brighter()); //Set default color

            g.drawRect(ptStart.x, ptStart.y, nwidth, nheight);

        }



}

// Class cRect ends    

//The OOPDraw2 main applet

public class OOPDraw2 extends NoFlickerApplet
{
cLine s;

cOval o;

cRect r;
Point startpos, endpos; //Declare the start and end positions
Button btnLine, btnOval, btnRect,btnClear;
Vector vt = new Vector(); //Vector for storing the shapes
int i = 0; //Vector index to keep count of elements(i.e.shapes)
int nheight1, nwidth1;
boolean bline = false;  //booleans to know which button was 

boolean boval = false; //hit/which shapes is to be drawn

boolean brect = false;
public void OOPDraw2()
    {
        //Do nothing in constructor off applet
    }
    public void init()
    {
        setLayout(new FlowLayout());
        //Create and Add the buttons

        btnLine = new Button("Line");

        btnOval = new Button("Oval");

        btnRect = new Button("Rectangle");

        btnClear = new Button("Clear");

        add(btnLine);

        add(btnOval);

        add(btnRect);

        add(btnClear);
    }
public void paint(Graphics g)
{
    //To get a shadow effect
    g.setColor(Color.black);

    g.fillRect(0,0,size().width,size().height);

    g.setColor(new Color(255,255,154));

    g.fillRect(1,1,size().width-3,size().height-3);
    for (int i = 0; i < vt.size(); i++)

    {   

        //Add the shapes to the vector 

        cShape sh = (cShape)vt.elementAt(i);

        sh.Draw(g);

    }
}
//Event handling
    public boolean action(Event e, Object o)
    {
        //See whic button was clicked and

        //set flags accordingly
        if (e.target.equals(btnLine))

        {

            bline = true;

            boval = false;

            brect = false;

        }
        if (e.target.equals(btnOval))

        {

            bline = false;

            boval = true;

            brect = false;

        }
        if (e.target.equals(btnRect))

        {

            bline = false;

            boval = false;            

            brect = true;

        }
        if (e.target.equals(btnClear))

        {

            //Clear the entire drawing screen

            //First remove all elements

                vt.removeAllElements();

            // then make vector index zero

                i =0;

            //finally, call repaint()

                repaint();

        }

        return true;

}
//Mouse Up i.e. mouse left button is released
public boolean mouseUp(Event evt, int x, int y)

{    
    endpos = new Point(x,y);
    if (bline)
    {

        s = (cLine)vt.elementAt(i);

        s.setEnd(endpos);

        i++; 

        //increment the index of Vector as

        //cLine object is now added at current index i

    }    
    if (brect)

        {    
        }
        repaint();
    return true;
}
//Mouse Down i.e. Left mouse button is down
public boolean mouseDown(Event evt, int x, int y)

{
    //Where the mouse went down is the start 

    //position of the shape to be drawn
    startpos = new Point(x,y);
    if (bline)
    {

        s = new cLine();     //Create the shape - Line

        s.setStart(startpos);//Set the start position where mouse went down

        vt.addElement(s);    //and add the shape (line) to the vector vt
    }
    if (boval)
    {

        o = new cOval();     //Create the shape - Oval

        o.setStart(startpos);//Set the start position where mouse went down

        vt.addElement(o);    //and add the shape (oval) to the vector vt

    }
    if (brect)
    {

        r = new cRect();     //Create the shape - Rectangle

        r.setStart(startpos);//Set the start position where mouse went down

        vt.addElement(r);    //and add the shape (Rectangle) to the vector vt

    }
    return true;
}
//Mouse Drag i.e. Left mouse button is down and mouse is being moved
public boolean mouseDrag(Event evt, int x, int y)

{
    //Now the mouse is being dragged without releasing,

    //which means that the user may stop his mouse over a 

    //point but not release it. So that point is the 

    //current endpoint
    endpos = new Point(x,y);
    if (bline)
    {

        s = (cLine)vt.elementAt(i);  //refer to that shape stored in vector

        s.setEnd(endpos);            //and set its end point.

    }
    if (boval)

    {
       //Here we see where the shape drawing started (mouse went down) and now

       //where the mouse is (mouse drag). And we draw from this new point to the

       //point from which the mouse went down. This avoids the Oval/Rectangle

       //from going out of the screen, or some really weird things from happening.

       // Try to take simple Line drawing type of approach and draw from bottom

       //right to top left and see what happens :)
       Point drawto = new Point( Math.max(x,startpos.x),Math.max(y,startpos.y));

       Point newstart = new Point(Math.min(x,startpos.x),Math.min(y,startpos.y));

       nwidth1 = Math.abs((drawto.x - newstart.x));

       nheight1 = Math.abs((drawto.y - newstart.y));

       o = (cOval)vt.elementAt(i);

       o.setWidth(nwidth1);

       o.setHeight(nheight1);

       o.setStart(newstart);
    }
    if (brect)
    {
        Point drawto = new Point( Math.max(x,startpos.x),Math.max(y,startpos.y));

        Point newstart = new Point(Math.min(x,startpos.x),Math.min(y,startpos.y));

        nwidth1 = Math.abs((drawto.x - newstart.x));

        nheight1 = Math.abs((drawto.y - newstart.y));

        r = (cRect)vt.elementAt(i);

        r.setWidth(nwidth1);

        r.setHeight(nheight1);

        r.setStart(newstart);
     }
    repaint();
    return true;
}    

// Noflicker applet class to avoid flickering (Got this from a
// news group..IF anyone knows whose contribution it is, please
// let me know. I wish to acknowledge the contributor). This basically
// draws the entire applet to an off-screen image and then 'dumps'
// the entire image to the screen at one go; thus avoiding flicker.
// This technique, though useful, should be used with care as it
// is CPU intensive.

class NoFlickerApplet extends Applet
{    
   }
//NoFlickerApplet class ends
} //ALL ends :)    

See the applet in action.