31 de julho de 2009

Convertendo apresentações Power Point em animações Flash

Suponha que você montou uma apresentação no Power Point para divulgar um produto da sua empresa. Nesta apresentação, você usou diversas configurações, animações e formatações, além de incluir gráficos e figuras. A apresentação ficou tão boa que seu chefe te pediu que a publicasse na página da empresa na Internet.

Qual a melhor forma de fazer isso de uma forma fácil e amigável ? Simplesmente salvar o Power Point como um HTML pode não ser interessante para alguém acessando o site. A melhor abordagem talvez fosse convertê-la numa animação Flash que é mais apropriada para distribuir na internet. Outro ponto é que animações flash funcionam nos principais navegadores de internet dos principais Sistemas Operacionais e a animação em si não pode ser alterada pelo usuário do site.

Deparei com essa situação recentemente na ABC71 pois a empresa está preparando material para realizar treinamentos no nosso ERP Omega e bastante coisa já foi montada como Power Point. O material ainda não está totalmente pronto e não foi publicado mas encontrei uma ferramenta ideal para o que queríamos.

A ferramenta chama-se ISpring e faz exatamente isso: converte suas apresentações Power Point numa animação Flash. Ela é distribuída como um plugin do Power Point e a interação é transparente já que é criada uma guia com o mesmo look-and-feel do Office 2007:
Não consegui encontrar no site do fabricante informações sobre se o ISpring trabalha com outras versões do Office.

Além de fazer a conversão, o ISpring permite que você inclua narração junto com a apresentação de forma sincronizada. Também permite que se configure uma taxa de compressão para controlar o tamanho final da animação em bytes e que se configure a escala que o resultado final terá em relação à apresentação original, isto é, o comprimento e altura da animação.

O site do produto garante que ele é capaz de converter mais de 180 tipos de animações do Power Point e todos os tipos de transição entre slides disponíveis. Ele também embute áudio e vídeo que tiverem sido incluídos na apresentação original, além de tratar links e os botões de ações. A aparência da animação resultante impressiona bem já que reproduz fielmente o que foi feito no Power Point.

Pela reprodução da barra de ferramentas acima dá pra ver também que há um botão para gerar rapidamente um vídeo Flash compatível para publicar no YouTube.

Há uma versão gratuita da aplicação para uso pessoal, isto é, para você converter apresentações pessoais - como um álbum de suas férias, por exemplo, ou montar e mandar algum cartão multimídia para alguém. A versão gratuita apenas realiza a conversão para Flash, não disponibilizando os recursos de controle de narração, taxa de compressão ou configuração de escala. Veja aqui a comparação entre as versões.

29 de julho de 2009

Design Patterns com Delphi : Abstract Factory

Imagine uma situação em que, dependendo de certas condições do ambiente operacional em que seu programa irá executar, um conjunto diferente de classes tenha que estar disponível para criação. Um exemplo típico disso é a criação de skins para permitir variações no visual do programa de acordo com opção selecionada pelo usuário. Nesse cenário, o conjunto de classes que representam componentes visuais têm que ser diferente para atender o visual selecionado.

Para resolver esse tipo de problema, foi desenvolvido uma variação do Design Pattern Factory Method, descrito no post anterior. Esse novo Pattern Criacional foi chamado Abstract Factory e a ideia dele é criar uma interface padrão (uma função) para decidir qual o Factory Method a ser utilizado. Na prática, equivale a implementar um Factory Method dentro de outro. Veja o esquema que representa este cenário:

Esquema para Abstract Factory
Neste exemplo, o usuário poderia optar por um de dois visuais disponíveis para a aplicação (Windows ou Modern). Internamente, a aplicação possui classes bases para desenhar os EditText e os ComboBox além de disponibilizar dois conjuntos de heranças dessas classes, um para cada "skin" possível. A função GetSkinFactory da classe TWSkinFactory é a responsável por instanciar a "fábrica" correta de acordo com o tipo de skin desejado:
type
TWTipoSkin = (tsWindows, tsModern);
TWSkinFactory = class
public
class function GetSkinFactory (ATipo: TWTipoSkin): TWSkinFactory;
function CreateEditText: TWEditText;virtual;abstract;
function CreateComboBox: TWComboBox;virtual;abstract;
end;
TWWindowsSkinFactory = class(TWSkinFactory)
public
function CreateEditText: TWEditText;override;
function CreateComboBox: TWComboBox;override;
end;
TWModernSkinFactory = class(TWSkinFactory)
public
function CreateEditText: TWEditText;override;
function CreateComboBox: TWComboBox;override;
end;

