DevSecOps

31 mar, 2008

Disparando um evento customizado

Publicidade

Eventos ocorrem o tempo todo em ActionScript, como vimos ao longo de todos os artigos. Estes ocorrem em resposta a um clique de usuário, ao adicionar um objeto em uma display list, ao mover o mouse, ao finalizar um preloader de arquivo externo, etc. Eles são categorizados como built-in events porque já foram definidos pelo próprio Flash Player.

Nós, como programadores, também possuímos a capacidade de criar novos eventos, bem como disparar eventos já construídos no Flash Player para que possamos estender as funcionalidades de nossa aplicação, para assim utilizar de maneira apropriada os conceitos da orientação a objeto em ActionScript 3.0.

Todos os eventos nesta linguagem são definidos de modo padrão:

obj.addEventListener(ClasseDoEvento.EVENTO, listener);

A arquitetura de eventos no ActionScript 3 é baseada no W3C Document Object Model (DOM) Level 3 Events Specification, disponível na url http://www.w3.org/TR/DOM-Level-3-Events.

Não esqueça que, sempre que desejar remover um evento, você deve utilizar:

obj.removeEventListener(ClasseDoEvento.EVENTO, listener);

Acessando o objeto via propriedade target

Dentro de um listener, a função que é determinada a ser executada quando o evento acontece, existem propriedades que o evento trás consigo como, por exemplo, a propriedade type, que indica o tipo do evento, a constante MouseEvent.CLICK retorna a string “click”. Existe uma outra propriedade, a propriedade target, que retorna o objeto que está executando a ação, que nem sempre é o objeto que tem o listener cadastrado. No exemplo abaixo, quando clicamos no objeto azul, este é rotacionado em 45 graus, independente do listener estar cadastrado ao objeto inteiro, no caso o quadro negro que contém o quadro azul:

import flash.display.Sprite;
import flash.events.MouseEvent;

var quadro:Sprite = new Sprite();
quadro.graphics.beginFill(0x000000);
quadro.graphics.drawRect(0, 0, 100, 30);
quadro.graphics.endFill();

var quadroInterno:Sprite = new Sprite();
quadroInterno.graphics.beginFill(0x0000FF);
quadroInterno.graphics.drawRect(0, 0, 50, 30);
quadroInterno.graphics.endFill();

addChild(quadro);
quadro.addChild(quadroInterno);

quadro.x = quadro.y = 200;

quadro.addEventListener(MouseEvent.CLICK, onClick);

function onClick(e:MouseEvent):void {
	e.target.rotation = 45;
}

Acessando o objeto via propriedade currentTarget

Para acessar o objeto que estamos registrando ao listener devemos usar outra propriedade, a propriedade currentTarget. O mesmo exemplo anterior seguirá abaixo, mas repare que agora, independentemente de se clicar no objeto azul, sempre será disparado o evento para o objeto inteiro, no caso o quadro:

import flash.display.Sprite;
import flash.events.MouseEvent;

var quadro:Sprite = new Sprite();
quadro.graphics.beginFill(0x000000);
quadro.graphics.drawRect(0, 0, 100, 30);
quadro.graphics.endFill();

var quadroInterno:Sprite = new Sprite();
quadroInterno.graphics.beginFill(0x0000FF);
quadroInterno.graphics.drawRect(0, 0, 50, 30);
quadroInterno.graphics.endFill();

addChild(quadro);
quadro.addChild(quadroInterno);

quadro.x = quadro.y = 200;

quadro.addEventListener(MouseEvent.CLICK, onClick);

function onClick(e:MouseEvent):void {
	e.currentTarget.rotation = 45;
}

Custom Event

Para disparar um evento personalizado, precisamos que nossa classe tenha herança com a classe EventDispatcher de alguma forma. No exemplo abaixo vamos fazer com que a classe Botão tenha dois eventos personalizados, Botão.CLICADO e Botão.ADICIONADO_NO_STAGE:

//Classe Botao

