import java.awt.*;

public class Projetbis extends java.applet.Applet {
  
  GraphCanvas graphcanvas = new GraphCanvas(this);
  Options options = new Options(this);   
  Scroll_pt_class scroll_pt_class = new Scroll_pt_class(this);
  
  
  public void init() {
    setLayout(new BorderLayout(10, 10));
    add("Center", graphcanvas);
    add("East", options);
    add("South", scroll_pt_class);
  }

  public void start() {
    graphcanvas.initialisation();

  }


  public void lock() {
    graphcanvas.lock();
    options.lock();
  } 
  
  public void unlock() {
    graphcanvas.unlock();
    options.unlock();
  }
  
}



Class Scroll_pt_class extends Panel {
  
  Private Scrollbar sb_point = new Scrollbar(Scrollbar.HORIZONTAL, graphcanvas.n, 5, 2, graphcanvas.maxN);
  Private Scrollbar sb_class = new Scrollbar(Scrollbar.HORIZONTAL, graphcanvas.Nb_Class, 5, 2, graphcanvas.maxC);


  public Scroll_pt_class(Projetbis myparent) {
    parent = myparent;
    setLayout(new GridLayout(6, 1, 0, 10));
    add(sb_class);
    add(sb_point);
  }

  public boolean handleEvent(Event evt) {    
    switch (evt.id) {
    case Event.SCROLL_LINE_UP: case Event.SCROLL_LINE_DOWN:
    case Event.SCROLL_PAGE_UP: case Event.SCROLL_PAGE_DOWN:
    case Event.SCROLL_ABSOLUTE:
      graphcanvas.setn(sb_point.getValue());
      graphcanvas.setclass(sb_class.getValue());
      graphcanvas.repaint();
      break;
    default:
      break;
    } // switch
    return(true);
  }

} // class Scroll_pt_class


class Options extends Panel {
  
// set of options at the right of the screen

  private Button b1 = new Button("clear");
  private Button b2 = new Button("run");
  private Button b3 = new Button("step");
  private Button b4 = new Button("reset");
  private Button b5 = new Button("example");
  private Button b6 = new Button("exit");
  private Projetbis parent;   
  private boolean Locked = false;
  
  public Options(Projetbis myparent) {
    parent = myparent;
    setLayout(new GridLayout(6, 1, 0, 10));
    add(b1);
    add(b2);
    add(b3);
    add(b4);
    add(b5); 
    add(b6);
  }
  
  public boolean action(Event evt, Object arg) {
    if (evt.target instanceof Button) {
      if (((String)arg).equals("step")) {}
      if (((String)arg).equals("next step")) {}
      if (((String)arg).equals("reset")) {}
      if (((String)arg).equals("clear")) {}
      if (((String)arg).equals("run")) {}
      if (((String)arg).equals("example")) {}
      if (((String)arg).equals("exit")) { 
	System.exit(0);
      } 
    }                   
    return true; 
  }
  
  public void lock() {
    Locked=true;
  }
  
  public void unlock() {
    Locked=false;
    b3.setLabel("step"); 
  } 
}    

class GraphCanvas extends Canvas {

// drawing area for the graph

  public   final int	maxN = 30;	// the max number of terminals
  public   int		n = 10;		// the current number of terminals
  private final int	r = 4;		// the radius of a terminal
  private Point		p[];		// the terminals
  private Point		current;	// the current one and its old location
  private float		m[][];		// the minimum spanning tree edges
  private Rectangle	border, inner;	// applet borders
  private Image		offScreenImage;	// offScreenImage for double-offScreenImage
  private Graphics	offScreenGraphics; // offScreenImage's Graphics
  private Dimension     offScreenSize;
  private boolean       Locked = false;
  private int          	step;
  private Projetbis    	parent;
  public int            Nb_Class;
  public final int      maxC = 9;
  private final float   Indef = 100;

  public GraphCanvas(Projetbis myparent) {
    parent = myparent;
  }
  
  public void lock() {
    // lock screen while running an algorithm
    Locked=true;
  }
  
  public void unlock() {
    Locked=false;
  }
  
