Arquivo

Arquivo do autor

Flash Builder, Catalyst e Flex 4 SDK disponíveis para downloads

2, junho, 2009 admin Sem comentários

Salve pessoal,

Ontem dia 01/06 foi finalmente lançado para download as novas versões do Flas Builder (Antigo Flex Builder), Catalyst e SDK.
Link de Download.
Link de documentação das novidades da versão Flash Builder

Vale a pena dar uma olhada nesta documentação de especificação, então acessem e baixem.

Categories: Flex, Notícias Tags:

FloripaFlex: Próxima Reunião

20, maio, 2009 admin 1 comentário

Salve Pessoal!

Segue abaixo o convite do Achille Carette, manager do AUG FloripaFlex:

Gostaria de convida-los para a próxima reunião do AUG FloripaFlex, no dia 20/05 na ACATE.
O assunto do dia é “Integrando Flex e PHP“, que será apresentada por um especialista do assunto, o Eduardo Kraus.

Horário:
Quarta 20/05, 19h - 20h

Endereço:
ACATE
Sala 1o Andar
(Associação Catarinense de Empresas de Tecnologia)
Rua Lauro Linhares, 589,
88036-001 - Trindade
Florianópolis - SC

Palestrante:
Eduardo Kraus

Eduardo Kraus trabalha desde 2005 com programação Web com HTML e PHP. Conheceu o Flex em 2007 e atualmente só desenvolve nesta linguagem com PHP. No momento esta pesquisando para desenvolver sites em Flex, de modo que o google consiga indexar e prestando serviço de desenvolvimento e consultoria

Pauta:
Integrando Flex e PHP

A palestra tem por objetivo apresentar o Flex aos programadores PHP e a facilidade em trabalhar com RemoteObject. Demonstar a integração do Flex com PHP e PHP+MySql utilizando AMFPHP e uma comparação com as três formas de integração. Uma breve abordagem do AMFPHP e suas configurações. E finalizando falar sobre segurança do Flex com PHP via AMFPHP

Inscrições:
Como sempre as inscrições são gratuitas mas as vagas limitadas. Por razões de organização, pedimos que façam sua inscrição pelo formulário
https://spreadsheets.google.com/viewform?hl=en&formkey=ckkzdU9ramk0ZVZwcDk2RThDTnVrUkE6MA

Mais informações:
AUG FloripaFlex
Página da reunião no AUG
Blog do Eduardo

Contamos com a sua presença,

Achille

Categories: Flex, Notícias Tags:

Criando um Custom Panel - Minimizar - Maximizar - Fechar.

18, maio, 2009 admin 1 comentário

Criando um Custom Panel.

Salve pessoal.
Na maioria dos projetos em que participo ou participei, são comuns os clientes ou usuários finais quererem telas nas quais tenha os botões de maximizar, minimizar, fechar e até mesmo outros tipos de componentes no topo do Panel. Hoje irei demonstrar como criar este componente de uma maneira simples e eficaz. Então vamos ao primeiro passo.
Este componente será similar ao FlexMdi, no qual hoje este faz parte do pacote flexlib.
Passo 1:
Certo primeiramente iremos criar um projeto Flex com a seguinte estrutura de pastas.

Estrutura

