Apr
29

XML e E4X em Actionscript 3.0 - part 1

Acabei de deixar no meu Blog, um tutorial sobre XML e E4X em Actionscript 3.0 que gostaria de partilhar com a comunidade, pelo que para quem tiver interessado poderá visualizar aqui:

XML e E4X em AS3




Mar
26

Menu ao estilo do MacOS

Ontem durante uma das minhas aulas surgiu a necessidade de se desenvolver um menu ao estilo do MacOS. Apesar de não ter perdido muito tempo a aperfeiçoá-lo, o resultado final ficou engraçado, pelo que partilho o código fonte convosco. Antes de mais, o resultado final:

Experimentem a clicar nos ícones. O menu pode ser usado tanto no Flash CS3 como no Flex.

Para usarem o menu nos vossos projectos, basta que:

  1. Coloquem na pasta do vosso projecto o ficheiro MacMenu.as;
  2. Coloquem no stage os ícones que pretendem que façam parte do menu. Tenham o cuidado de centrar as imagens no ponto 0,0 por causa do zoom;
  3. Façam o seguinte código:
var listaDeIcones:Array=[m1, m2, m3, m4, m5, m6];

var menu:MacMenu = new MacMenu(listaDeIcones);

addChild(menu); // Por causa do enterFrame. Preferia evitar esta solução, mas por agora…

Onde m1, m2, m3, etc, são o nome das instâncias dos vossos ícones.

O menu possui três parâmetros de configuração:

  • ratio: define a distância de reacção ao rato. Quanto menor o número, mais próximo precisa o rato de estar para que os ícones reajam. Exemplo: menu.ratio= 130;
  • escala_maxima: define o zoom máximo que os ícones terão. Exemplo: menu.escala_maxima=1.2;
  • escala_minima: define o zoom mínimo que os ícones terão. Exemplo: menu.escala_minima=0.5;

Decidi separar o código de reacção aos cliques retirando-o da classe MacMenu, isto porque podem querer criar as vossas próprias reacções aos cliques. Se no entanto quiserem usar as do exemplo acima (no clique, o ícone fica com um brilho e começa aos saltos), precisarão da classe GlowReactor e da pasta caurina:

  1. Copiar para o vosso projecto a pasta caurina;
  2. Copiar para o vosso projecto o ficheiro GlowReactor.as;
  3. Fazer o seguinte código:
new GlowReactor(listaDeIcones);

Algumas das práticas usadas no exemplo são discutíveis, mas recordem-se que foi feito em meia hora com fins educativos. Ainda assim, espero que vos agrade e seja útil.

O código fonte pode ser descarregado daqui.




Mar
11

Best Practices #1 - A morte do parent.parent.parent: criação de componentes fracamente acoplados

Pretendo com este post iniciar uma série de posts de best-practices de desenvolvimento em Actionscript 3.

Começo com um dos maiores erros que costumo ver, especialmente em antigos programadores Actionscript 2: a amaldiçoada utilização do parent (o antigo _parent) ou do stage (o antigo _root).
Este post aplica-se tanto a Flash CS3 como a Flex. O código está puramente em Actionscript 3, mas o raciocínio é exactamente o mesmo para MXML.

O caso

Imaginemos a seguinte imagem:

menu.jpg

Temos o Stage. Dentro do Stage, temos um menu e duas secções: seccaoA e seccaoB. Dentro do menu temos dois botões: opcaoA e opcaoB. Ou seja:

  • Stage
  • Stage.menu
  • Stage.menu.opcaoA
  • Stage.menu.opcaoB
  • Stage.seccaoA
  • Stage.seccaoB

Queremos que quando o utilizador clique na opcaoA, a seccaoA seja mostrada, e que aconteça o mesmo para a opcaoB e seccaoB.

O código, para os adeptos do “parent”, parece óbvio:

(Dentro do Menu):

// Construtor
public function Menu()
{
opcaoA.addEventListener(MouseEvent.CLICK, opcaoAClickHandler);
opcaoB.addEventListener(MouseEvent.CLICK, opcaoBClickHandler);
}

function opcaoAClickHander(ev:MouseEvent):void
{
parent.seccaoA.visible=true;
parent.seccaoB.visible=false;
}

function opcaoBClickHander(ev:MouseEvent):void
{
parent.seccaoA.visible=false;
parent.seccaoB.visible=true;
}

