import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.ScrollPane;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;

// Canvas d'un circuit, herite de HWCanvas
public class CircuitCanvas extends HWCanvas {
	
	// Canvas serializable
	private static final long serialVersionUID = 1L;
	
	// Police de caractere pour afficher le nom dans le canvas
	private Font font;
	
	// Drag
	GPin gpinA; // Pin de base de liaison
	public enum PINNING { NONE, ALLOWED, NOTALLOWED };
	PINNING allowedPinning; // Liaison en cours valide ou non
	Point dragPoint1, dragPoint2; // Point de base et courant lors d'un drag
	Rectangle dragRect = new Rectangle(); // Rectangle du drag
	// En mode de selection multiple, possible selection multiple, liaison
	boolean selectionning = false, may_selectionning = false, pinning = false;
	
	// Boutons
	ArrayList<Button> buttonClips = new ArrayList<Button>();
	
	// Dernieres informations de la souris
	MouseEvent lastME;
	
	// Nombre de pins d'entrees et sorties de base (modifiable via les touches (CTRL+)F...)
	int n_in=2, n_out=1;
	
	// Constructeur
	public CircuitCanvas(){
		super();
		font = new Font("ARIAL", Font.PLAIN, 18);
		// Ajout des boutons dans le menu
		addButton("Porte ET (a)");
		addButton("Porte OU (o)");
		addButton("Porte NON (n)");
		addButton("Porte XOR (x)");
		addButton("Porte Tempo (t)");
		addButton("Porte Impulse (i)");
		addButton("Porte Cycle (c)");
		addButton("Porte Bascule (b)");
		addButton("Entrée (q)");
		addButton("Sortie (s)");
		// Demarrage du thread qui gere le repaint du canvas
		refresh_thread.start();
	}
	
	// Destruction de l'element
	@SuppressWarnings("deprecation") // refresh_thread.stop(), thread non critique 
	public void Dispose(){
		if(isDisposed) return;
		if(refresh_thread!=null){ // Destruction du thread de repaint
			refresh_thread.stop();
			refresh_thread = null;
		}
		selectedClips.clear(); // Suppression des clips
		buttonClips.clear();
		hoverClip = null;
		super.Dispose(); // Destruction de la classe parente
	}
	
	// Repaint du canvas
	boolean redrawing = false; // Si on est en phase de repaint
	Semaphore sem = new Semaphore(0);
	public void redraw(){
		// Si detruit, ou deja en phase de repaint, on quitte
		if(isDisposed) return;
		if(redrawing) return;
		requestFocus(); // On demande le focus (probleme de focus dans Linux)
		sem.release(); // On relache le semaphore pour lancer le repaint
	}
	
	// Thread de repaint
	Thread refresh_thread = new Thread(){public void run(){
		while(!isDisposed){ // Tant que pas detruit
			try {
				sem.acquire(); // On acquit le semaphore (on attends qu'on le relache dans la methode redraw() pour continuer)
			} catch (InterruptedException e1) {}
			if(g==null) continue; // Si le graphics n'est pas initialiser, ca sert a rien de continuer
			redrawing = true; // La phase de repaint demarre
			try { // On attends un peu, au cas ou il y ait plein de repaint necessaire successif
				Thread.sleep(15); // Limiter à 1000/15 ips
			} catch (InterruptedException e) {}
			// Dessiner les clips
			((HWCanvas)(CircuitCanvas.this)).redraw(false);
			// Si on est en mode de liaison
			if(pinning){
				// Suivant si la liaison est faisable ou non, on change la couleur du trait
				if(allowedPinning		== PINNING.ALLOWED) g.setColor(new Color(50, 255, 50, 50));
				else if(allowedPinning	== PINNING.NONE) 	g.setColor(new Color(50, 50, 255, 50));
				else										g.setColor(new Color(255, 50, 50, 50));
				// Dessin de la ligne
				g.setStroke(GLiaison.stroke);
				g.drawLine(	dragPoint1.x, dragPoint1.y, dragPoint2.x, dragPoint2.y );
			}else if(selectionning){
				// Si on est en mode de selection, on affiche un rectangle representation cette selection
				g.setColor(new Color(50, 50, 255, 50));
				g.fillRect(	dragRect.x, dragRect.y, dragRect.width, dragRect.height );
			}
			try{ // Affichage du menu si voulue
				if(showMenu)
					for(Button draw : buttonClips)
						draw.repaint(g, -CircuitCanvas.this.getX(), -CircuitCanvas.this.getY());
			}catch(Exception e){}
			// Affichage de la mini-map si voulue
			if(showMap) createMap();
			// Affichage du nom
			g.setColor(Color.GRAY);
			g.setFont(font);
			g.drawString("Maxence Jaouan - Projet portes logiques", 10, 25);
			g.setColor(Color.WHITE);
			// Affichage de la strategy
			refresh();
			// Phase de repaint terminee
			redrawing = false;
		}
	
	}};
	
