import java.awt.*; import java.awt.event.*; import java.applet.*; import java.io.*; /** PolyClipApplet is an applet that animates a polygon clipping algorithm.*/ public class PolyClipApplet extends Applet implements Runnable { PolyClipCanvas canvas; //drawing area Button step; //The button that user clicks on to get algorithm to do next step Button start; //The button that user clicks on to get algorithm to start Checkbox stepMode; //So user can turn off single step execution boolean dontWait = false; //If true, we don't wait till step button pressed /** Thread that executes given algorithm */ Thread runner; /** Start thread that executes given algorithm */ public void start() { if (runner != null){ /* let previous animation finish */ dontWait = true; wakeUp(); Thread.yield(); dontWait = false; } runner = new Thread(this); runner.start(); //Run in separate thread so it can step } /** This is the method called when a thread is started being animated. */ public void run() { //System.out.println("Polygon: "+polyToString(canvas.getPolygon())); //System.out.println("Rectangle: "+rectToString(canvas.getClipRectangle())); Polygon c = canvas.clipPolygon(canvas.getPolygon(),canvas.getClipRectangle()); runner = null; } /** Make algorithm continue execution after step() has been called */ synchronized void wakeUp() { notify(); } /** Stop execution until "Step" button is pressed and display a message*/ synchronized void step(String message) { if (dontWait) return; showStatus(message); try { if (stepMode.getState()) { wait(); } else { Thread.sleep(1000); //wait one second } } catch (InterruptedException e) { /*nothing */ } } /** init() is called by browser to initialize the applet */ public void init() { setBackground(Color.white); setLayout(new BorderLayout()); canvas = new PolyClipCanvas(this); add(canvas,"Center"); Panel p = new Panel(); /* When this button is clicked on the start method is called */ start = new Button("Start"); p.add(start); start.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e){ start(); } }); /* When this button is clicked on the wakeUp method is called */ step = new Button("Step"); p.add(step); step.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e){ wakeUp(); } }); /* No need to do anything when user changes state of the checkbox */ stepMode = new Checkbox("Step Mode",true); p.add(stepMode); Button clear = new Button("Clear"); p.add(clear); clear.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e){ canvas.clear(); } }); add(p,"South"); } public int getInt(StreamTokenizer st) throws IOException{ while (st.nextToken() != StreamTokenizer.TT_EOF) { if (st.ttype == StreamTokenizer.TT_NUMBER) { return (int)st.nval; } } throw new EOFException("EOF while looking for an int"); } public String polyToString(Polygon p){ StringBuffer sb = new StringBuffer(p.npoints+" ["); //find top leftmost point int topleftindex = 0; for (int i = 0; i < p.npoints; i++){ if (p.xpoints[i] < p.xpoints[topleftindex] || (p.xpoints[i] == p.xpoints[topleftindex] && p.ypoints[i] < p.ypoints[topleftindex])){ topleftindex = i; } } for (int i = 0; i < p.npoints; i++){ int j = (i+topleftindex) % p.npoints; sb.append("("+p.xpoints[j]+","+p.ypoints[j]+"),"); } sb.setCharAt(sb.length()-1,']'); return sb.toString(); } public String rectToString(Rectangle r){ return r.x + " " + r.y + " " + r.width + " " + r.height; } /* method for non-interactive testing of PolyClipCanvas */ public void test(){ dontWait = true; Polygon p = new Polygon(); Rectangle r = new Rectangle(); canvas = new PolyClipCanvas(this); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StreamTokenizer st = new StreamTokenizer(in); try { while (st.nextToken() != StreamTokenizer.TT_EOF) { if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("Polygon")) { //Define a polygon for clipping p = new Polygon(); for (int n = getInt(st); n>0; n--){ p.addPoint(getInt(st),getInt(st)); } System.out.println("Polygon "+polyToString(p)); } else if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("Rectangle")) { //Define a clip rectangle r = new Rectangle(getInt(st),getInt(st),getInt(st),getInt(st)); System.out.println("Rectangle "+rectToString(r)); } else if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("Clip")) { //Clip the polygon and print the result Polygon clip = canvas.clipPolygon(p,r); System.out.println("Clipped "+polyToString(clip)); } else if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("GetClipRectangle")) {//Print the clip rectangle defined by the canvas r = canvas.getClipRectangle(); System.out.println("Rectangle "+rectToString(r)); } else if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("Frame")) {//create a frame so that the canvas can draw on screen Frame f = new Frame(); f.setSize(300,300); f.add(canvas); f.setVisible(true); } else if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("MouseEvent")) {//send a mouse event to canvas MouseEvent e = new MouseEvent(canvas,getInt(st), 0,getInt(st),getInt(st),getInt(st), 1,false); canvas.dispatchEvent(e); } else if (st.ttype == StreamTokenizer.TT_WORD && st.sval.equals("Quit")) { System.exit(0); } } } catch (IOException e){ System.err.println("Error on reading"); } } public static void main(String[] args){ PolyClipApplet applet = new PolyClipApplet(); applet.setStub(new FakeAppletStub("")); applet.test(); } }