Vers un éditeur de circuits logiques...

Comme promis, voici le source du programme décrit au TD du vendredi 18 décembre 1998. Vous pouvez récupérer le source dans le fichier archivé=compressé cl.java.tar.gz

Que cela ne vous empêche pas de passer un bon Noël et une bonne année :-)

import java.awt.*;
import java.awt.event.*;

/** ==
  Ensemble d'objets 
  */
class Ensemble 
{
  // -- Nombre maximal d'objets
  private int max;
  // -- Nombre courant d'objets
  private int cpt;
  // -- Tableau de stockage
  private Object t[];

  // -- Constructeur
  public Ensemble(int n)
  {
    max = n;
    cpt = 0;
    t = new Object[n];
  }

  // -- Lecture du i-eme objet
  public Object get(int i) 
  {
    return(t[i]);
  }

  // -- Ajout d'un objet a l'ensemble
  public boolean add(Object o)
  {
    if (cpt < max) { t[cpt++] = o; return true; }
    else return false;
  }

  // -- Lecture du nombre courant d'objets
  public int getcursize() { return cpt; }

  // -- Appartenance
  public boolean mem(Object o)
  {
    for(int i=0; i < cpt; i++)
      {
	if (o==t[i]) return true;
      }
    return false;
  }
       
}

/** ==
  Les points de connexion
  */
class ConnexionPoint 
{
  // -- Un compteur global : 
  //    chaque point recoit un numero d'ordre de creation
  static int N = 0;
  
  // -- Position
  int x;
  int y;

  // -- Numero
  int n;

  // -- Pour affichage (cf 'paint')
  int xs[] = {0,0,0};
  int ys[] = {0,0,0};

  // -- Constructeurs
  ConnexionPoint() { n = ++N; }
  ConnexionPoint(int x0, int y0) 
  { 
    n = ++N; x = x0; y = y0; 
    xs[0] = x; xs[1] = x+5; xs[2] = x;
    ys[0] = y; ys[1] = y+2; ys[2] = y+5;
  }

  // -- Mise a jour des positions 
  void place(int x0, int y0) 
  { 
    x = x0; y = y0; 
    xs[0] = x; xs[1] = x+5; xs[2] = x;
    ys[0] = y; ys[1] = y+2; ys[2] = y+5;
  }

  // -- Effacement
  void clear(Graphics g) { g.clearRect(x,y,5,5); }

  // -- Affichage
  void paint(Graphics g) { g.fillPolygon(xs,ys,3); }

  // -- Affichage texte
  void print() { System.out.println("ConnexionPoint ["+n+"]("+x+","+y+")"); }

}

/** ==
  Les boites de connection
  */
abstract class ConnexionBox
  implements MouseListener, MouseMotionListener
{
  // -- Position
  int x;
  int y;
  
  // -- Deplacement demande
  int nextX;
  int nextY;

  // -- Boite active ou non (cf 'paint' et 'place')
  boolean selected;

  // -- Points d'entree et points de sortie
  ConnexionPoint in[];
  ConnexionPoint out[];

  // -- Deplacement effectif
  void place(int x0, int y0) { x = x0; y = y0; }

  // -- Effacement
  abstract void clear(Graphics g);

  // -- Affichage
  abstract void paint(Graphics g);

  // -- Affichage texte
  abstract void print();

  // -- Reaction aux evenements souris :
  //    'Nop' pour l'instant
  public void mousePressed(MouseEvent e) { ; }
  public void mouseReleased(MouseEvent e) { ; } 
  public void mouseClicked(MouseEvent e) { ; }
  public void mouseEntered(MouseEvent e) { ; }
  public void mouseExited(MouseEvent e) { ; }

  public void mouseDragged(MouseEvent e) { ; }
  public void mouseMoved(MouseEvent e) { ; }

}

/** ==
  Fils de connection
  */
class WireBox extends ConnexionBox
{

  // -- Etats du fil
  boolean inConnected;
  boolean inConnecting;
  boolean outConnected;
  boolean outConnecting;

  // -- Position entree
  int inX;
  int inY;
  // -- Deplacement entree
  int nextInX;
  int nextInY;