	// Mini-map
	// Position/taille de la mini-map
	int mapx, mapy, mapw, maph;
	// Ratio de division pour la minimap
	int map_size = 10;
	public void createMap(){
		mapw = (int)(this.getWidth()/map_size);
		maph = (int)(this.getHeight()/map_size);
		g.setColor(new Color(200, 200, 255, 100));
		mapx = -this.getX() + 20;
		mapy = this.getParent().getHeight()-maph -this.getY() - 40;
		g.fillRect(mapx-10, mapy-10, mapw+20, maph+20);
		try{
			// Recuperation de l'image de base des composants, et la dessiner a la bonne position
			for(Clip draw : clips)
				if(draw.getImage() != null){
					if(draw instanceof GLiaison) g.drawImage(draw.getImage(), mapx+(draw.x-draw.width/2)/map_size, mapy+(draw.y-draw.height/2)/map_size, draw.width/map_size, draw.height/map_size, null);
					else g.drawImage(draw.getImage(), mapx+draw.x/map_size, mapy+draw.y/map_size, draw.width/map_size, draw.height/map_size, null);
				}
		}catch(Exception ex){}
		g.setColor(new Color(255, 255, 255, 100));
		g.fillRect(mapx-this.getX()/map_size, mapy-this.getY()/map_size, this.getParent().getWidth()/map_size, this.getParent().getHeight()/map_size);
	}
	
	// Evenement de clique de souris
	public void mouseClicked(MouseEvent me) {
		if(hoverClip != null && hoverClip instanceof GIn) // (hoverClip = clip que l'on survole avec la souris)
			((GIn)hoverClip).mouseClicked(me);
	}
	// Quand la souris rentre dans l'applet
	public void mouseEntered(MouseEvent me) {
		mouseMoved(me);
	}
	// Quand la souris sort de l'applet
	public void mouseExited(MouseEvent me) {
		setHoverClip(null);
	}
	
