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:
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:
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:
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:
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:
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.
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.
Imaginemos a seguinte imagem:
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:
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…
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?
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…
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 é 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!
O raciocínio passará a ser então:
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.
Desta forma, o nosso menu já não sofre de problemas de reutilização nem de refactoring:
É 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!
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.
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:
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.