Com a estrutura acima criada vamos criar uma classe ‘as’ chamada BaseCustomPanel a qual irá estender um Panel. Esta classe será à base de todas as futuras telas e por sua vez não irá conter os botões de maximizar, minimizar e fechar. Porém a mesma lhe dará a total flexibilidade de adicionar qualquer componente no header (Topo - Cabeçalho) do Panel. Abaixo segue o código AS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package com.imaster.customPanel {
 
	import flash.display.DisplayObject;
 
	import mx.containers.Panel;
	import mx.core.Application;
	import mx.core.UIComponent;
	import mx.effects.Blur;
	import mx.events.FlexEvent;
	import mx.managers.PopUpManager;
 
	[Style(name="headerHorizontalGap", type="Number", inherit="no")]
	/**
	 * @author Fabiel Prestes
	 */
	public class BaseCustomPanel extends Panel {
 
		/**
		 * Aqui será armazenado todos os componente FILHOS que serão adicionados
		 * ao HEADER
		 */
		[ArrayElementType("mx.core.UIComponent")]
		public var arrayFilhos:Array = [];
 
		private var blurIn:Blur;
 
		/**
		 * Construtor Padrao
		 */
		public function BaseCustomPanel() {
			super();
		}
 
		/**
		 * @inheritDoc
		 */
		override protected function childrenCreated():void {
			super.childrenCreated();
 
			configStyle();
 
			/* Para cada Filho adicionado no objeto 'arrayFilhos'
			 * será realizado algumas configurações como:
			 * Adiciona-lo no HEADER do PANEL
			 * Propriedade buttonMode = true ....*/
			for each (var child:UIComponent in arrayFilhos)
				addTitleBarComponent(child);
		}
 
		/**
		 * @private
		 */
		private function abreComEfeito():void{
			blurIn = new Blur();
			blurIn.blurXFrom = 10;
			blurIn.blurXTo = 0;
			blurIn.blurYFrom = 10;
			blurIn.blurYTo = 0;
			blurIn.duration = 600;
			blurIn.play([this]);
		}
 
		/**
		 * Realizando a configuração padrão dos Estilos
		 */
		private function configStyle():void {
			this.setStyle("headerHorizontalAlign", "rigth");
			this.setStyle("headerVerticalAlign", "middle");
			this.setStyle("headerHorizontalGap", 5);
		}
 
		/**
		 * @inheritDoc
		 */
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
			super.updateDisplayList(unscaledWidth, unscaledHeight);
 
			reposicioneElementosNoCabecalho();
		}
 
		/**
		 * Reposiciona todos os componentes FILHOS ao PAI 'HEADER'
		 */
		protected function reposicioneElementosNoCabecalho():void {
			var componenteFilho:UIComponent;
			var posicaoX:Number = 0;
			var tamanhoPai:Number = 0;
			var posicaoY:Number = 0;
			var headerHorizontalGap:Number = getStyle('headerHorizontalGap');
 
			/* Caso não tenha sido adicionado Nenhum filho, deve apenas retornar e continuar
			 * o processamento natural. */
			if (arrayFilhos.length == 0)
				return;
 
			tamanhoPai = this.width - 10;
 
			/* Para cada filho Definido para ser adicionado no cabeçalho deve ser
			 * verificado seu tamanho para assim ser posicionado no componente HEADER do PANEL. */
			for (var i:int; i < arrayFilhos.length; i++) {
				componenteFilho = UIComponent(arrayFilhos[i]);
				componenteFilho.setActualSize(componenteFilho.getExplicitOrMeasuredWidth(), componenteFilho.getExplicitOrMeasuredHeight());
 
				/* Abaixo é pego a altura do HEADER do PANEL subtraido com a altura do COMPONENTE filho
				 * e DIVIDIDO por 2, afim de pegar o valor que será definido no Y. Desta maneira
				 * o filho ficará no meio do HEADER. */
				posicaoY = (getHeaderHeight() - componenteFilho.getExplicitOrMeasuredHeight()) / 2;
 
				/* Abixo é pego o tomanho total do PANEL subtraido com o tamanho total do COMPONENTE
				 * filho SUBTRAIDO com o HORIZONTAL GAP, afim de pegar o valor que será definido no X.
				 * Desta maneira os componente FILHOS ficarão sempre a DIREITA do PANEL.
				 * A variavel TAMANHOPAI e tambem sempre recebe o resultado desta subtração para que assim
				 * os FILHOS não irão ficar sobre postos um ao outro.*/
				posicaoX = tamanhoPai - componenteFilho.getExplicitOrMeasuredWidth() - headerHorizontalGap;
				tamanhoPai = posicaoX;
 
				/* Move o componente FILHO para o X e Y calculado anteriormente. */
				componenteFilho.move(posicaoX, posicaoY);
			}
		}
 
		/**
		 * Responsavel por Adicionar o Filho ao HEADER e realizar algumas pré configurações
		 */
		public function addTitleBarComponent(child:UIComponent):void {
			child.buttonMode = true;
 
			/* Este metodo é responsavel por adicionar o FILHO ao HEADER do PANEL. */
			titleBar.addChild(child);
 
			invalidateDisplayList();
		}
 
		public function openPanel():void{
			PopUpManager.addPopUp(this, DisplayObject(Application.application));
			PopUpManager.centerPopUp(this);
			abreComEfeito();
		}
	}
}