	// Quand on appuit sur la souris
	public void mousePressed(MouseEvent me) {
		if(me.getButton() != MouseEvent.BUTTON1) return; // Si c'est autre chose que le bouton gauche, on quitte
		mouseMoved(me); // On appelle mouseMoved pour mettre a jour le curseur
		dragPoint1 = dragPoint2 = me.getPoint();
		if(showMap && Clip.hitTest(new Rectangle(mapx, mapy, mapw, maph), me.getPoint())){ // Si on affiche la mini-map et qu'on est dessus, on gère pour se deplacer
			((ScrollPane)this.getParent()).setScrollPosition((int)(me.getPoint().getX() - mapx)*map_size-this.getParent().getWidth()/2, (int)(me.getPoint().getY() - mapy)*map_size-this.getParent().getHeight()/2);
		}else if(hoverClip == null){ // Si on survole aucun clip, alors on peut commencer une selection multiple
			may_selectionning = true;
			dragRect.setBounds(0, 0, 0, 0);
			if(!me.isControlDown()) selectedClips.clear(); // Si CTRL est maintenu, on n'efface pas la selection courante
		}else if(hoverClip instanceof Button){ // Si on clique sur un bouton, on gere son action
			if(showMenu) selectButton((Button) hoverClip, !((Button)hoverClip).selected);
		}else if(hoverClip instanceof GLiaison){ // Si il s'agit d'une liaison, on voit si elle propose de se redimensionner
			if(!isSelected(hoverClip)){
				if(!me.isControlDown()) selectedClips.clear();
				selectClip(hoverClip, true);
			}
			((GLiaison) hoverClip).mousePressed(me);
			bringMeToFront(hoverClip);
		}else if(hoverClip instanceof GPin){ // Si il s'agit d'un pin, on initialise la procedure de liaison
			pinning = true;
			gpinA = (GPin) hoverClip;
			allowedPinning = PINNING.NONE;
			dragPoint1 = new Point(gpinA.parent.x+gpinA.x+gpinA.width/2, gpinA.parent.y+gpinA.y+gpinA.height/2);
		}else{ // Sinon on selectionne/deselectionne le clip
			if(!isSelected(hoverClip)){
				if(!me.isControlDown()) selectedClips.clear();
				selectClip(hoverClip, true);
			}else{
				selectClip(hoverClip, !me.isControlDown());
			}
			// On remet le clip au premier plan
			bringMeToFront(hoverClip);
		}
	}
	// Evement lorsque qu'on relache le bouton de la souris
	public void mouseReleased(MouseEvent me) {
		if(me.getButton() != MouseEvent.BUTTON1) return; // Si ce n'est pas le bouton gauche, on quitte
		mouseMoved(me);
		if(selectionning){ // Si on était en mode de selection, on supprime le rectangle
			dragRect.setBounds(0, 0, 0, 0);
		}else if(pinning){ // Si on est en mode de liaison
			if(hoverClip != null && hoverClip instanceof GPin && allowedPinning == PINNING.ALLOWED){ // Et qu'on relache sur un pin et que la liaison est autorise
				try{
					new Thread(){public void run(){try {
						new GLiaison(gpinA, (GPin) hoverClip); // On cree la liaison
					} catch (Exception e) {}
					gpinA = null;}}.start();
				}catch(Exception e){}
			}
			
		}else if(hoverClip == null && selectedButton != null){ // Menu
			GCircuitElement gce = null;
			switch(buttonClips.indexOf(selectedButton)){ // Suivant quel bouton c'est, on cree tel ou tel porte
				case 0 :
					gce = new GCircuitElement(this, new Et(n_in,n_out));
					break;
				case 1 :
					gce = new GCircuitElement(this, new Ou(n_in,n_out));
					break;
				case 2 :
					gce = new GCircuitElement(this, new Not(1,n_out));
					break;
				case 3 :
					gce = new GCircuitElement(this, new Xor(n_in,n_out));
					break;
				case 4 :
					gce = new GCircuitElement(this, new Tempo(n_in,n_out));
					break;
				case 5 :
					gce = new GCircuitElement(this, new Impulse(n_in,n_out));
					break;
				case 6 :
					gce = new GCircuitElement(this, new Cycle(n_in,n_out));
					break;
				case 7 :
					gce = new GCircuitElement(this, new Bascule(n_out));
					break;
				case 8 :
					gce = new GIn(this, new Entree());
					break;
				case 9 :
					gce = new GOut(this, new Sortie());
					break;
			}
			if(gce != null) gce.move(lastME.getX()-gce.width/2, lastME.getY()-gce.height/2); // Et on la place sous la souris
			mouseMoved(lastME);
		}else if(hoverClip != null){
			if(hoverClip instanceof GLiaison) // Si on survole une liaison, on lui indique qu'on a relache la souris
					((GLiaison) hoverClip).mouseReleased(me);
		}
		selectionning = may_selectionning = pinning = false;
		redraw(); // On redessine le canvas
	}
	
	// Recuperation des clips selectionnes lors de la selection multiple
	public void findSelectedClips(){
		try{
			for(Clip cclp : clips){
				if(cclp instanceof GLiaison) continue; // On ne selectionne pas les liaisons (pour les selectionner, il faut cliquer dessus)
				GCircuitElement clp = (GCircuitElement) cclp;
				clp.setSelected(dragRect.contains(clp.x+clp.width/2, clp.y+clp.height/2)); // Si le centre du clip est dans le rectangle, le clip est selectionne
			}
		}catch(Exception ex){}
		redraw();
	}
	