package com.leandroamano.layout {
	
	import flash.display.Sprite;
	import flash.display.GradientType;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	public class Botao extends Sprite{
		
		public static const CLICADO = "clicado";
		public static const ADICIONADO_NO_STAGE = "adicionado na display list";
		
		public function Botao() {
			graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x0000FF], [100, 100], [0x00, 0xFF]);
			graphics.drawRect(-50, 0, 100, 30);
			graphics.endFill();
			
			buttonMode = true;
			
			addEventListener(MouseEvent.CLICK, clickHandler);
			addEventListener(Event.ADDED_TO_STAGE, addHandler);
		}
		
		private function clickHandler(e:MouseEvent):void {
			dispatchEvent(new MouseEvent(Botao.CLICADO));
		}
		private function addHandler(e:Event):void {
			dispatchEvent(new Event(Botao.ADICIONADO_NO_STAGE));
		}
	}
}

No arquivo de teste:

import com.leandroamano.layout.Botao;
import flash.events.Event;

var meuBotao:Botao = new Botao();
meuBotao.x = meuBotao.y =200;

meuBotao.addEventListener(Botao.CLICADO, aoClicar);
meuBotao.addEventListener(Botao.ADICIONADO_NO_STAGE, aoAdicionar);

addChild(meuBotao);

function aoClicar(e:Event):void {
	trace("tipo:", e.type);//tipo: clicado
	trace("alvo:", e.currentTarget, "\n");//alvo: [object Botao]
}
function aoAdicionar(e:Event):void {
	trace("tipo:", e.type);//tipo: adicionado na display list
	trace("alvo:", e.currentTarget, "\n");//alvo: [object Botao] 
}

Estendendo uma classe de evento

Neste exemplo entenderemos de maneira simplória como fazer com que os eventos fiquem separados da classe Botão.

//Classe BotaoEvent

package com.leandroamano.events {
	
	import flash.events.Event;
	
	public class BotaoEvent extends Event {
		
		public static const ADICIONADO_NO_STAGE = "adicionado na display list";
		
		public function BotaoEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) {
			super(type, bubbles, cancelable);
		}
	}
}

//Classe BotaoMouseEvent

package com.leandroamano.events {
	
	import flash.events.MouseEvent;
	
	public class BotaoMouseEvent extends MouseEvent {
		
		public static const CLICADO = "clicado";
		
		public function BotaoMouseEvent(type:String, bubbles:Boolean = true, cancelable:Boolean = false) {
			super(type, bubbles, cancelable);
		}
	}
}

//Classe BotaoSeparado

package com.leandroamano.layout {
	
	import flash.display.Sprite;
	import flash.display.GradientType;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import com.leandroamano.events.BotaoEvent;
	import com.leandroamano.events.BotaoMouseEvent;
	
	public class BotaoSeparado extends Sprite{
		
		public static const CLICADO = "clicado";
		public static const ADICIONADO_NO_STAGE = "adicionado na display list";
		
		public function BotaoSeparado() {
			graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x0000FF], [100, 100], [0x00, 0xFF]);
			graphics.drawRect(-50, 0, 100, 30);
			graphics.endFill();
			
			buttonMode = true;
			
			addEventListener(MouseEvent.CLICK, clickHandler);
			addEventListener(Event.ADDED_TO_STAGE, addHandler);
		}
		
		private function clickHandler(e:MouseEvent):void {
			dispatchEvent(new BotaoMouseEvent(BotaoMouseEvent.CLICADO));
		}
		private function addHandler(e:Event):void {
			dispatchEvent(new BotaoEvent(BotaoEvent.ADICIONADO_NO_STAGE));
		}
	}
}

No arquivo de teste:

import com.leandroamano.layout.BotaoSeparado;
import com.leandroamano.events.BotaoEvent;
import com.leandroamano.events.BotaoMouseEvent;

var meuBotao:BotaoSeparado = new BotaoSeparado();
meuBotao.x = meuBotao.y =200;

meuBotao.addEventListener(BotaoMouseEvent.CLICADO, aoClicar);
meuBotao.addEventListener(BotaoEvent.ADICIONADO_NO_STAGE, aoAdicionar);

addChild(meuBotao);

function aoClicar(e:BotaoMouseEvent):void {
	trace("tipo:", e.type);//tipo: clicado
	trace("alvo:", e.currentTarget, "\n");//alvo: [object BotaoSeparado]
}
function aoAdicionar(e:BotaoEvent):void {
	trace("tipo:", e.type);//tipo: adicionado na display list
	trace("alvo:", e.currentTarget, "\n");//alvo: [object BotaoSeparado] 
}

Um dispatchEvent não precisa estar necessariamente dentro de uma função utilizada como listener. Podemos também (é o que fazemos na maioria das vezes) dispará-las dentro de uma função qualquer.