  // -- Position sortie
  int outX;
  int outY;
  // -- Deplacement sortie
  int nextOutX;
  int nextOutY;

  // -- Zone de dessin (cf 'mouseReleased')
  DesignPanel p;

  // -- Constructeur
  WireBox(DesignPanel p0)
  {
    super();
    p = p0;
    inX = 5;
    inY = 5;
    outX = 20;
    outY = 5;
    inConnected = false;
    inConnecting = false;
    outConnected = false;
    outConnecting = false;
    selected = false;
    in = new ConnexionPoint[] {new ConnexionPoint(inX-2, inY-2)};
    out = new ConnexionPoint[] {new ConnexionPoint(outX-2, outY-2)};
  }

  // -- Deplacement effectif :
  //    entree ou sortie, suivant l'etat
  void place(int x0, int y0)
  {
    if (inConnecting)
      { 
	inX = x0; inY = y0;
	in[0].place(x0-2, y0-2);
      }
    else if (outConnecting)
      { 
	outX = x0; outY = y0;
	out[0].place(x0-2, y0-2);
      }
  }

  // -- Effacement
  void clear(Graphics g)
  { 
    g.drawLine(inX,inY,outX,outY);
    in[0].paint(g);
    out[0].paint(g);
  }

  // -- Affichage
  void paint(Graphics g) 
  { 
    if (inConnecting) { place(nextInX, nextInY); }
    else if (outConnecting) { place(nextOutX, nextOutY); }
    g.drawLine(inX,inY,outX,outY);
    in[0].paint(g);
    out[0].paint(g);
  }

  // -- Affichage texte
  void print() 
  { 
    System.out.println("WireBox :");
    in[0].print();
    out[0].print();
  }

  // -- Reaction au bouton presse :
  //    devient actif ('selected') si l'on designe
  //    le point d'entree ou le point de sortie
  public void mousePressed(MouseEvent e) 
  { 

    int xm = e.getX();
    int ym = e.getY();

    inConnecting =
      (!inConnected 
       && (inX-5 <= xm && xm <= inX+5) && (inY-5 <= ym && ym <= inY+5));

    outConnecting =
      (!outConnected
       && (outX-5 <= xm && xm <= outX+5) && (outY-5 <= ym && ym <= outY+5));

    selected = inConnecting || outConnecting;
  }

  // -- Reaction au bouton relache :
  //    mise a jour du point de sortie ou d'entree
  //    suivant l'etat
  public void mouseReleased(MouseEvent e)  
  {
    if (selected) 
      {
	int xm = e.getX();
	int ym = e.getY();

	if(inConnecting)
	  {
	    ConnexionPoint cp = p.isOutPoint(xm, ym);
	    if (cp != null) 
	      { 
		clear(p.getGraphics());
		in[0] = cp;
		nextInX = cp.x+2;
		nextInY = cp.y+2;
		paint(p.getGraphics());
		inConnecting = false;
	      }
	  }
	else if (outConnecting)
	  {
	    ConnexionPoint cp = p.isInPoint(xm, ym);
	    if (cp != null) 
	      {
		clear(p.getGraphics());
		out[0] = cp;
		nextOutX = cp.x+2;
		nextOutY = cp.y+2;
		paint(p.getGraphics());
		outConnected = true;
	      }
	  }
	selected = false;
      }
  }

  // -- Reaction au mouvement de la souris
  public void mouseDragged(MouseEvent e)
  {
    if (selected)
      { 
	if (inConnecting)
	  { 
	    nextInX = e.getX(); nextInY = e.getY(); 
	  }
	else if (outConnecting)
	  { nextOutX = e.getX(); nextOutY = e.getY(); }
      }
  }

}

/** ==
  Une boite a une entree et une sortie
  */