implementation

class function TWSkinFactory.GetSkinFactory (ATipo: TWTipoSkin): TWSkinFactory;
begin
Result := Nil;
case ATipo Of
tsWindows: Result := TWWindowsSkinFactory.Create;
tsModern: Result := TWModernSkinFactory.Create;
end;
end;

Veja que a função GetSkinFactory é uma função de classe (não precisa de uma instância para ser usada) enquanto as funções de criação dos componentes visuais são abstratas já que o objetivo dessa classe é apenas introduzir o comportamento esperado para as heranças. Neste exemplo, o comportamento desejado é criar instâncias para os componentes visuais:
function TWWindowsSkinFactory.CreateEditText: TWEditText;
begin
Result := TWEditWindows.Create;
end;
function TWModernSkinFactory.CreateEditText: TWEditText;
begin
Result := TWEditModern.Create;
end;

Cada classe de "fábrica" cria instâncias dos componentes apropriados para o tipo de "skin" selecionado e o polimorfismo faz o resto, deixando o código do programa mais limpo e mais fácil de manter. Supondo que haja um ComboBox para escolha do visual:
var factory : TWSkinFactory;
ed1 : TWEditText;
begin
factory := TWSkinFactory.GetSkinFactory (TWTipoSkin (ComboBox1.ItemIndex));
{...}
ed1 := factory.CreateEditText;
ed1.Desenha;
{...}

A variável factory é instanciada com base na opção do usuário e o resto do programa a utiliza para criar a interface visual. Isto é, o programa não sabe de antemão com qual conjunto de classes visuais está trabalhando. Da mesma forma que no Factory Method, usar o Abstract Factory deixará um único ponto do código para ser alterado caso novas heranças de "skin" sejam necessárias.

As situações onde esses Patterns podem ser usados também são parecidas: é preciso ter conjuntos de classes com relação de herança e o programa tem que ter conhecimento prévio das classes disponíveis pois elas têm que estar presentes na função Factory.

27 de julho de 2009

Design Patterns com Delphi : Factory Method

Conforme afirmei no post anterior (Implementando Design Patterns), os Patterns do tipo Criacionais flexibilizam a criação de instâncias de classes (Objetos). No caso do Factory Method, essa flexiblização ocorre ao usar uma interface padrão para criar instâncias de classes que têm relação de herança entre si. A ideia é construir um método (a interface padrão) que é capaz de decidir qual classe deve ser instanciada, tomando por base um ou mais valores passados por parâmetro.

Neste contexto, Interface não tem a ver com o conceito embutido na palavra chave interface do Delphi. Aqui ele se refere à forma com que a função se relaciona com o mundo exterior, isto é, quais parâmetros deverão ser informados por outras partes do programa para se obter a instância desejada. A interface padrão é, então, uma função bem conhecida que centraliza a criação de instâncias para uma família de classes.

Tome, por exemplo, as classes representadas no diagrama abaixo:

Esquema para Factory Method
Há uma classe TWForma que é base para 3 heranças conhecidas (TWCirculo, TWQuadrado e TWTriangulo). Em Delphi, essa relação seria declarada como segue:
type
TWForma = class
{ ... }
procedure Desenha;virtual;
end;
TWCirculo = class(TWForma)
{ ... }
procedure Desenha;override;
end;
TWQuadrado = class(TWForma)
{ ... }
procedure Desenha;override;
end;
TWTriangulo = class(TWForma)
{ ... }
procedure Desenha;override;
end;

A outra classe existente no esquema é a TWFormaFactory. Através dela implementaremos um único método - o Factory Method - que é declarado como um método de classe, isto é, não é preciso instanciar a classe para utilizá-lo. Esse método é o coração do Design Pattern Factory Method pois é nele que fica a inteligência para instanciar as classes. Veja a declaração:
type
TWTipoForma = (tfCirculo, tfQuadrado, tfTriangulo);
TWFormaFactory = class
class function GetTWForma (ATipo: TWTipoForma): TWForma;
end;

implementation