OK, com a nossa classe base criada iremos agora realizar uma extensão da mesma, fazendo algumas alterações como inclusão dos botões de minimizar, maximizar e fechar.
Segue abaixo o código da classe WindowPanel.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
package com.imaster.customPanel {
	import com.imaster.event.WindowPanelEvent;
 
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
 
	import mx.containers.Box;
	import mx.controls.Image;
	import mx.core.UIComponent;
	import mx.effects.Blur;
	import mx.effects.Move;
	import mx.effects.Parallel;
	import mx.effects.Resize;
	import mx.effects.Sequence;
	import mx.events.EffectEvent;
	import mx.managers.PopUpManager;
	import mx.utils.ObjectUtil;
 
	[Event(name="minimixar", type="com.imaster.event.WindowPanelEvent")]
	[Event(name="maximizar", type="com.imaster.event.WindowPanelEvent")]
	[Event(name="fechar", type="com.imaster.event.WindowPanelEvent")]
	/**
	 * @author Fabiel Prestes
	 */
	public class WindowPanel extends BaseCustomPanel {
 
		private var imgFechar:Image;
		private var imgMaximizar:Image;
		private var imgMinimizar:Image;
 
		private var glow:GlowFilter;
 
		private var sequenceMinimizar:Sequence;
 
		private var parallelMaximizar:Parallel;
		private var moveMaximizar:Move;
		private var resizeMaximizar:Resize;
 
		private var parallelMinimizar:Parallel;
		private var resizeMinimizar:Resize;
		private var moveMinimizar:Move;
 
		private var widthOriginal:Number;
		private var heightOriginal:Number;
 
		[Bindable]
		private var xOriginal:Number;
 
		[Bindable]
		private var yOriginal:Number;
 
		public var panelPai:UIComponent;
		public var barra:Box;
 
		/**
		 * Contrutor Padrão
		 */
		public function WindowPanel() {
			super();
		}
 
		/**
		 * @inheritDoc
		 */
		override protected function childrenCreated():void{
			this.setStyle("styleName", "windowpanel");
 
			configBotoes();
 
			super.childrenCreated();
 
			widthOriginal = ObjectUtil.copy(this.width) as Number;
			heightOriginal = ObjectUtil.copy(this.height) as Number;
 
			configEfeitoBotoes();
		}
 
		/**
		 * @private
		 * Metodo responsavel por guarda a posição X e Y atual da tela para que
		 * assim ao maximizar a tela a mesma volte para a sua posição original.
		 */
		private function trateMouseUpMinimizar(evt:MouseEvent):void{
			xOriginal = this.x;
			yOriginal = this.y;
		}
 
		/**
		 * @private
		 * Responsavel por criar e configurar os botoes de Maximizar, Minimizar e Fechar.
		 */
		private function configBotoes():void{
 
			imgMaximizar = new Image();
			imgMaximizar.source = "assets/img/maximizar.png";
			imgMaximizar.width = 20;
			imgMaximizar.height = 20;
 
			imgMinimizar = new Image();
			imgMinimizar.source = "assets/img/minimizar.png";
			imgMinimizar.width = 20;
			imgMinimizar.height = 20;
 
			imgFechar = new Image();
			imgFechar.source = "assets/img/fechar.png";
			imgFechar.width = 20;
			imgFechar.height = 20;
 
			imgMaximizar.addEventListener(MouseEvent.MOUSE_OVER, trateMouseOver);
			imgMaximizar.addEventListener(MouseEvent.MOUSE_OUT, trateMouseOut);
			imgMaximizar.addEventListener(MouseEvent.CLICK, trateMaximizarClick);
 
			imgMinimizar.addEventListener(MouseEvent.MOUSE_OVER, trateMouseOver);
			imgMinimizar.addEventListener(MouseEvent.MOUSE_OUT, trateMouseOut);
			imgMinimizar.addEventListener(MouseEvent.CLICK, trateMinimizarClick);
			imgMinimizar.addEventListener(MouseEvent.MOUSE_UP, trateMouseUpMinimizar);
 
			imgFechar.addEventListener(MouseEvent.MOUSE_OVER, trateMouseOver);
			imgFechar.addEventListener(MouseEvent.MOUSE_OUT, trateMouseOut);
			imgFechar.addEventListener(MouseEvent.CLICK, trateFecharClick);
 
			this.arrayFilhos.push(imgFechar);
			this.arrayFilhos.push(imgMaximizar);
			this.arrayFilhos.push(imgMinimizar);
		}
 
		/**
		 * @private
		 * Responsavel por instanciar e configurar os efeitos que serão realizados
		 * pelo click do mouse nas imagens no HEADER.
		 */
		private function configEfeitoBotoes():void{
			/* Este efeito será utilizado quando o mouse estiver em cima do botoes/imagens
			 * no HEADER */
			glow = new GlowFilter();
            glow.color = 0xffffff;
            glow.blurX = glow.blurY = 20;
		}
 
		/**
		 * @private
		 * Responsavel por instanciar e configurar os efeitos que serão realizados
		 * pelo click do mouse na imagem de Maximizar.
		 */
		private function configEfeitoMaximizar():void{
 
            if(moveMaximizar == null){
            	moveMaximizar = new Move(this);
	            moveMaximizar.duration = 600;
            }
 
			moveMaximizar.xFrom = barra.x;
			moveMaximizar.yFrom = barra.y;
 
            moveMaximizar.xTo = xOriginal;
            moveMaximizar.yTo = yOriginal;
 
            if(resizeMaximizar == null){
	            resizeMaximizar = new Resize(this);
 
	            resizeMaximizar.heightTo = heightOriginal;
	            resizeMaximizar.widthTo = widthOriginal;
	            resizeMaximizar.duration = 600;
            }
 
			if(parallelMaximizar == null){
				parallelMaximizar = new Parallel(this);
 
	            parallelMaximizar.addChild(moveMaximizar);
	            parallelMaximizar.addChild(resizeMaximizar);
   			}
		}
 
		/**
		 * @private
		 * Responsavel por instanciar e configurar os efeitos que serão realizados
		 * pelo click do mouse na imagem de Minimizar.
		 */
		private function configEfeitoMinimizar():void{
			if(resizeMinimizar == null){
	            resizeMinimizar = new Resize(this);
	            resizeMinimizar.widthTo = 200;
	            resizeMinimizar.heightTo = 35;
	            resizeMinimizar.duration = 600;
			}
 
			if(moveMinimizar == null){
	            moveMinimizar = new Move(this);
	            moveMinimizar.duration = 600;
			}
 
			var filhosBarra:int = barra.getChildren().length;
 
			if(filhosBarra >= 1){
				moveMinimizar.xTo = (barra.getChildAt(0).width + 10) * filhosBarra;
			}else{
	            moveMinimizar.xTo = barra.x;
			}
 
            moveMinimizar.yTo = barra.y; 
 
            if(parallelMinimizar == null){
	            parallelMinimizar = new Parallel();
            	parallelMinimizar.addChild(resizeMinimizar);
	            parallelMinimizar.addChild(new Blur());
	            parallelMinimizar.addChild(moveMinimizar);
            }
 
			if(sequenceMinimizar == null){
	            sequenceMinimizar = new Sequence(this);
				sequenceMinimizar.addChild(parallelMinimizar);
	            sequenceMinimizar.addEventListener(EffectEvent.EFFECT_END, trateFimEfeitoMinimizar);
			}
		}
 
		/**
		 * @private
		 * Trata o OVER do mouse nas imagens do HEADER
		 */
		private function trateMouseOver(evt:MouseEvent):void{
            evt.currentTarget.filters =[glow];
		}
 
		/**
		 * @private
		 * Trata o OUT do mouse nas imagens do HEADER
		 */
		private function trateMouseOut(evt:MouseEvent):void{
			evt.currentTarget.filters = [];
		}
 
		/**
		 * @private
		 * Trata o CLICK da imagem maximizar do HEADER
		 */
		private function trateMaximizarClick(evt:MouseEvent):void{
			barra.removeChild(this);
			PopUpManager.addPopUp(this, panelPai);
 
			configEfeitoMaximizar();
			parallelMaximizar.play();
			this.dispatchEvent(new WindowPanelEvent(WindowPanelEvent.MAXIMIZAR));
		}
 
		/**
		 * @private
		 * Trata o CLICK da imagem mniimizar do HEADER
		 */
		private function trateMinimizarClick(evt:MouseEvent):void{
			configEfeitoMinimizar();
			sequenceMinimizar.play();
		}
 
		/**
		 * @private
		 * Trata o CLICK da imagem fechar do HEADER
		 */
		private function trateFecharClick(evt:MouseEvent):void{
			var blur:Blur = new Blur(this);
            blur.blurXFrom = 0;
            blur.blurYFrom = 0;
            blur.blurXTo = 10;
            blur.blurYTo = 10;
            blur.duration = 600;
            blur.addEventListener(EffectEvent.EFFECT_END, trateFimEfeitoFechar);
			blur.play();
		}
 
		/**
		 * @private
		 * Apos terminar o efeito de minimizar, é dispachado o evento do tipo MINIMIZAR
		 */
		private function trateFimEfeitoMinimizar(evt:EffectEvent):void{
			barra.addChild(this);
			this.dispatchEvent(new WindowPanelEvent(WindowPanelEvent.MINIMIZAR));
		}
 
		/**
		 * @private
		 * Apos terminar o efeito de mafechar, é dispachado o evento do tipo FEHCAR
		 * e logo em seguida a tela é removida.
		 */
		private function trateFimEfeitoFechar(evt:EffectEvent):void{
			try{
				PopUpManager.removePopUp(this);
				barra.removeChild(this);
				panelPai.removeChild(this);
			}catch(er:Error){}
			this.dispatchEvent(new WindowPanelEvent(WindowPanelEvent.FECHAR));
		}
	}
}