Aparentemente isto resolveria o problema de uma assentada só. Porém…

Os problemas do parent

Infelizmente está 100% incorrecto utilizar o parent. A regra é simples: é *proibido* usá-lo. Surgiu um problema que obriga à utilização do parent? Repense! Leia este post, e veja como se resolve.
E obviamente perguntará: porque é que está incorrecto?

Problema 1: Reutilização

O seu menu está um espectáculo: é um dos preferidos na sua empresa tanto que o quer utilizar em vários projectos.

Entretanto aparece um novo projecto onde vai usar o menu. Porém foi outro elemento da equipa que fez a seccaoA e seccaoB, mas…. deu-lhes outros nomes. Chamou-lhes “seccao1″ e “seccao2″. E agora, que faz?

Primeira opção: mudar os nomes dados pelo seu colega (seccao1 e seccao2) para seccaoA e seccaoB. Big mistake: infelizmente o outro elemento da equipa tinha feito imenso código que usava intensivamente os nomes “seccao1″ e “seccao2″. E agora vai fazer o quê? Mexer no código dele? Não me parece…

Segunda opção: mudar no seu código onde está parent.seccaoA para parent.seccao1. Parece uma boa ideia dado o exemplo que fizemos aqui, mas se se tratasse um menu altamente complexo que usasse imensas vezes “parent.seccaoA”, seria lógico (e rápido) estar a mudar em todo o lado para seccao1 ?

Ok, é teimoso e estaria disposto a mudar o seu código todo… Porém, ao fazer isto, em vez de ter um menu que está a reutilizar entre projectos, na realidade acaba por estar a criar vários menus diferentes. Isto porque para cada projecto terá que mudar o código de cada menu de acordo com os nomes das secções. Ou seja, no fundo é um menu diferente com código diferente por projecto…

Problema 2: Refactoring

O seu projecto está feito e parece terminado. Porém, agora aparece o chefe a dizer “Ah e tal, vocês fizeram isto mal. Não quero a seccaoA dentro do Stage, mas sim dentro de um MovieClip chamado SectionContainer que tem uma borda e uns efeitos giros”. E lá vão vocês criar o SectionContainer, e colocar as secções lá dentro. Entretanto compilam e… Erro!

O código antigo do menu referia-se a parent.seccaoA. Porém, com a alteração, a seccaoA neste momento pode ser acedida assim: parent.sectionContainer.seccaoA. E com isto lá ter que ir mudar o seu código (e rezar para que o menu não seja complexo ao ponto de ter que mudar 23423423 linhas…).

A solução: componentes fracamente acoplados

A solução é relativamente simples, e passa por se cumprir uma regra também ela simples:

« Um componente/”MovieClip” nunca pode saber nada sobre quem o usa. Um componente/”MovieClip” só é responsável por si próprio »

Por outras palavras, se dentro do Menu está a fazer “parent.seccaoA”, quer dizer que o menu sabe que existe uma secção fora de si chamada seccaoA - sabe mais do que deveria saber.

Então como posso fazer: “quanto se clica na opcaoA, quero mostrar a seccaoA” se o menu não pode saber que há uma seccaoA ? Ora, o menu não tem que mudar para a seccaoA mas sim avisar quem o está a usar que está na altura de mudar para a seccaoA. Avisar como? Através de eventos!

Lançar e apanhar os eventos

O raciocínio passará a ser então:

  1. O utilizador clica no botão, o que despoleta um click e respectiva chamada da função opcaoAClickHander
  2. O opcaoAClickHandler deverá avisar o componente externo que está na altura de mudar para a seccaoA, lançando um evento chamado por exemplo “opcaoAClick”
  3. O Stage deverá estar a escutar eventos do tipo “opcaoAClick”, e quando os apanha chama a função menuOpcaoAClickHandler
  4. O menuOpcaoAClickHandler deverá conter o código necessário para mostrar a secção correspondente e esconder as outras.

Assim, o código correspondente:

(Dentro do Menu):

// Construtor
public function Menu()
{
opcaoA.addEventListener(MouseEvent.CLICK, opcaoAClickHandler);
opcaoB.addEventListener(MouseEvent.CLICK, opcaoBClickHandler);
}

function opcaoAClickHander(ev:MouseEvent):void
{
dispatchEvent(new Event("opcaoAClick"));
}

