Dans ce tutoriel, nous allons voir comment développer une classe permettant de créer une fenêtre disposant d'un bouton de fermeture et du système de Drag and Drop.

La partie graphique

Pour commencer, notre classe a besoin de plusieurs paramètres, tel
que son parent, sa couleur, ou encore son contenu.

Voici la signature de notre classe :

public function PopUp(_parent:Stage, _color:uint, content:MovieClip):void

Dans le constructeur, nous instancions les différentes parties de notre fenêtre, puis nous dessinons le cadre et l'entête.

/**
 * Dessine les contours et la croix
 */
private function drawPopUp(content:MovieClip):void {
    // constante pour la hauteur du header
    var header_height : Number = 16;
			
    /**
     * création du dégradé pour faire joli ;)
     */
    var h : Shape = new Shape();
    h.graphics.lineStyle(2, _color); // bordures
			
    // Matrice de transformation du dégradé
    var matrice:Matrix = new Matrix();
    matrice.createGradientBox(_min_width, header_height);
			
    h.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x95B8E3], [1, 1], [0, 255], matrice);
    h.graphics.drawRect(0, 0, _min_width + 4, header_height);
			
    h.graphics.endFill();
			
    _header_mv.addChild(h);
			
    /**
     * création de la croix
     */
    var cross_size : Number = 11; // constante : taille de la croix
			
    _cross_mv = new Sprite();
    _cross_mv.buttonMode = true;
    _cross_mv.x = _min_width - cross_size;
    _cross_mv.y = 2;
			
    // dessin du contour
    var c : Shape = new Shape();
    c.graphics.beginFill(0x000000);
    c.graphics.drawRect(0,0,cross_size,cross_size);
    c.graphics.endFill();
			
    // dessin de la croix
    var sh_c : Shape = new Shape();
    sh_c.graphics.beginFill(0xFFFFFF, 0);
    sh_c.graphics.lineStyle(2, 0xFFFFFF);
    sh_c.graphics.moveTo(2,2);
    sh_c.graphics.lineTo(9,9);
    sh_c.graphics.moveTo(2,9);
    sh_c.graphics.lineTo(9,2);
    sh_c.graphics.endFill();
			
    _cross_mv.addChild(c);
    _cross_mv.addChild(sh_c);
    _cross_mv.addEventListener(MouseEvent.CLICK, deletePopUp);
			
    _header_mv.addChild(_cross_mv);
			
    /**
     * Création du body
     */
    _body_mv.y = header_height;
			
    var contour : Shape = new Shape();
    contour.graphics.beginFill(0xFFFFFF);
    contour.graphics.lineStyle(2, _color); // bordures
    contour.graphics.drawRect(0,0, _min_width + 4, _min_height+4);
    contour.graphics.endFill();
			
    _body_mv.addChild(contour);
			
    content.x = 2;
    content.y = 2;
    _body_mv.addChild(content);
}

Le squelette de notre fenetre est a present créé.


Le système Drag and Drop

Le système de Drag and Drop (ou de "glisser - déposer") nécessite trois écouteurs sur les évènements de la souris :

// Création des écouteurs pour le drag&drop
_header_mv.addEventListener(MouseEvent.MOUSE_DOWN, drag);
_header_mv.addEventListener(MouseEvent.MOUSE_UP, drop);

// Pour éviter les erreurs si le popup est bougé trop vite
_root_mv.addEventListener(MouseEvent.MOUSE_UP, drop);

A présent, nous allons utiliser les méthodes : startDrag() et stopDrag() de la classe Sprite.
stratDrag() permet de faire glisser un sprite jusqu'à l'arrêt explicite de celui-ci en utilisant stopDrag().

private function drag(e:MouseEvent):void {
	startDrag();
	_isDragging = true;
}
		
private function drop(e:MouseEvent):void {
	// on arrête le déplacement seulement s'il a déjà commencé
	if(_isDragging) stopDrag();
}

Aller plus loin

Plusieurs ajouts pourraient être fait, principalement l'action sur la croix de fermeture :

/**
 * Fonction de suppression du popup
 */
public function deletePopUp(e:MouseEvent=null):void {
	// destruction des listeners
	_cross_mv.removeEventListener(MouseEvent.CLICK, deletePopUp);
	_header_mv.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
	_header_mv.removeEventListener(MouseEvent.MOUSE_UP, drop);
	_root_mv.removeEventListener(MouseEvent.MOUSE_UP, drop);
			
	// suppression du popup dans la display list
	_root_mv.removeChild(this);
			
	// on envoi un évènement, si jamais on a besoin de faire des actions supplémentaires
	dispatchEvent(new Event(PopUp.DELETE));
}

Nous pourrions également passer en paramètre la taille souhaitée, ou encore la couleur du dégradé.
De par sa portabilité, tout est envisageable.


Demo et code


Votre lecteur Flash n'est pas à jour. Installer la dernière version


Voici le code complet de la classe :