	public void mouseDragged(MouseEvent me) {
		lastME = me;
		if(pinning) mouseMoved(me);
		if(may_selectionning){ // Selection multiple possible ? Comme on drag, il s'agit bien d'une selection multiple
			selectionning = true;
			
			// Mise a jour du rectangle de selection, avec que des valeurs positives pour Rectangle.contains()
			dragPoint2 = me.getPoint();
			dragRect.setBounds(Math.min(dragPoint1.x, dragPoint2.x),
			Math.min(dragPoint1.y, dragPoint2.y),
			Math.abs(dragPoint2.x-dragPoint1.x),
			Math.abs(dragPoint2.y-dragPoint1.y));
			
			findSelectedClips();
		}else if(pinning){
			dragPoint2 = me.getPoint();
		}
		else if(hoverClip != null){
			if(hoverClip instanceof GLiaison){ // Si on survole une liaison, on la previent qu'on drag
				((GLiaison) hoverClip).mouseDragged(me);
			}else if(hoverClip instanceof GCircuitElement){ // Sinon on deplace les elements
				for(Clip clp : selectedClips)
					clp.move(clp.x + me.getX() - dragPoint2.x, clp.y + me.getY() - dragPoint2.y);
				dragPoint2 = me.getPoint();
			}
		}
		redraw(); // On repaint le tout
	}
	
	// Evenement lorsque la souris bouge
	public void mouseMoved(MouseEvent me) {
		if(me==null) return;
		lastME = me; // Sauvegarde des dernieres informations de la souris
		try{
			int i=clips.size()-1;
			Object obj = null;
			// On verifie si on clique sur la mini-map
			if(showMap && Clip.hitTest(new Rectangle(mapx, mapy, mapw, maph), me.getPoint())){
				setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
			}else{
				if(showMenu) // Ou sur le menu
					for(int u=0; u<buttonClips.size(); u++){
						if((obj=((Button) buttonClips.get(u)).getItem(me)) != null)
							break;
					}
				if(obj==null) // Si on a pas bougé sur de ces elements, alors on verifie si on a bougé sur un des clips, du premier au dernier (car le dernier dessine est au dessus des autres) 
					for(; i>=0; i--){
						if((obj=((GCircuitElement) clips.get(i)).getItem(me)) != null)
							break;
					}
			}
			
			// On met a jour le clip que l'on survole
			if(setHoverClip((Clip) obj)){
				if(pinning){ // Si on est en mode liaison, on verifie si la liaison est faisable
					if(hoverClip == null || !(hoverClip instanceof GPin)) allowedPinning = PINNING.NONE;
					else if(gpinA.pin.isOut() && ((GPin)hoverClip).pin.isOut()) allowedPinning = PINNING.NOTALLOWED;
					else allowedPinning = PINNING.ALLOWED;
				}
				redraw();
			}
			// Si on survole une liaison, on change le curseur suivant le fil que l'on veut bouger 
			if(hoverClip instanceof GLiaison){
				switch(((GLiaison)hoverClip).selectedLine){
					case 0:
					case 2:
						setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
						break;
					case 1:
						setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
						break;
					default:
						setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
						break;
				}
			}
		}catch(Exception ex){}
	}
	
	// Clip que l'on survole
	Clip hoverClip;
	public Clip getHoverClip(){ return hoverClip; }
	public boolean setHoverClip(Clip clp){
		if(isDisposed) return false;
		if(clp == hoverClip) return false;
		hoverClip = clp;
		if(hoverClip instanceof GPin) setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
		else if(hoverClip instanceof GLiaison){ // Dans mouseMoved
		}else if(hoverClip instanceof GIn || hoverClip instanceof Button) setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		else if(hoverClip instanceof GCircuitElement) setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
		else setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		return true;
	}
	
	// Clips selectionnes
	ArrayList<Clip> selectedClips = new ArrayList<Clip>();
	public boolean isSelected(Clip clp){ return selectedClips.contains(clp); }
	public boolean selectClip(Clip clp, boolean yes){
		if(isDisposed) return false;
		if(!(clp instanceof GCircuitElement))  return false;
		if(selectedClips.contains(clp) == yes) return false;
		if(!yes)	selectedClips.remove(clp);
		else		selectedClips.add(clp);
		return true;
	}
	
	// Suppression d'un clip
	public void removeClip(Clip draw) {
		if(isDisposed) return;
		selectClip(draw, false);
		if(hoverClip == draw){ // Si il etait survole, on met a jour le tout
			mouseMoved(lastME);
			hoverClip = null;
		}
		if(gpinA == draw) pinning = false;
		super.removeClip(draw);
	}
	