O grande detalhe desta classe é que esta armazena a referência de seu Parent (Pai) e da barra onde a mesma ficará minimizada.
Na mesma foi incluído efeitos diferentes em cada ação de botão, por exemplo.
Botão Minimizar: Foi aplicado um efeito paralelo no qual a tela vai se movimentando (Move) e se redimensionando (Resize) até atingir a barra de minimização, com um pequeno Blur ao final.
Botão Maximizar: Neste existe apenas o efeito Resize, deixando mais simples.
Botão Fechar: Neste também foi aplicado apenas o efeito Blur simples mais bem atrativo aos olhos do usuário final, pois se assemelha bastante com o efeito que o Windows Vista oferece.
Também foi aplicado nos botões um efeito de Glow, no momento em que o usuário passa o mouse por cima dos botões, efeito bem similar ao Vista.
Todos os botões tem listener Mouse.Click e Mouse.Mouse_Over e para cada um destes possuem seus próprios comportamentos, porem a cada fim de comportamento os mesmos dispacham seus próprios eventos, afim de tornar mais flexível a sua utilização pelos outros desenvolvedores que utilizarão seu coponente.
É um componente relativamente simples para a construção e agora vocês verão que também é de simples aplicação. Vamos as classes de teste.
WindowPanelTeste.mxml, uma simples classe que extende o WindowPanel e adiciona um VBox com um background Cinza.