function opcaoBClickHander(ev:MouseEvent):void
{
dispatchEvent(new Event("opcaoBClick"));
}

(Dentro do Stage, que está associado a uma classe chamada Index):

// Construtor
public function Index()
{
menu.addEventListener("opcaoAClick", menuOpcaoAClickHandler);
menu.addEventListener("opcaoBClick", menuOpcaoBClickHandler);
}

function menuOpcaoAClickHandler(ev:MouseEvent):void
{
seccaoA.visible=true;
seccaoB.visible=false;
}

function menuOpcaoBClickHandler(ev:MouseEvent):void
{
seccaoA.visible=false;
seccaoB.visible=true;
}

Ou seja, se só o Stage é que sabe que existem secções, só o Stage é que pode mudar de secções. Então o menu simplesmente lança um aviso “olha, está na altura de mudar para a seccaoA”. O Stage apanha o aviso, e faz então o que é necessário para mostrar a secção correspondente.

Mais correcto ainda, seria criar um Custom Event, que possuiria uma String como propriedade pública onde seria colocado o nome da secção. Porém, isso fica para uma posterior lição.

Conclusões

  • Qualquer componente ou MovieClip nunca pode saber *nada* sobre quem o está a usar.
  • Não usar o parent.
  • Não usar o parent.
  • Não usar o parent.
  • Sempre que surge um caso de “aqui ficava mesmo bem um parent”, usamos o dispatchEvent como descrito acima.

Desta forma, o nosso menu já não sofre de problemas de reutilização nem de refactoring:

  • se quisermos usar o menu noutro projecto, é só colocá-lo noutro projecto: não é preciso mudar o código do menu, pois este é completamente independente do projecto onde é usado;
  • se o projecto sofrer alterações de estrutura, é só alterar o projecto sem mexermos no menu: não é preciso mudar o código do menu, pois este é completamente independente do projecto onde é usado.

É de realçar que este raciocínio não deve ser aplicado só a menus, mas a TUDO. Vai usar o parent? Esqueça. Use o dispatchEvent!




Feb
21

Material das apresentações do Portugal Flex Camp

Está finalmente reunido o material usado nas apresentações do Portugal Flex Camp. Deixo-vos abaixo os links:

Vou ver ainda se consigo que me entreguem os vídeos das apresentações, embora não saiba se será possível.




Feb
20

Portugal Flex Camp - Slides da apresentação de integração de Flex com PHP usando AMFPHP

E assim se passou o primeiro Portugal Flex Camp! - Sim, a esta hora devia estar a dormir, mas é impossível deitar-me sem fazer um post..

Na minha opinião, e considerando que foi a primeira vez que se fez este evento em Portugal, foi um sucesso tanto pela qualidade da generalidade das apresentações, como pelo facto de termos tido a sala completamente cheia. Gostei especialmente da apresentação do Serge Jespers, embora a do Enrique Duvos não tenha ficado atrás.

Vou tentar reunir as apresentações aqui no riapt, e ver se consigo que o ISCTE nos disponibilize os vídeos em formato digital.

Entretanto deixo-vos aqui a minha apresentação em PDF, e o source code respectivo. Falo da apresentação sobre integração de Flex com PHP através de AMFPHP.

Aproveito para agradecer:

  • A todos os presentes;
  • Ao ISCTE, cuja organização foi impecável;
  • À Adobe Portugal e internacional, em especial à Sumi Lim, Enrique Duvos e Serge Jesper
  • Ao Kim Hansen pelo apoio (dude, on the next event you have to make a presentation!)

Para aqueles que me pediram um cartão e não o receberam (desde Dezembro que esgotei os cartões, e ainda não tive tempo para mandar fazer novos..), deixo aqui os meus contactos:

mail: joao [dot] saleiro [at] webfuel [dot] pt
skype: joao.saleiro

E para quem me quiser “seguir” no twitter, o meu twitter é joaosaleiro (http://twitter.com/joaosaleiro).

Gostaria ainda de saber a opinião dos presentes relativamente tanto ao evento em geral, como à minha apresentação em específico. Podem fazê-lo enviando mail para a mailing list, ou deixando um comentário neste post. Não tenham medo de fazer críticas - o objectivo é aprender com o que foi feito de bem, e corrigir num próximo evento aquilo que não correu tão bem.

top