	// Ajout d'un clip
	public void addClip(Clip draw) {
		if(isDisposed) return;
		if(draw instanceof GLiaison) // Si il s'agit d'une liaison, on l'ajout au debut de la liste pour qu'il soit affiche en fond
			 clips.add(gliaisonCount(), draw);
		else clips.add(draw);
		redraw();
	}
	
	// Compteur de clip de liaison
	public int gliaisonCount(){
		for(int i=0; i<clips.size(); i++)
			if(!(clips.get(i) instanceof GLiaison))
				return i;
		return 0;
	}
	
	// Met un certain clip au premier plan
	public void bringMeToFront(Clip sender){
		if(isDisposed) return;
		if(!clips.contains(sender)) return;
		clips.remove(sender);
		if(sender instanceof GLiaison)
			 clips.add(gliaisonCount(), sender);
		else clips.add(sender);
	}
	
	// Effacer les clips selectionnes
	public void remSelectedClips(){
		while(selectedClips.size()>0)
			selectedClips.get(0).Dispose();
	}
	
	// Evement lors de l'appuis sur une touche
	public void keyPressed(KeyEvent ke) {
		if(pinning || selectionning) return;
		GCircuitElement gce = null;
		switch(ke.getKeyCode()){
			case KeyEvent.VK_DELETE : remSelectedClips(); break;
			case KeyEvent.VK_A :
				if(ke.isControlDown()){ selectedClips.clear(); selectedClips.addAll(clips); redraw(); }
				else gce = new GCircuitElement(this, new Et(n_in,n_out));
				break;
			case KeyEvent.VK_O :
				gce = new GCircuitElement(this, new Ou(n_in,n_out));
				break;
			case KeyEvent.VK_X :
				gce = new GCircuitElement(this, new Xor(n_in,n_out));
				break;
			case KeyEvent.VK_N :
				gce = new GCircuitElement(this, new Not(1,n_out));
				break;
			case KeyEvent.VK_I :
				gce = new GCircuitElement(this, new Impulse(n_in,n_out));
				break;
			case KeyEvent.VK_T :
				gce = new GCircuitElement(this, new Tempo(n_in,n_out));
				break;
			case KeyEvent.VK_C :
				gce = new GCircuitElement(this, new Cycle(n_in,n_out));
				break;
			case KeyEvent.VK_B :
				gce = new GCircuitElement(this, new Bascule(n_out));
				break;
			case KeyEvent.VK_Q :
				gce = new GIn(this, new Entree());
				break;
			case KeyEvent.VK_S :
				gce = new GOut(this, new Sortie());
				break;
			case KeyEvent.VK_F1 :
				if(ke.isControlDown())	n_out = 1;
				else					n_in  = 1;
				break;
			case KeyEvent.VK_F2 :
				if(ke.isControlDown())	n_out = 2;
				else					n_in  = 2;
				break;
			case KeyEvent.VK_F3 :
				if(ke.isControlDown())	n_out = 3;
				else					n_in  = 3;
				break;
			case KeyEvent.VK_F4 :
				if(ke.isControlDown())	n_out = 4;
				else					n_in  = 4;
				break;
			case KeyEvent.VK_F5 :
				if(ke.isControlDown())	n_out = 5;
				else					n_in  = 5;
				break;
			case KeyEvent.VK_F6 :
				if(ke.isControlDown())	n_out = 6;
				else					n_in  = 6;
				break;
			case KeyEvent.VK_F7 :
				if(ke.isControlDown())	n_out = 7;
				else					n_in  = 7;
				break;
			case KeyEvent.VK_F8 :
				if(ke.isControlDown())	n_out = 8;
				else					n_in  = 8;
				break;
			case KeyEvent.VK_F9 :
				if(ke.isControlDown())	n_out = 9;
				else					n_in  = 9;
				break;
			case KeyEvent.VK_F10 :
				if(ke.isControlDown())	n_out = 10;
				else					n_in  = 10;
				break;
			case KeyEvent.VK_SPACE :
				for(Clip clp : selectedClips)
					if(clp instanceof GIn) ((GIn)clp).switchOnOff();
				break;
			case KeyEvent.VK_1 :
				addBascule();
				break;
			case KeyEvent.VK_M :
				showHideMenu();
				break;
			case KeyEvent.VK_P :
				showHideMap();
				break;
			case KeyEvent.VK_ESCAPE :
				selectButton(null, false);
				break;
			case KeyEvent.VK_D :
			case KeyEvent.VK_TAB : // TAB = D, suivant où l'applet se trouve, TAB est consumé avant d'arriver ici
				{
					if(clips.size()==0) break;
					int i=0;
					for(i=0; i<clips.size(); i++)
						if(selectedClips.contains(clips.get(i))) break;
					selectedClips.clear();
					if(ke.isShiftDown()){
						if(i>0) selectedClips.add(clips.get(i-1));
						else selectedClips.add(clips.get(clips.size()-1));
					}else{
						if(i<clips.size()-1) selectedClips.add(clips.get(i+1));
						else selectedClips.add(clips.get(0));
					}
					redraw();
				}
				break;
			case KeyEvent.VK_F :
				{
					if(clips.size()==0) break;
					int i=0, last=-1;
					for(i=0; i<clips.size(); i++)
						if(clips.get(i) instanceof GIn){
							if(selectedClips.contains(clips.get(i))) break;
							last = i;
						}
					selectedClips.clear();
					if(ke.isShiftDown()){
						if(last == -1)
							for(i=clips.size()-1; i>=0; i--)
								if(clips.get(i) instanceof GIn){
									last = i;
									break;
								}
						selectedClips.add(clips.get(last));
					}else{
						for(++i; i<clips.size(); i++)
							if(clips.get(i) instanceof GIn){
								selectedClips.add(clips.get(i));
								break;
							}
						if(selectedClips.size() == 0){
							for(i=0; i<clips.size(); i++)
								if(clips.get(i) instanceof GIn){
									selectedClips.add(clips.get(i));
									break;
								}
						}
					}
					redraw();
				}
				break;
		}
		if(gce != null) gce.move(lastME.getX()-gce.width/2, lastME.getY()-gce.height/2);
		mouseMoved(lastME);
	}