Main.mxml, uma simples classe de teste. A mesma já é instanciada com duas janela WindowTeste criada como default, também possui um botão para adicionar novas janelas testes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
		<![CDATA[
			import com.imaster.WindowPanelTeste;
			import mx.managers.PopUpManager;
			import mx.controls.PopUpButton;
			import com.imaster.customPanel.WindowPanel;
 
			public var filhos:Number = 1;
 
			private function init():void{
				var tela:WindowPanelTeste = new WindowPanelTeste();
				tela.panelPai = this;
				tela.barra = hbBarra;
				tela.title = "Tela 1";
 
				PopUpManager.addPopUp(tela, this);
				PopUpManager.centerPopUp(tela);
 
				var tela2:WindowPanelTeste = new WindowPanelTeste();
				tela2.panelPai = this;
				tela2.barra = hbBarra;
				tela2.title = "Tela 2";
 
				PopUpManager.addPopUp(tela2, this);
				PopUpManager.centerPopUp(tela2);
			}
 
			private function novaJanela():void{
				var tela:WindowPanelTeste = new WindowPanelTeste();
				tela.panelPai = this;
				tela.barra = hbBarra;
				tela.title = "Nova Janela";
				tela.openPanel();
			}
		]]>

Aí esta um componente simples e flexível. Muitos devem até estar se perguntando, o “porque de se criar este componente se já existe outros.?”. Certamente já existem componentes similares a este, contudo a questão aqui é demonstrar em maneira simples como é possível criar seus próprios componentes e não ficar dependendo da comunidade ou dos criadores do mesmo para resolverem problemas com as lib. E com certeza a partir deste componente você poderá deixá-lo muito mais robusta e atraente basta usar a criatividade.
Espero mais uma vez ter ajudado e até a próxima. Abaixo segue o link do source para download

Exemplo Funcionando:

This movie requires Flash Player 9

Categories: Flex, Flex Fast Code Tags:

Internacionalizando (I18n) Aplicações Flex

3, maio, 2009 admin 1 comentário

Salve pessoal,

Hoje irei demonstrar como deixar sua aplicação multi-idiomas de uma maneira simples e facil.

Em grandes projetos web uma das principais preocupações dos arquitetos é a internacionalização do projeto. Fazer com que os usuários possam acessar e utilizar a aplicação sem ter que se preocupar com com a língua é um dos principais pontos positivos para um projeto se destacar no mercado.Visando isso os arquitetos da Adobe aperfeiçoaram o recurso de internacionalização do Flex 3, este recurso é chamado de ResourceBundle.
Desta maneira ficou muito simples e flexivel aplicar I18n veja porque:

1 - Você pode compilar recursos para várias localidades em uma única aplicação ou módulo.
2 - Você acessar todos os recursos através do ResourceManager, no qual pode gerenciar os recursos para várias localidades.
Você pode mudar em tempo de execução a localidade do recurso.
3 - Você também pode usar imagens, sons, etc, e não apenas Strings

Estes são apenas uns dos melhoramentos e vantagens de utilizar o ResourceBundle do Flex 3. O ResourceBundle possuim algumas exigências como criar um arquivo Locale para cada idioma, contudo existe uma forma de burlar isso utilizando arquivos properties.

Neste artigo irei demonstrar como aplicar I18n usando o ResourceManager sem ter criar arquivos Locales. I18n com ResourceBundle

Primeiramente iremos criar um projeto Flex, irei chama-lo de Flex_I18n_A. No projeto crie uma nova pasta chamada I18n nesta crie os seguintes arquivos XML: pt_BR, en_US e es_ES.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="iso-8859-1"?>
<locale lang="en_US">
	<property key="titulo_app" value="Applying I18n in Flex applications" />
	<property key="usuario" value="Username" />
	<property key="senha" value="Password" />
	<property key="login_erro" value="User credentials are wrong. Please try again" />
	<property key="bt_login" value="Login" />
	<property key="bt_logout" value="Logout" />
	<property key="msg_boas_vindas" value="User logged in successfully." />
	<property key="idioma" value="Language" />
	<property key="selecione_idioma" value="Select a language." />