class function TWFormaFactory.GetTWForma (ATipo: TWTipoForma): TWForma;
begin
Result := Nil;
case ATipo Of
tfCirculo: Result := TWCirculo.Create;
tfQuadrado: Result := TWQuadrado.Create;
tfTriangulo: Result := TWTriangulo.Create;
end;
end;

Aqui, a interface padrão para criar instâncias do TWForma é o método GetTWForma. Repare que ele tem conhecimento prévio sobre as classes que serão criadas. Por causa do polimorfismo, o método pode ser declarado de forma a retornar um ponteiro para a classe base TWForma e o resto do programa não precisa se preocupar com qual tipo foi realmente instanciado já que a classe TWForma introduziu acesso a todo o comportamento que é esperado. Isso configura o cenário ideal para usar o padrão Factory Method: classes com relação de herança e conhecimento prévio das classes a instanciar.

Usar esse padrão tem um clara vantagem se comparada a usar simplesmente o constructor de cada classe: se novas heranças de TWForma forem declaradas, haverá um único ponto do código para ser alterado.

Uma forma de usar o exemplo seria incluir um Combo num Form para permitir que o usuário adicione um nova forma a uma lista e essa lista controle o que será desenhado em tela:
tpForma := TWTipoForma (ComboBox1.ItemIndex);
forma := TWFormaFactory.GetTWForma (tpForma);
ListaFormas.Add (forma);
{ ... }
forma.Desenha;

25 de julho de 2009

Implementando Design Patterns

Há muitas expressões associadas à Tecnologia de Informação que são meros modismos, formas de se criar problemas para vender solução. Essas expressões surgem e logo são descartadas para dar lugar a outras mais "modernas", muitas vezes ideias requentadas que são apresentadas sob uma nova roupagem. Confesso que pensei ser esse o caso a primeira vez que ouvi falar dos Design Patterns ou Padrões de Projeto de Software, mas estava enganado.

A expressão Design Patterns diz respeito a uma série de soluções bem testadas e documentadas para resolver problemas computacionais específicos. Ou seja, alguém tinha um problema de programação e conseguiu resolvê-lo de uma forma bem estruturada, tornando a solução reaproveitável. É justamente essa a razão de não ser apenas modismo já que cada uma das soluções pode ser aplicada sempre que aparecer a mesma situação que o Pattern se propõe a resolver, independendo da linguagem de programação ou do ambiente operacional escolhido - única restrição é que a linguagem comporte o conceito de Objetos. É provável que você já use algumas das soluções propostas sem mesmo saber que se trata de um Design Pattern já estabelecido.

A ideia dos Padrões de Projeto foi introduzida na década de 1970 pelo austríaco Christopher Alexander. Ele propôs um sistema que estabelece as características de um padrão - isto é, como determinar que algo se constitui num padrão - e como descrever formalmente o padrão. A grosso modo, essa descrição formal deve detalhar o problema em questão, contextualizá-lo ao indicar em quais situações o padrão descrito se aplica e, obviamente, descrever a solução para o problema proposto. Embora Christopher Alexander seja arquiteto e sua teoria tenha sido calcada no projeto e construção como entendidos pela Arquitetura, seus conceitos de Padrões de Projeto são genéricos o suficiente para serem adotados na informática.

O transporte dessas ideias para a Computação teve início na década de 1980 mas o grupo mais conhecido de Padrões de Projeto de Software foi descrito em 1994 no livro Design Patterns. O fato do livro ter sido escrito por 4 programadores deu nome à coleção de Patterns: Gof ou Gang of Four.

Os padrões Gof foram agrupados em 3 categorias, de acordo com o momento em que são aplicados:
Criacionais: são padrões que introduzem formas de se criar instâncias de uma Classe. Os padrões dessa categoria tornam mais flexíveis a instanciação de classes em situações em que o tipo de classe necessária pode variar ao longo da existência de um programa.

Estruturais: são padrões que tratam das associações estruturais entre classes e objetos, isto é, as formas com que as classes se conectam dentro de um programa para garantir a coesão do projeto.

Comportamentais: são padrões que permitem modelar a maneira como classes e objetos colaboram entre si, estabelecendo as interações e as divisões de responsabilidades dessas classes e objetos num sistema.

Esse post é apenas uma introdução ao assunto. Pretendo colocar outros posts para mostrar na prática a utilização dos Design Patterns através de exemplos em Delphi.