	// Ajouter de quoi faire une bascule avec des portes ET et NON
	void addBascule(){
		if(isDisposed) return;
		GCircuitElement g1 = new GCircuitElement(this, new Not(1, 1));
		GCircuitElement g2 = new GCircuitElement(this, new Not(1, 1));
		GCircuitElement g3 = new GCircuitElement(this, new Not(1, 1));
		GCircuitElement g4 = new GCircuitElement(this, new Not(1, 1));
		GCircuitElement g5 = new GCircuitElement(this, new Et(2, 1));
		GCircuitElement g6 = new GCircuitElement(this, new Et(2, 1));
		try {
			new GLiaison(g1.gpins.get(1), g5.gpins.get(0));
			new GLiaison(g2.gpins.get(1), g6.gpins.get(1));
			new GLiaison(g5.gpins.get(2), g3.gpins.get(0));
			new GLiaison(g6.gpins.get(2), g4.gpins.get(0));
			new GLiaison(g4.gpins.get(1), g5.gpins.get(1));
			new GLiaison(g3.gpins.get(1), g6.gpins.get(0));
		} catch (Exception e) {}
		g1.move(140, 130);
		g2.move(140, 200);
		g3.move(600, 65);
		g4.move(600, 265);
		g5.move(350, 50);
		g6.move(350, 250);
	}
	
	// Afficher/Cacher la mini-map
	boolean showMap = true;
	public void showHideMap(){
		showMap = !showMap;
		redraw();
	}
	
	// Afficher/Cacher le menu
	boolean showMenu = true;
	public void showHideMenu(){
		showMenu = !showMenu;
		redraw();
	}
	
	// Ajout d'un bouton au menu
	int xb=50, yb=50;
	Button selectedButton;
	public void addButton(String text){
		buttonClips.add(new Button(this, text, xb, yb, 150, 20));
		yb += 30;
	}
	// Selectionner un bouton
	public void selectButton(Button but, boolean yes){
		if(selectedButton != null) selectedButton.select(false);
		selectedButton = yes?but:null;		
		if(selectedButton != null) selectedButton.select(true);
	}
}