  public final void update(Graphics g) {
    
    // prepare new image offscreen
    Dimension d=size();
    if ((offScreenImage == null) || (d.width != offScreenSize.width) ||
	(d.height != offScreenSize.height)) {
      offScreenImage = createImage(d.width, d.height);
      offScreenSize = d;
      offScreenGraphics = offScreenImage.getGraphics();
    }
    offScreenGraphics.setColor(Color.white);
    offScreenGraphics.fillRect(0, 0, d.width, d.height);

    // redraw the terminals
    
     for (int i = 0; i < n; i++) {
       offScreenGraphics.setColor(Color.green);
       offScreenGraphics.fillOval(p[i].x - r, p[i].y - r, 2 * r, 2 * r);
      offScreenGraphics.setColor(Color.black);
      offScreenGraphics.drawOval(p[i].x - r, p[i].y - r, 2 * r, 2 * r);
    }
    
    // draw the current one in cyan
    if (current != null) {
      offScreenGraphics.setColor(Color.cyan);
      offScreenGraphics.fillOval(current.x - r, current.y - r, 2 * r, 2 * r);
      offScreenGraphics.setColor(Color.black);
      offScreenGraphics.drawOval(current.x - r, current.y - r, 2 * r, 2 * r);
    } 

    g.drawImage(offScreenImage, 0, 0, null);
  }

  
  public void initialisation() {
    p = new Point[maxN];
    current = null;
    m = new float[maxN][maxN];
    
    border = new Rectangle(0, 0, size().width , size().height );
    inner = new Rectangle(r , r , size().width -  r , size().height -  r);
    
    // initialize the terminals to random locations
    for (int i = 0; i < maxN; i++) {
      p[i] = new Point((int) Math.round(Math.random()
					* (size().width - r )),
		       (int) Math.round(Math.random()
					* (size().height - r)) );
      for (int j = 0; j < maxN; j++) {
	m[i][j] = Indef;
      }
    }
    
    setBackground(Color.white);	
    repaint();

   } // init()
  
   public void paint(Graphics g) {
     update(g);
  } // paint(Graphics)
  
  
  public boolean handleEvent(Event evt) {
    switch (evt.id) {
      
    case Event.MOUSE_DOWN:
      Rectangle rect = new Rectangle();
      
      current = null;
      for (int i = 0; (i < n) && (current == null); i++) {
	rect.reshape(p[i].x - r, p[i].y - r, 2 * r, 2 * r);
	if (rect.inside(evt.x, evt.y)) {
	  current = p[i];
	}
      }
      break;
    case Event.MOUSE_UP: {
      current = null;
      repaint();
      break;
    }
      
    case Event.MOUSE_DRAG: {
      if (current != null) {
	if (inner.inside(evt.x, evt.y)) {
	  current.move(evt.x, evt.y);
	}
	else {
	  current.move(Math.max(Math.min(evt.x, inner.x + inner.width), inner.x),
		       Math.max(Math.min(evt.y, inner.y + inner.height), inner.y));
	}
	repaint();
      }
      break;
    }
      
    case Event.SCROLL_LINE_UP: case Event.SCROLL_LINE_DOWN:
    case Event.SCROLL_PAGE_UP: case Event.SCROLL_PAGE_DOWN:
    case Event.SCROLL_ABSOLUTE: {
      repaint();
      break;
    }
      
    default: {
      break;
    }
      
    } // switch
    
    return(true);
  } // handleEvent(Event)
  
  
  // Euclidean distance between two points (x1,y1) and (x2,y2)
  private int distance(int x1, int y1, int x2, int y2) {
    return((int) Math.round(Math.sqrt(
				      (double) (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))));
  } // distance(int,int,int,int)
  
  
  public void setn(int i) {
    n = i;
    parent.sb_point.setValue(n);
  }
  
  public void setclass(int i) {
    Nb_Class = Math.min(i,maxC);
    m = new float[maxN][maxC];
    for (i = 0; i < maxN; i++) {
      m[i][1] = Indef;
      m[i][2] = Indef;
    }
//    init_distance();
    System.out.println("Class :"+Nb_Class);
  }
  
  
  
}