package com.revolugame.as3.ui {

	/**
	 * Classe permettant de créer une fenetre disposant d'un bouton de fermeture et du systeme drag&drop
	 * @author : Adrien
	 * @version : 0.1
	 */

	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.MovieClip;
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.display.GradientType;
	import flash.media.Video;
	
	import flash.geom.Matrix;
	
	import flash.events.Event;
	import flash.events.MouseEvent;

	public class PopUp extends Sprite {
	
		/**
		 * Objet d'affichage parent
		 */
		private var _root_mv : Stage; // remplacer par un DisplayObject
		
		/**
		 * Sprite du header. C'est sur ce sprite que sera l'ecouteur du drag&drop
		 */
		private var _header_mv : Sprite;
		
		/**
		 * Sprite cliquable, dedans viendra se coller le shape du dessin de la croix
		 */
		private var _cross_mv : Sprite;
		
		/**
		 * Sprite dans lequel sera le texte. Il dispose seulement des décorations (selon le param color)
		 */
		private var _body_mv : Sprite;
		
		/**
		 * Sprite accueillant le contenu de la fenetre
		 */
		private var _content_mv : Sprite;
		
		/**
		 * Couleur des bordures
		 */
		private var _color : uint;
		
		/**
		 * Largeur min de la fenetre
		 */
		private var _min_width : Number;
		
		/**
		 * Hauteur min de la fenetre
		 */
		private var _min_height : Number;
		
		/**
		 * variable de gestion du drag&drop
		 */
		private var _isDragging : Boolean = false;
		
		public static const DELETE : String = "delete";
		
		/**
		 * Constructeur s'occupant de la création des deux sprites principaux
		 * @params 	_parent : DisplayObject parent du popup
		 * 		_width : largeur du popup
		 *		_height : hauteur du popup
		 *		_color : couleur des bordure
		 */
		public function PopUp(parent:Stage, color:uint, content:MovieClip):void {
			super();
			initDisplay(); // initialisation de l'affichage
			drawPopUp(content); // dessin du squelette
			initListener(); // initialisation des écouteurs
		}
		
		private function initDisplay():void {
			_root_mv = parent;
			_color = color;
			_min_height = content.height;
			_min_width = content.width;
			
			_root_mv.addChild(this);
			
			_header_mv = new Sprite();
			addChild(_header_mv);
			
			_body_mv = new Sprite();
			addChild(_body_mv);
		}
		
		private function initListener():void {
			// Création des écouteurs pour le drag&drop
			_header_mv.addEventListener(MouseEvent.MOUSE_DOWN, drag);
			_header_mv.addEventListener(MouseEvent.MOUSE_UP, drop);
			// pour eviter les erreurs si le popup est bougé trop vite
			_root_mv.addEventListener(MouseEvent.MOUSE_UP, drop);
		}
		
		/**
		 * Dessine les contours et la croix
		 */
		private function drawPopUp(content:MovieClip):void {
			// constante pour la hauteur du header
			var header_height : Number = 16;
			
			/**
			 * creation du dégradé
			 */
			var h : Shape = new Shape();
			h.graphics.lineStyle(2, _color); // bordures
			
			// Matrice de transformation du dégradé
			var matrice:Matrix = new Matrix();
			matrice.createGradientBox(_min_width, header_height);
			
			h.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x95B8E3], [1, 1], [0, 255], matrice);
			h.graphics.drawRect(0, 0, _min_width + 4, header_height);
			
			h.graphics.endFill();
			
			_header_mv.addChild(h);
			
			/**
			 * création de la croix
			 */
			var cross_size : Number = 11; // cst : taille de la croix
			
			_cross_mv = new Sprite();
			_cross_mv.buttonMode = true;
			_cross_mv.x = _min_width - cross_size;
			_cross_mv.y = 2;
			
			// dessin du contour
			var c : Shape = new Shape();
			c.graphics.beginFill(0x000000);
			c.graphics.drawRect(0,0,cross_size,cross_size);
			c.graphics.endFill();
			
			// dessin de la croix
			var sh_c : Shape = new Shape();
			sh_c.graphics.beginFill(0xFFFFFF, 0);
			sh_c.graphics.lineStyle(2, 0xFFFFFF);
			sh_c.graphics.moveTo(2,2);
			sh_c.graphics.lineTo(9,9);
			sh_c.graphics.moveTo(2,9);
			sh_c.graphics.lineTo(9,2);
			sh_c.graphics.endFill();
			
			_cross_mv.addChild(c);
			_cross_mv.addChild(sh_c);
			_cross_mv.addEventListener(MouseEvent.CLICK, deletePopUp);
			
			_header_mv.addChild(_cross_mv);
			
			/**
			 * Création du body
			 */
			_body_mv.y = header_height;
			
			var contour : Shape = new Shape();
			contour.graphics.beginFill(0xFFFFFF);
			contour.graphics.lineStyle(2, _color); // bordures
			contour.graphics.drawRect(0,0, _min_width + 4, _min_height+4);
			contour.graphics.endFill();
			
			_body_mv.addChild(contour);
			
			content.x = 2;
			content.y = 2;
			_body_mv.addChild(content);
		}
		
		/**
		 * Fonction de suppression du popup
		 */
		public function deletePopUp(e:MouseEvent=null):void {
			// destruction des listeners
			_cross_mv.removeEventListener(MouseEvent.CLICK, deletePopUp);
			_header_mv.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
			_header_mv.removeEventListener(MouseEvent.MOUSE_UP, drop);
			_root_mv.removeEventListener(MouseEvent.MOUSE_UP, drop);
			
			// suppression du popup dans la display list
			_root_mv.removeChild(this);
			
			// on envoi un evenement, si jamais on a besoin de faire des actions supplémentaires
			dispatchEvent(new Event(PopUp.DELETE));
		}
		
		private function drag(e:MouseEvent):void {
			startDrag();
			_isDragging = true;
		}
		
		private function drop(e:MouseEvent):void {
			// on arrete le deplacement que s'il a deja commencé
			if(_isDragging) stopDrag();
		}
		
	}
	
}