class NotBox extends ConnexionBox 
             implements MouseListener, MouseMotionListener
{

  // -- Dimension
  int w;
  int h;

  // -- Constructeur
  NotBox()
  {
    super();
    w = 20;
    h = 15;
    x = 5;
    y = 5;
    nextX = 5;
    nextY = 5;
    selected = false;
    in = new ConnexionPoint[] {new ConnexionPoint()};
    out = new ConnexionPoint[] {new ConnexionPoint()};
  }

  // -- Deplacement effectif
  void place(int x0, int y0)
  {
    super.place(x0, y0);
    in[0].place(x, y+5);
    out[0].place(x+w, y+5);
  }

  // -- Effacement
  void clear(Graphics g)
  {
    g.clearRect(x,y,w+1,h+1);
    in[0].clear(g);
    out[0].clear(g);
  }

  // -- Affichage
  void paint(Graphics g)
  {
    if (selected) { place(nextX, nextY); }
    g.drawRect(x,y,w,h);
    in[0].paint(g);
    out[0].paint(g);
  }

  // -- Affichage texte
  void print() 
  { 
    System.out.print("NotBox ("+x+","+y+") ");
    System.out.print("InPoints ");
    for(int i=0; i < in.length; i++) in[i].print();
    System.out.print(" OutPoints ");
    for(int i=0; i < out.length; i++) out[i].print();
  }

  // -- Reaction au bouton presse :
  //    devient actif si concerne
  public void mousePressed(MouseEvent e)
  {
    if (!selected)
      {
	int xm = e.getX();
	int ym = e.getY();
	
	selected = ((x <= xm && xm <= x+w) && (y <= ym && ym <= y+h));
      }
  }

  // -- Reaction au bouton relache :
  //    devient inactif
  public void mouseReleased(MouseEvent e) 
  { 
    if (selected) 
      {
	selected = false; 
      }
  }

  // -- Reaction au mouvement de la souris :
  //    demande de mouvement si actif
  public void mouseDragged(MouseEvent e)
  {
    if (selected)
      { 
	nextX = e.getX();
	nextY = e.getY();
      }
  }
  
}

/** ==
  La zone de dessin
  */
class DesignPanel extends Panel
{

  // -- Ensemble des boites de connection
  Ensemble bs;

  // -- Ensemble de fils de connection
  Ensemble ws;
  
  // -- Constructeur
  DesignPanel(int h, int w)
  {
    super();
    setSize(h,w);
    setVisible(true);
    bs = new Ensemble(25);
    ws = new Ensemble(25);
  }

  // -- Retourne le point de connection designe
  //    (a peu pres) par 'x' et 'y' si c'est un point
  //    d'entree, 'null' sinon
  ConnexionPoint isInPoint(int x, int y)
  {
    int i=0;
    while(i < bs.getcursize())
      {
	ConnexionBox b = (ConnexionBox)bs.get(i);

	int j=0;
	while(j < b.in.length)
	  {
	    ConnexionPoint cp = b.in[j];
	    if ((x-5 <= cp.x && cp.x <= x+5) && (y-5 <= cp.y && cp.y <= y+5))
	      { return cp; }
	    j++;
	  }
	i++;
      } 
    return (ConnexionPoint)null;
  }

  // -- Retourne le point de connection designe
  //    (a peu pres) par 'x' et 'y' si c'est un point
  //    d'entree, 'null' sinon
  ConnexionPoint isOutPoint(int x, int y)
  {
    int i=0;
    while(i < bs.getcursize())
      {
	ConnexionBox b = (ConnexionBox)bs.get(i);

	int j=0;
	while(j < b.out.length)
	  {
	    ConnexionPoint cp = b.out[j];
	    if ((x-5 <= cp.x && cp.x <= x+5) && (y-5 <= cp.y && cp.y <= y+5))
	      { return cp; }
	    j++;
	  }
	i++;
      } 
    return (ConnexionPoint)null;
  }

  // -- Ajout d'une nouvelle boite de connection
  void addBox(ConnexionBox b)
  {
    bs.add(b);
    addMouseMotionListener(b);
    addMouseListener(b);
  }

  // -- Ajout d'un nouveau fil de connection
  void addWire(ConnexionBox b)
  {
    ws.add(b);
    addMouseMotionListener(b);
    addMouseListener(b);
  }

  // -- Effacement d'une boite (ou d'un fil) de connexion
  void clearBox(ConnexionBox b)
  {
    setForeground(getBackground());
    b.clear(this.getGraphics());
  }

  // -- Affichage d'une boite (ou d'un fil) de connexion
  void paintBox(ConnexionBox b)
  {
    setForeground(Color.black);
    b.paint(this.getGraphics());
  }