</locale>
 
<?xml version="1.0" encoding="iso-8859-1"?>
<locale lang="pt_BR">
	<property key="titulo_app" value="Aplicando I18n em aplicações Flex." />
	<property key="usuario" value="Usuário" />
	<property key="senha" value="Senha" />
	<property key="login_erro" value="Dados incorretos. Tente novamente." />
	<property key="bt_login" value="Login" />
	<property key="bt_logout" value="Sair" />
	<property key="msg_boas_vindas" value="Usuário logado com sucesso." />
	<property key="idioma" value="Idioma"/>
	<property key="selecione_idioma" value="Selecione um idioma."/>
</locale>
 
<?xml version="1.0" encoding="iso-8859-1"?>
<locale lang="es_ES">
	<property key="titulo_app" value="Aplicando i18n aplicaciones en Flex." />
	<property key="usuario" value="Nombre de Usuario" />
	<property key="senha" value="Contraseña" />
	<property key="login_erro"
		value="Credenciales de usuario se equivoca. Por favor, inténtelo de nuevo." />
	<property key="bt_login" value="Inicio de sesión" />
	<property key="bt_logout" value="Cerrar sesión" />
	<property key="msg_boas_vindas" value="Usuario conectado correctamente." />
	<property key="idioma" value="Idioma" />
	<property key="selecione_idioma" value="Seleccione un idioma."/>
</locale>

Agora com os três arquivos criados iremos criar a classe que irá fazer o carregamento dos arquivos xml.
Para cada key do XML será setado na propriedade content do ResourceBundle, desta maneira poderemos usar o metodo getString para pegar o value internacionalizado da key.

Agora iremos criar a classe com/flexI18n/utils/ConfigI18n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.flexI18n.utils {
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
 
	import mx.resources.ResourceBundle;
	import mx.resources.ResourceManager;
 
	/**
	 * @author Fabiel Prestes
	 */
	public class ConfigI18n {
 
		private var resourceBundle:ResourceBundle;
 
		[Bindable]
		public var currentLocale:String = "pt_BR";
 
		public function ConfigI18n() {
			super();
		}
 
		/**
		 * Carrega o xml locale baseado na String passada como parametro.
		 */
		public function loadLocale(locale:String= "pt_BR"):void {
			currentLocale = locale;
			var xmlLoader:URLLoader = new URLLoader();
			xmlLoader.addEventListener(Event.COMPLETE, createBundle);
			xmlLoader.load(new URLRequest("I18n/" + currentLocale + ".xml"));
		}
 
        /**
        * @private
        * Apos o xml ser carregado com sucesso, deve-se pegar cada chave (key) e valor 
        * (value) e adicionar no resourceBundle, para assim ser acessado em qualquer local da aplicação.
        * @eventType Event
        */
        private function createBundle(e:Event):void {
            var propertyList:XMLList = new XML(e.target.data).property;
 
            resourceBundle = new ResourceBundle(currentLocale, "ApplicationResource");
 
            for each (var property:XML in propertyList) {
            	resourceBundle.content[property.@key] = property.@value;
            }
 
            ResourceManager.getInstance().addResourceBundle(resourceBundle);
            ResourceManager.getInstance().update();
            ResourceManager.getInstance().localeChain = [currentLocale,"pt_BR"];
        }
	}
}

Apenas uma observação na classe ConfigI18n, nós criamos uma variavel ResourceBundle aplicamos todas as mensagens internacionalizadas do XML e por final pegamos nosso resource e aplicamos no ResourceManager cujo este é um singleton, lembrando que sempre apos adicionar um novo resource deve-se fazer um update no ResourceManager para que todas as alterações sem efetivadas.

Outro detalhe é que quando XML terminou de ser carregado, foi instanciado o ResourceBundle e assim definido um nome para o Locale e um identificador para o BundleName. É através deste identicador que conceguiremos recurar as mensagens internacionalidas do ResourceManager.

OK, com a classe resposavel por carregar e configurar o ResourceBundle vamos criar uma tela de login para para demonstrar a autilização do ResourceBundle.

Agora iremos criar a classe com/flexI18n/views/LoginUI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%">
 
	<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.managers.PopUpManager;
			import com.flexI18n.utils.ConfigI18n;
 
			[Bindable] public var availableLocales:Array = [ {label:"English", data:"en_US"},
															 {label:"Portuguese", data:"pt_BR"},
			                                                 {label:"Spanish", data:"es_ES"} 
			                                               ];
 
 
			private function onLogin(e:Event):void {
				PopUpManager.removePopUp(this);
				Alert.show(resourceManager.getString('ApplicationResource','msg_boas_vindas'));
			}
 
			private function comboChangeHandler():void {
                var locale:ConfigI18n = new ConfigI18n();
                locale.loadLocale(localeComboBox.selectedItem.data);
                this.localeComboBox.selectedIndex = -1;
			}
 
		]]>
	</mx:Script>
	<mx:Form width="100%">
		<mx:FormItem label="{resourceManager.getString('ApplicationResource','usuario')}">
			<mx:TextInput id="username" width="200"/>
		</mx:FormItem>
		<mx:FormItem label="{resourceManager.getString('ApplicationResource','senha')}" direction="horizontal">
			<mx:TextInput id="password" displayAsPassword="true"  width="200"/>
		</mx:FormItem>
		<mx:FormItem label="{resourceManager.getString('ApplicationResource','idioma')}">
			<mx:ComboBox id="localeComboBox" selectedIndex="-1"
                dataProvider="{availableLocales}"
                change="comboChangeHandler()"
             	width="200" prompt="{resourceManager.getString('ApplicationResource','selecione_idioma')}"/>
		</mx:FormItem>
	</mx:Form>
	<mx:ControlBar width="100%" horizontalAlign="right">
		<mx:Button label="{resourceManager.getString('ApplicationResource','bt_login')}"
			click="onLogin(event)" enabled="{username.text != '' &amp;&amp; password.text != ''}"  x="517" y="118"/>
	</mx:ControlBar>
 
</mx:TitleWindow>

Se vocês olharem a classe acima, não foi em nenhum momento instanciado um objeto ResourceBundle, mais então de onde saiu
a variavel resourceBundle usada. Muito simples estamos usando o atributo da classe UIComponent.

A classe main fica da seguinte maneira.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
 
	<mx:Script>
		<![CDATA[
			import mx.managers.PopUpManager;
			import com.flexI18n.views.LoginUI;
			import com.flexI18n.utils.ConfigI18n;
 
			private function initApp():void{
				new ConfigI18n().loadLocale();
 
				var login:LoginUI = new LoginUI();
				PopUpManager.addPopUp(login, this, true);
				PopUpManager.centerPopUp(login);
			}
		]]>
	</mx:Script>
 
</mx:Application>

É isso aí, uma maneira simples e facil de fazer sua aplicação ficar multi-idioma.
Espero ter ajudado e até a próxima.

Categories: Flex, Flex Fast Code Tags:

Plugin para Identar Codigos Flex

10, abril, 2009 admin Sem comentários

Olá pessoal,

Esses dias dando uma vasculhada pela net adentro, encontrei no sourceForge um projeto bem legal.
Os caras criaram um plugin para identação de códigos Flex Mxml e As.

O link do projeto http://sourceforge.net/projects/flexformatter/
Para instalar o plugin é muito simples.
- Faça o download do jar e coloque dentro da plasta plugin de seu Eclipse ou FlexBuilder.
- Reinicie o Eclipse com o comando -clean e show de bola
- Em sua barra de tarefa irá aparecer dois novos icones de identação.

Barra de Tarefas.
Plugin

Você pode fazer seu proprio estilo de identação e tambem tem opção de Exportar ou Importar para outra maquina que tenha o plugin instalado.

Categories: Java Fast Code Tags:

IBM retira oferta de compra da Sun, dizem jornais

7, abril, 2009 admin Sem comentários

Salve pessoal,

Para alguns esta noticia é um alívio, para outros é uma satisfação e para outros uma decepção.
Enfim acaba a angustia e a especulação de o Java 7 não ser mais free.

Segue a notícia do G1

Categories: Java, Notícias Tags:

Trabalhando com FlexSession

1, abril, 2009 admin 6 comentários

Salve pessoal,

Após ter recebidos alguns e-mails e ter visto a mesma dúvida nas listas de discuções resolvi criar um post sobre Gerenciamento de Sessão em aplicações Flex.

Apenas resaltando este é um assunto muito complexo este post não irá sanar todas as suas duvidas, mais irá lhe dar um Norte nos seus estudos. Em caso de duvidas leia a documentação do BlazeDS ou mande um e-mail.

Então vamos lá.


Gereciamento de sessão usando BlazeDS

O blazeDS nos fornece três classes para sincronização entre a aplicação Flex e Servidor, são estas: FlexClient, MessageClient e FlexSession.
Segue um breve resumo de cada ojbeto.

# FlexClient