  // -- Afficahge de l'ensemble des boites et fils de connection
  void paintBoxes()
  {

    for(int i=0; i < bs.getcursize(); i++)
      {
	ConnexionBox b = (ConnexionBox)bs.get(i);

	if (b.selected) clearBox(b);
	paintBox(b);
      }

    for(int i=0; i < ws.getcursize(); i++)
      {
	ConnexionBox b = (ConnexionBox)ws.get(i);

	if (b.selected) clearBox(b);
	paintBox(b);
      }
    
  }

  // -- Affichage general
  public void paint(Graphics g)
  {
    setVisible(true);
    paintBoxes();
  }

  // -- Affichage texte
  void print() 
  { 
    System.out.println("DesignPanel ");
    for(int i=0; i < bs.getcursize(); i++) 
      { 
	((ConnexionBox)bs.get(i)).print();
	System.out.println();
      }
    for(int i=0; i < ws.getcursize(); i++) 
      { 
	((ConnexionBox)ws.get(i)).print();
	System.out.println();
      }
  }

}

/** ==
  Gestionnaire d'evenements pour la zone de dessin :
  appelle la methode 'paint' sur les evenements auxquels
  reagissent les boites de connexion
  */
class panelMouseAdapter implements MouseListener, MouseMotionListener
{

  // -- La zone de dessin
  DesignPanel p;

  // -- Constructeur
  panelMouseAdapter(DesignPanel p0) { p = p0; }

  // -- Reactions au evenements souris
  public void mousePressed(MouseEvent e) { p.paint(p.getGraphics()); }
  public void mouseReleased(MouseEvent e) { p.paint(p.getGraphics()); } 
  public void mouseClicked(MouseEvent e) { ; }
  public void mouseEntered(MouseEvent e) { ; }
  public void mouseExited(MouseEvent e) { ; }

  public void mouseDragged(MouseEvent e) { p.paint(p.getGraphics()); }
  public void mouseMoved(MouseEvent e) { ; }
}

/** ==
  Classe pincipale
  */
class cl2
{

  // -- La zone de dessin
  static DesignPanel p = new DesignPanel(200,200);
  // -- Le delegue pour la zone de dessin
  static panelMouseAdapter a = new panelMouseAdapter(p);
  // La fentre principale
  static Frame f = new Frame("Titre");

  // -- Stop ou encore ?
  static boolean stop = false;

  // -- *LA* methode
  public static void main(String args[])
  { 

    // -- Fenetre principale
    f.setSize(300,300);
    f.setLayout(new BorderLayout(2,2));
    f.show();

    // -- Zone de dessin
    p.addMouseListener(a);
    p.addMouseMotionListener(a);
    f.add("Center",p);

    // -- Zone des boutons
    // Bouton "box" : creation d'une boite
    Button boxb = new Button("box");
    boxb.addActionListener(new ActionListener()
      {
	public void actionPerformed(ActionEvent e)
	  {
	    NotBox b = new NotBox();
	    p.addBox((ConnexionBox)b);
	    b.selected = true;
	    p.paintBox((ConnexionBox)b);
	    b.selected = false;
	  }
      });

    // Bouton "connect" : creation d'un fil
    Button conb = new Button("connect");
    conb.addActionListener(new ActionListener()
      {
	public void actionPerformed(ActionEvent e)
	  {
	    WireBox b = new WireBox(p);
	    p.addWire((ConnexionBox)b);
	    //b.selected = true;
	    p.paintBox((ConnexionBox)b);
	    b.selected = false;
	  }
      });

    // Bouton "print" : affichage texte
    Button printb = new Button("print");
    printb.addActionListener(new ActionListener()
      {
	public void actionPerformed(ActionEvent e)
	  {
	    p.print();
	  }
      });

    // Zone des boutons : initialisations
    Panel bp = new Panel();
    bp.setLayout(new GridLayout());
    bp.add(boxb);
    bp.add(conb);
    bp.add(printb);
    f.add("South",bp);

    // Affichage du tout
    f.paintAll(f.getGraphics());
  }  
}

Page initiale Maison Page précédente POD