Toda aplicação Flex escrita em MXML ou em ActionScript, ambas são compiladas e incluidas dentro de um SWF. Quando o SWF se conecta com o servidor BlazeDS, o objeto flex.messaging.client.FlexClient é criado para representar o SWF no servidor.
O arquivo SWF e o objeto FlexClient tem um relacionamento um-para-um (one-to-one), deste modo todo
FlexClient tem um identificador unico em sua propriedade ID, no qual o servidor BlazeDS gera.

# MessageClient

Se uma aplicação Flex contém um componente flex.messaging.Consumer, o servidor irá criar uma correspondente instância do objeto flex.messaging.MessageClient para representar a subscrição do estado do componente Consumidor (Consumer).
Todo objeto MessageClient tem um identificador único chamado clienteId.
BlazeDS pode gerar automaticamente um valor para o clientId, mas a aplicação Flex também pode definir um valor para a propriedade Consumer.clientId antes de chamar o metodo Consumer.subscribe().

# FlexSession

Um objeto FlexSession representa a conexão entre a aplicação Flex e o Servidor. Este ciclo de vida depende diretamente do protocolo subjacente, no qual é determinado pelos canais e parâmetros utilizados no Cliente e Servidor, respectivamente.
Se uma base de canal HTTP, tais como AMFChannel ou HTTPChannel, é utilizada na aplicação Flex, um objeto FlexSession é embutido numa sessao HTTP.
Se um canal HTTP se conecta a um servlet, o subjacente a sessão HTTP é um objeto J2EE HttpSession.

Todo este pequeno resumo acima pode parecer um bixo de 1000 cabeça mais conforme você for usando em
aplicações tudo isso ficará claro e simples.

# Relacionamento entre FlexClient, MessageClient e FlexSession

Um objeto FlexClient pode ter um ou mais intancias de FlexSession a ela associados, em função dos canais que Flex a aplicação utiliza.
Por exemplo, se a aplicação Flex usa um HTTPChannel e um FlexSession isso representa apenas um HTTP session criado pelo HTTPChannel no servidor.
Um FlexSession também pode ter um ou mais objeto FlexClient associadas a ele. Por exmeplo, quando o usuario abre a aplicação Flex em duas tabs no navegador dois objetos FlexClient são criados, porém o servidor considera dois separadores partilhando a mesma subjacente HTTP sessão.

Em termos de hierarquia, FlexClient e FlexSession são pares que existe uma relação entre pais e filhos FlexClient / FlexSession e MessageClient.

Resaltando Novamente: Sei que os explicações acima são bem complexas por isso é interessante que vocês parem um tempo e
leiam a documentação do BlazeDS para um maior entendimento do assunto, este post tem o intuito apenas de abrir a mente e dar um Norte.

## Exemplo Rápido e Fácil.

# Usando FlexContext com FlexSession and FlexClient.

A classe utilitária flex.messaging.FlexContext expõe o contexto atual sobre a execução do servidor, a mesma fornece acesso ao FlexSession e ao FlexClient.
Ela também fornece contexto global através do acesso MessageBroker, ServletContext, e ServletConfig instâncias.
O seguinte exmplo mostra uma classe Java que chama o metodo FlexContext.getHttpRequest() e pega do mesmo o objeto HTTPServletRequest e também chama o metodo FlexContext.getFlexSession() para obter o objeto de sessao atual.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package br.com.fabielprestes
 
import flex.messaging.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class SessionCorrente {
	public HttpServletRequest request;
	public FlexSession session;
 
	public SessionCorrente() {
		request = FlexContext.getHttpRequest();
		session = FlexContext.getFlexSession();
	}
 
	public String getSessionId() throws Exception {
		String s = new String();
		s = (String) session.getId();
		return s;
	}
 
	public String getHeader(String h) throws Exception {
		String s = new String();
		s = (String) request.getHeader(h);
		return h + "=" + s;
	}
}

Então é isso pessoal na proxima parte irei demonstrar como utilizar o objeto ExternalInterface para trabalhar com as sessões, fiquem atento.

Dúvidas ou Sugestões deixem seu comentário.

Categories: Dicas, Flex Tags:

Links projetos OpenSource #1

1, abril, 2009 admin Sem comentários
Categories: Links Tags:

Mock para exame Flex/AIR 3 - Grátis

27, março, 2009 admin Sem comentários

Salve pessoal,

Hoje recebi um link muito legal do Mario Jr.
A empresa PXL Designs em parceria com a Rich Desktop Solutions criaram o mock para a certificação Flex/Air.
Este Mock é free contudo ainda esta em versão Beta.

Download

Abraços

Categories: Certificação Flex, Dicas, Flex, Notícias Tags:

Novo JUG ‘jugma’

27, março, 2009 admin Sem comentários

Salve pessoal,

Esta semana nasceu mais um JUG o jugma, foi uma galera lá do Maranhão que criaram, esperamos que gerem bons frutos.

Categories: Notícias Tags: