Conforme apresentado recentemente aqui nesta revista, a nova versão do Delphi, a XE2, foi lançada e veio repleta de novidades. Uma que chamou a atenção da comunidade antes mesmo do lançamento oficial foi o tão badalado FireMonkey. Este que é o mais novo framework da Embarcadero voltado para o desenvolvimento de aplicações de negócios com visual mais rico e de caráter multi-plataforma, rodando nativamente em Windows, Mac (OS X) e iOS. Dessa forma, este artigo visa fazer uma explanação de como se dá a construção de aplicações com o FireMonkey, e sua proximidade e diferenças com relação às aplicações VCL tradicionais.

Quando usar o FireMonkey

Se você é um desenvolvedor Delphi que almeja melhorar suas aplicações, seja no aspecto visual, através de interfaces de usuário mais ricas, ou ainda torná-las aptas a rodarem em outros ambientes além do Windows, como Mac (OS X) e iOS, a alternativa ideal se resume em apenas um nome: FireMonkey. Esta nova plataforma de desenvolvimento de aplicações da Embarcadero traz consigo uma nova gama de componentes, disponibilizados no IDE através da tradicional Tool Palette, proporcionando ao desenvolvedor a mesma experiência RAD que consagrou o Delphi. Dessa forma, além do reaproveitamento do conhecimento, o profissional consegue facilmente construir aplicações que atendam a novos nichos de mercado.

O que é o FireMonkey?

O FireMonkey é considerado pela Embarcadero figura principal da nova geração de plataformas para desenvolvimento de aplicações. Aplicações estas que apresentam como principais características o seu caráter multi-plataforma, ou seja, podem ser executadas em ambientes distintos além de possuir um visual mais arrojado e rico. Este tipo de visual proporciona um envolvimento maior com o usuário, potencializando seu grau de experiência. Tecnicamente falando, os recursos gráficos do FireMonkey fazem uso da GPU do hardware, que é a unidade de processamento gráfico da máquina, possibilitando assim o trabalho com gráficos HD, 3D, efeitos de imagem e animações. Outro recurso disponível é sua conectividade com banco de dados, utilizada principalmente em aplicações de negócios. Para estes casos entra em cena o LiveBindings que é uma nova forma de ligação de dados apresentada também nesta versão XE2 do Delphi. Ao ser construída, uma aplicação FireMonkey pode ser direcionada nativamente para as plataformas Windows (32 e 64 bits), Mac (OS X) e iOS.

Conforme dito, o FireMonkey é apresentado como sendo de natureza multi-plataforma, ou seja, presume-se que ele rode em outras plataformas além da já tradicional Windows 32 bits (Win32). Assim sendo, uma aplicação construída com FireMonkey poderá rodar também em Windows 64 bits, Mac OS X e iOS. Outro detalhe diz respeito à premissa de que tais aplicações possuem um visual mais rico que o habitual, que se torna um atrativo a mais ao usuário final. Devido a esta característica aplicações FireMonkey necessitam e fazem uso da GPU (Unidade de Processamento Gráfico) do hardware.

Todavia, independente das “novas características” que uma aplicação possa ter, ela sempre estará direcionada a um contexto de negócio. Exemplo disso é a construção de uma aplicação somente para fins de estudo, ou para elaboração de um aplicativo utilitário e ainda nos casos mais corriqueiros, aplicações comerciais. Neste ponto todas se parecem em um ponto fundamental que é o seu trabalho com dados, ou seja, as informações pertinentes do negócio que a aplicação está inserida. Em situações como esta, é comum a utilização de banco de dados para o armazenamento dos dados e consequentemente o vínculo deste com o aplicativo. No Delphi, este tipo de atividade é feito, tradicionalmente, com as aplicações do tipo VCL Forms Application. Contudo, com a chegada do FireMonkey, ganha-se mais uma alternativa de desenvolvimento nativo e é justamente neste ponto que este artigo pretende dar o start necessário ao desenvolvedor que queira dar os primeiros passos nesta nova plataforma de desenvolvimento apresentada pela Embarcadero. Assista ao vídeo:

Trabalhando com banco de dados em aplicações FireMonkey

Para se ter uma noção clara do que esperar do FireMonkey para a construção de aplicações com conectividade a banco de dados, nada melhor do que fazer um comparativo com a forma que já estamos acostumados a trabalhar, ou seja, através do desenvolvimento de aplicações do tipo VCL Forms Application.

No Delphi, ao se construir aplicações deste tipo e que fazem acesso a banco de dados são utilizadas tecnologias responsáveis por estabelecer a conexão e prover toda a interatividade necessária entre aplicação e banco. Eles fazem o intermédio entre as duas partes e são representados pelos componentes de acesso a dados, providos tanto nativamente pelo IDE quanto por terceiros (comerciais ou não). São exemplos nativos os componentes dos grupos dbExpress, DataSnap, InterBase e dbGo, cada qual com sua especialidade e propósito. Por exemplo, se a aplicação fará acesso a um banco Firebird, a opção mais sensata é fazer uso dos componentes DBX, do grupo dbExpress, que possui um driver específico para o SGBD. Na mesma medida, se o banco em questão for Interbase, da própria Embarcadero, os componentes IBX do grupo Interbase são os mais otimizados para o processo. Para SQL Server, os componentes ADO, do grupo dbGo são os mais tradicionais. Finalmente, caso a aplicação faça parte de uma estrutura multicamadas e, portanto, deverá acessar um servidor de aplicação, o uso de DataSnap é imprescindível.

Tomando como base a utilização do Firebird como SGBD e seu banco de dados de exemplo que acompanha sua instalação, denominado Employee, a definição inicial desta conexão numa aplicação VCL se dá no Data Explorer do próprio IDE. Este processo básico define o uso da tecnologia dbExpress. Quando usamos este tipo de abordagem, o famoso trio de componentes (SQLDataSet ou SQLQuery + DataSetProvider + ClientDataSet) se faz presente na maioria dos casos, juntamente de um componente de conexão central (SQLConnection). Meramente como demonstração a seguir temos na Listagem 1 o código de um objeto de conexão SQLConnection, mapeado para o banco de dados mencionado.


object Employee: TSQLConnection
    ConnectionName = 'Employee'
    DriverName = 'FIREBIRD'
    GetDriverFunc = 'getSQLDriverINTERBASE'
    LibraryName = 'dbxfb.dll'
    LoginPrompt = False
    Params.Strings = (
      'drivername=FIREBIRD'
      'librarynameosx=libsqlfb.dylib'
      'vendorlibwin64=fbclient.dll'
      'vendorlibosx=/Library/Frameworks/Firebird.framework/Firebird'
      'blobsize=-1'
      'commitretain=False'
        'Database=localhost:C:\Program Files\Firebird\Firebird_2_5\exampl' +
        'es\empbuild\EMPLOYEE1.FDB'
      'localecode=0000'
      'Password=masterkey'
      'rolename=RoleName'
      'sqldialect=3'
      'isolationlevel=ReadCommitted'
      'user_name=sysdba'
      'waitonlocks=True'
      'trim char=False'
      'ServerCharSet=WIN1252')
    VendorLib = 'fbclient.dll'
  end
Listagem 1. SQLConnection

Após isso, o processo natural se encaminha pela definição da tabela do banco a ser manipulada pela aplicação, através de um componente TSQLDataSet. Hipoteticamente ao optar pela tabela denominada Country, teríamos um objeto definido da seguinte forma:


object COUNTRY: TSQLDataSet
    SchemaName = 'sysdba'
    CommandText = 'select * from COUNTRY'
    DbxCommandType = 'Dbx.SQL'
    Params = <>
    SQLConnection = Employee
end

Finalizando, por motivos de boas práticas e além de poder trabalhar com os dados em memória, o uso de um TDataSetProvider e de um TClientDataSet acabariam por definir a estrutura inicial da aplicação, em termos de conectividade. Já para a manipulação em tela das informações obtidas da tabela do banco, em aplicações VCL temos a presença dos controles data-aware que têm a capacidade de ler e escrever valores para um determinado campo (Field) informado. Controles estes que podem ser encontrados nativamente no grupo Data Controls (Figura 1).

VCL - Data Controls
Figura 1. VCL - Data Controls

Tomando como base um simples TDBEdit, a definição do campo que se deseja manipular ocorre da maneira explícita através de sua propriedade DataField. A seguir temos o código do objeto que aponta o controle para um campo denominado CURRENCY, da tabela.


object DBEdit1: TDBEdit    
  DataField = 'CURRENCY'
  DataSource = DataSource1
end

Fazendo um comparativo desta forma tradicional com as novas aplicações FireMonkey, a parte de conexão com banco de dados permanece inalterada, ou seja, é possível utilizar os mesmos grupos de componentes, sendo dbExpress e DataSnap as tecnologias recomendadas pela Embarcadero. Com isso, tem-se um reaproveitamento de conhecimento inicial. No entanto a grande diferença em relação ao desenvolvimento VCL diz respeito à forma que se dá a manipulação dos dados de uma tabela em tela. Isto porque o FireMonkey não possui controles data-aware, como os do grupo DataControls da VCL onde é possível simplesmente apontá-lo a um DataSet através de um TDataSource, e então selecionar determinado Field. Tomando como base o que foi mostrado até aqui, no FireMonkey ao invés de TDBEdit, temos um simples TEdit. Neste ponto a grande questão que inevitavelmente surge deve ser: é realmente possível construir uma aplicação FireMonkey com acesso a banco de dados? Se sim, de que forma isso é possível? A resposta para isso é LiveBindings.

Este novo recurso, como será visto adiante, faz com que os controles FireMonkey tornem-se data-aware e passem a se comportar conforme ao que já estamos acostumados em aplicações VCL. Isto acontece porque o FireMonkey utiliza-se de outros componentes LiveBinding para fazer o movimento de dados entre os componentes de acesso a dados e seus próprios controles. Dessa forma, o código do objeto TDBEdit que tínhamos na VCL, em FMX seria substituído por um TEdit simples, sem indicação de Field:


object Edit1: TEdit
Position.Point = '(24,40)'
Width = 100.000000000000000000
Height = 22.000000000000000000
TabOrder = 0
ReadOnly = False
Password = False
Text = ''
end

Tal indicação se dará em um objeto de binding, conforme mostrado a seguir:


object DBLinkEdit1Currency1: TBindDBEditLink
      Category = 'DB Links'
      DataSource = BindScopeDB1
      FieldName = 'Currency'
      EditControl = Edit1
end

Neste caso, o tipo do objeto em questão é um TBindDBEditLink, que é o tipo utilizado para se conectar um controle FireMonkey a um Field de um componente de dados e que será visto em detalhes na parte prática do artigo. Ainda sobre o código apresentado, o detalhe fica por conta das propriedades EditControl e FieldName. A primeira aponta para o controle envolvido no binding enquanto que a segunda aponta para o nome do Field que se deseja vincular.

LiveBindings

Assim como o FireMonkey, o LiveBindings é uma das novidades da nova versão do Delphi, a XE2. Em suma, ele é o mais novo recurso para ligação de dados em aplicações Delphi, sejam elas VCL ou FireMonkey, e que se baseia em expressões para interligar objetos através de suas propriedades. Para quem utiliza ou já utilizou as tecnologias WPF e Silverlight, através do Delphi Prism, o recurso de binding destas é muito similar.

As expressões utilizadas pelo LiveBindings são do tipo relacional, conhecidas como Binding Expressions. Estas podem ser do tipo unidirecional ou bidirecional, que é a característica que define o fluxo dos dados na ligação. Normalmente, esta ligação se dá entre objetos distintos através de uma ou mais de suas propriedades, num processo que à grosso modo estabelece uma relação entre objetos de origem e destino, onde o primeiro é quem provê os dados ao segundo. No LiveBindings estes objetos são tecnicamente nomeados, respectivamente, como source objects (objetos de origem) e control objects (objetos de controle). Nesta mesma linha há ainda a possibilidade de se ter um objeto ligado a si mesmo, ou seja, o próprio objeto se coloca no papel de origem e destino.

Um exemplo bem corriqueiro deste tipo de funcionalidade é poder refletir instantaneamente o texto que é digitado em uma caixa de entrada (um TEdit ou um TMemo, por exemplo) em outro controle de exibição, como um TLabel. Na Figura 2 temos o esboço de uma interface visual de uma aplicação VCL tradicional com esse propósito.

Na prática, o Delphi provê todo este processo de forma visual através do trabalho com propriedades chaves presentes nos componentes visuais de aplicações VCL e FireMonkey, via Object Inspector. Além destes o LiveBindings conta ainda com componentes específicos, disponíveis no novo grupo homônimo presente na Tool Palette (Figura 3). Obviamente é possível também definir toda a mecânica de binding programaticamente, ou seja, via código, para casos específicos. Por não ser tão intuitiva quanto à definição visual, a própria Embarcadero a recomenda somente para aplicações do tipo Console.

Para se ter uma noção clara do trabalho com LiveBindings e assim obter uma amostragem prévia do que acontece na prática numa futura aplicação FireMonkey, será feita uma explicação evolutiva, começando pela maneira mais tradicional de apresentá-los, que é através de uma aplicação do tipo VCL Forms Application. Desta forma, partindo da interface apresentada anteriormente serão mencionados rapidamente os passos básicos envolvidos para a definição da funcionalidade. Neste ponto, de acordo com a premissa da aplicação o objetivo a ser atingido é fazer com que a aplicação replique instantaneamente o texto digitado no controle TEdit (edtTexto) no controle TLabel (lblTexto). Tenha em mente que o controle TEdit será o objeto de origem (source object), enquanto que TLabel será o objeto de controle (control object).

O passo inicial diz respeito à necessidade da presença de um componente TBindingList que serve para centralizarmos e gerenciarmos a lista de bindings criados, assim como acontece com o TActionList, que centraliza e gerencia ações presentes numa aplicação. Dito isto, é nele que se deve criar o novo objeto binding do tipo TBindExpression. Esta primeira etapa também pode ser iniciada a partir do objeto de controle através do menu de contexto de sua propriedade LiveBindings, conforme é mostrado na Figura 4. Fazendo isso, o próprio IDE se encarrega de mostrar uma caixa de diálogo com a lista dos possíveis tipos de objetos LiveBindings que podem ser criados (Figura 5), bem como em seguida adiciona automaticamente um componente TBindingList já com o novo Binding criado.

Interface visual –
Aplicação VCL Forms
Figura 2. Interface visual – Aplicação VCL Forms
Novo grupo de componentes - LiveBindings
Figura 3. Novo grupo de componentes - LiveBindings
Menu de
contexto da propriedade LiveBindings
Figura 4. Menu de contexto da propriedade LiveBindings
Tipos de LiveBinding
Figura 5. Tipos de LiveBinding

No TBindingList podemos visualizar o TBindingExpression criado (Figura 6). Dentre suas propriedades algumas merecem destaque, reforçando a teoria sobre LiveBindings apresentada inicialmente. SourceComponent e ControlComponent referem-se, obviamente, aos objetos de origem (source) e destino (control) envolvidos, neste caso, edtTexto e lblTexto respectivamente. Uma vez definidos os objetos faz-se necessária também a indicação da expressão a ser utilizada por cada um. Dessa forma, a propriedade ControlExpression que é a expressão relacionada a ControlComponent, recebe como valor Caption, pois esta é a propriedade do componente TLabel (lblTexto) que deverá ser manipulada. Semelhante a isso, SourceExpression> fará menção ao nome da propriedade do objeto definido em SourceComponent, ou seja, Text. Isto porque o Binding necessitará pegar o valor atribuído à propriedade Text do componente TEdit (edtTexto).

Outro item que merece destaque é a propriedade denominada Direction que diz respeito à direção do fluxo dos dados na ligação (Binding) que está sendo estabelecida. São três seus valores possíveis:

  • SourceToControl: esta é a opção marcada por padrão. Ela diz que o fluxo das informações se dará do objeto origem ao destino, ou seja, de Source para Control. É o que será utilizada no exemplo;
  • ControlToSource: define o fluxo inversamente à opção anterior, ou seja, as informações irão do objeto definido como Control para o objeto Source;
  • Bidirectional: como o próprio nome sugere, esta opção faz um mix das outras duas. Os dados trafegam tanto de Source para Control quanto o inverso.
BindExpression
Figura 6. BindExpression

Uma vez definido o LiveBindings ainda se faz necessário uma última etapa para que tudo funcione conforme o esperado, que diz respeito à notificar o mecanismo de expressão (expression engine) sobre as mudanças ocorridas na expressão de entrada. Isto é necessário porque o tipo de Binding criado é gerenciado, ou seja, tem sua propriedade Managed marcada como True. Em outras palavras isso significa que o binding é avaliado automaticamente quando um objeto ou uma propriedade na expressão de entrada é modificado. De forma inversa, um binding não-gerenciado necessita ser avaliado de forma explícita e manualmente.

No nosso caso a expressão de entrada é a propriedade Text do componente edtTexto. Neste caso o evento adequado para se monitorar as mudanças ocorridas em TEdit é seu evento OnChange. O código a seguir mostra a codificação necessária para a notificação das mudanças ao mecanismo de expressão. Para isso apenas uma única linha de código é o suficiente, onde é chamado o método Notify do próprio objeto TBindingList. Este método recebe dois parâmetros, sendo o primeiro o objeto em questão e o segundo a propriedade afetada. Ainda sobre este último parâmetro, caso ele fosse passado em branco, todos os bindings que fazem referência ao objeto em questão seriam avaliados no mesmo momento.


procedure TfrmTestLiveBindings.edtTextoChange(Sender: TObject);
begin
  BindingsList1.Notify(edtTexto, 'Text');
end; 

FireMonkey, LiveBindings e dbExpress

A parte prática do artigo visa apresentar os passos básicos e essenciais para se construir uma aplicação FireMonkey com conectividade a banco de dados. Como já mencionado anteriormente para que isso se torne possível é imprescindível também o uso de outra tecnologia – o Live Bindings – que ficará responsável por fazer a ligação de dados entre os controles visuais e os componentes de dados. Perceba que somente com esta prática já nos atualizamos perante as novidades apresentadas pela nova versão, XE2, do Delphi, dando o start para futuros estudos sobre estas tecnologias e utilização das mesmas em projetos do seu cotidiano.

Como o intuito aqui é dar um enfoque maior na teoria e nos conceitos envolvidos no processo de desenvolvimento para este tipo de aplicação, o projeto de exemplo será bem enxuto. O mesmo possuirá uma única tela principal responsável por fazer a manutenção dos cadastros de contatos pessoais. Os dados envolvidos serão salvos um banco de dados Firebird que já dá margens para utilização de outra tecnologia, o dbExpress. A escolha deste grupo de componentes para acesso a dados se deu pelo fato da sua grande usabilidade pela comunidade Delphi, pela presença de um driver exclusivo e nativo para o SGBD, além da praticidade em se utilizar o Data Explorer do IDE para gerência da conexão com o banco de dados.

Seguindo os passos de uma aplicação VCL tradicional a primeira etapa envolve a definição da base de dados. Pelo fato da aplicação ser trivial, o banco também é totalmente simples. Apenas para não deixar de mencionar e assim deixar o exemplo completo, a Listagem 2 mostra o script SQL utilizado para criá-lo.


SET SQL DIALECT 3;
SET NAMES WIN1252;
SET CLIENTLIB 'fbclient.dll';
 
CREATE DATABASE '[caminho_banco]\DBContatos.fdb'
USER 'SYSDBA' PASSWORD 'masterkey'
PAGE_SIZE 8192
DEFAULT CHARACTER SET WIN1252 COLLATION WIN1252;
 
CREATE TABLE CONTATOS (
    CONTATO_ID  INTEGER NOT NULL,
    NOME        VARCHAR(80),
    ENDERECO    VARCHAR(80),
    CIDADE      VARCHAR(80),
    UF          CHAR(2),
    TELEFONE    VARCHAR(15)
);
 
  ALTER TABLE CONTATOS ADD CONSTRAINT PK_CONTATOS 
  PRIMARY KEY (CONTATO_ID); 
Listagem 2. Script para criação da base de dados

Com o banco criado, para que se aproveite os recursos do Data Explorer basta se definir uma nova conexão do tipo Firebird, conforme já mostrado aqui em artigos anteriores. Dessa forma, posteriormente, pelo simples arrastar de uma tabela apresentada no Data Explorer para, por exemplo, um Data Module, serão inseridos automaticamente os componentes de acesso a dados necessários já configurados e prontos para uso. O único complemento necessário seria a inclusão de componentes TDataSetProvider, TClientDataSet e TDataSource. Para esta demonstração mantendo o foco em facilitar ao máximo o desenvolvimento, todos eles serão colocados no próprio formulário a ser construído.

O projeto que está sendo construído será do tipo FireMonkey HD Application, que é apenas um dos quatro novos tipos de projetos voltados para FireMonkey, apresentados nessa nova versão do Delphi. A Figura 7 exibe estas opções.

Novas opções de projeto, exclusivos para FireMonkey
Figura 7. Novas opções de projeto, exclusivos para FireMonkey

Essencialmente o FireMonkey foi nos apresentado como sendo uma tecnologia voltada para a criação de aplicações com interfaces mais ricas e que, entre outras coisas, oferece suporte a trabalho com gráficos 3D. Justamente por isso são providos tipos específicos para estas aplicações (3D Application), conforme pôde ser visto na imagem anterior. Além disso, nota-se a presença de dois tipos sufixados com iOS Application, que são providos para o desenvolvimento voltado para o sistema operacional móvel da Apple, o iOS (iPhone OS).

Sendo assim FireMonkey HD Application pode ser considerado o tipo mais tradicional dentre as opções. Ao selecioná-lo temos um processo parecido com o que acontece com uma VCL Forms Application, em que a estrutura da aplicação é automaticamente criada pelo IDE, mais especificamente um projeto contendo um Form padrão já adicionado. Este já vem aberto no Form Designer para o início do desenvolvimento, o detalhe é que enquanto na VCL este Form apresenta a extensão .dfm em FireMonkey o mesmo possui a nova extensão .fmx. Contudo, o arquivo de code-behind se mantém como .pas, com a única alteração se dando em sua seção Uses que possui agora o direcionamento para os namespaces da FMX, tais como FMX.Controls, FMX.Forms, FMX.Dialogs, ao invés de Vcl.Controls, Vcl.Forms, Vcl.Dialogs.

Um esboço da interface visual da aplicação de exemplo pode ser visto na Figura 8. Nela foram utilizados alguns tipos distintos de controles, como os tradicionais TLabel, TEdit e TButton que ganharam sua versão para FireMonkey, como também os exclusivos TBindNavigator e TComboEdit. Este último, aliás, é semelhante a um ComboBox comum da VCL em que podemos adicionar os itens de sua coleção através de sua propriedade Items, ao contrário do TComboBox> da FMX, que não dispõe deste recurso, sendo necessário ligá-lo a uma lista. Já TBindNavigator, como o próprio nome sugere, possui as mesmas características e comportamento de um TDBNavigator, que proporciona a manipulação do registros de uma fonte de dados, vide inserir, excluir, editar, navegar, etc.

Interface visual da aplicação de exemplo
Figura 8. Interface visual da aplicação de exemplo

Seguindo os passos de um desenvolvimento padrão, se faz necessário então ligar os controles em tela com cada campo do componente de dados. Como já dito, para que estes controles se tornem data-aware será feito uso de LiveBindings. Na prática a forma mais fácil de definir um LiveBindings entre um controle visual e um campo de uma tabela é utilizando sua propriedade LiveBindings, através da opção Link to DB Field. Somente por sua nomenclatura facilmente já podemos supor que se trata de um recurso exclusivo para a conectividade necessária para o presente contexto. Neste momento pela nova caixa de diálogo que é aberta, vemos que estamos definindo um novo DB Link que se relaciona a algum dos Fields do DataSet vinculado ao DataSource. Na Figura 9 é exibida a referida caixa de diálogo onde estão listados os campos (fields) disponíveis da tabela do banco. Portanto, este é o processo que deverá ser feito a cada um dos controles envolvidos (TEdit e TComboEdit), relativos aos campos da tabela.

Definindo novo DB Link
Figura 9. Definindo novo DB Link

Já na primeira definição de LiveBindings, o IDE se encarrega de adicionar automaticamente em tela outros dois componentes pertencentes ao grupo LiveBindings: TBindingList e TBindScopeDB. Em suma o primeiro, conforme já abordado anteriormente, irá centralizar e gerenciar a lista de bindings definidos, enquanto que o segundo se liga ao DataSource demarcando assim o escopo de banco de dados para o contexto, ou seja, indica a fonte de dados a ser utilizada pelo LiveBindings.

Para fixar, entenda o TBindScopeDB como um componente não-visual que provê uma forma de tornar os dados contidos em determinada fonte de dados, para qualquer componente que necessite acessá-los utilizando LiveBindings. Além disso, quando fazemos menção à TBindingsList, estamos nos referindo direta ou indiretamente ao uso de coleções de binding (ligações). Seja em aplicações VCL ou FireMonkey, cada LiveBinding criado na aplicação será encontrado em um BindingList. Tanto que ao se criar um novo LiveBinding através do ObjectInspector para determinado controle, um componente TBindingList é adicionado automaticamente no formulário em questão. Este provê ainda um editor de Binding, que pode ser acessado com um mero duplo-clique sobre o componente. A Figura 10 exibe editor, já com todos os LiveBindings definidos para este exemplo.

Editor de BindingsList
Figura 10. Editor de BindingsList

Através deste editor o desenvolvedor pode visualizar as informações necessárias para uma ideal configuração e manutenção dos LiveBindings definidos na aplicação. Algumas das operações que podem ser realizadas são: criar um novo Binding ou Binding Expression, excluir um Binding existente, visualizar Binding Expressions e visualizar as propriedades de um Binding. Além disso, existe ainda um editor de expressões para LiveBindings do tipo Binding Expressions que, ao contrário dos LiveBindings do tipo DB Link, necessitam da definição de uma expressão explícita para seu funcionamento. Através dela torna-se possível a edição visual dos parâmetros de uma expressão binding. Este editor é acessado também através de um duplo-clique, em cima de um Binding Expression qualquer. Ele pode ser visto na Figura 11.

Editor de BindExpression
Figura 11. Editor de BindExpression

Ciente disso o controle para navegação também deverá estar ligado a esta fonte para que as operações sobre o componente de dados possam ser feitas. Em vista disso, o próprio componente TBindNavigator já provê uma propriedade denominada BindScope, onde deverá ser apontada o TBindScopeDB devido. Complementando, o botão Apply irá fazer a chamado ao método ApplyUpdates do ClientDataSet e assim salvar efetivamente as informações na tabela do banco de dados. O processo de codificação da linguagem não muda pelo fato de estarmos trabalhando com FireMonkey, portanto o código do evento ficaria da seguinte forma:


procedure TfrmCadContatos.btnApplyClick(Sender: TObject);
begin
  if ClientDataSet1.ApplyUpdates(0) = 0 then
    ShowMessage('Registro salvo com sucesso!');
end;

Em uma situação comum, numa aplicação VCL, ao invés de ShowMessage poderíamos estar chamando o método MessageBox da classe TApplication (VCL.Forms.TApplication), conforme mostrado a seguir para uma mensagem mais customizada. No entanto vale lembrar que em FMX isso ainda não é possível, uma vez que sua classe TApplication (FMX.Forms.TApplication) não provê o método MessageBox como na VCL.


  Application.MessageBox('Registro salvo com sucesso!', 'Atenção', MB_ICONWARNING);

Para deixar a aplicação de exemplo totalmente funcional, a Listagem 3 apresenta a codificação dos eventos OnCreate e OnDestroy do formulário, que irá controlar a abertura e fechamento do TClientDataSet em tela, bem como o da conexão definida no componente TSQLConnection.


procedure TfrmCadContatos.FormCreate(Sender: TObject);
begin
  SQLConnection1.Connected := True;
  ClientDataSet1.Open;
end;
 
procedure TfrmCadContatos.FormDestroy(Sender: TObject);
begin
  ClientDataSet1.Close;
  SQLConnection1.Connected := False;
end;
Listagem 3. Codificação dos eventos Create e Destroy do Form

Já neste momento é possível fazer os primeiros testes com a aplicação. A melhor forma de se fazer isso é testando todas as operações disponíveis, como inclusão, alteração, exclusão e navegação. Nunca se esquecendo que, por estarmos utilizando a arquitetura dbExpress em conjunto com ClientDataSet, para se efetivar qualquer alteração deve-se sempre confirmar a operação através do botão Apply. Do contrário, as mudanças serão persistidas somente em memória, sendo perdidas ao finalizar o aplicativo. A Figura 12 mostra o exemplo já em execução, com dados sendo devidamente salvos no banco de dados.

Aplicação de exemplo em execução
Figura 12. Aplicação de exemplo em execução

Estilizando uma aplicação FireMonkey

Em aplicações Web quando se menciona a estilização de uma página HTML, está se fazendo referência à definição da apresentação dos documentos escritos nesta linguagem. Em outras palavras, define a forma visual de como a página será apresentada ao usuário. Para isso, comumente é utilizado um recurso denominado CSS (Cascading Style Sheets), que é uma linguagem de estilo utilizada exclusivamente para esta finalidade, colocando-se assim toda a formatação em um único documento a parte (.css), isolado da página HTML em si, mas vinculado à mesma. Em aplicações FireMonkey isto também é possível, e similarmente aos arquivos .css temos arquivos .style, que definem a apresentação visual da aplicação.

Uma aplicação FMX é composta por um conjunto de controles FireMonkey, os quais são compostos basicamente de sub-controles e formas primitivas, sendo lapidados por efeitos que tornam seu visual mais rico. Desta forma no FireMonkey os estilos são definidos a partir desta composição de recursos e armazenados em uma estrutura denominada style book (livro de estilos). Cada classe de controle FMX possui nativamente um estilo padrão, definido por código (hard coded). Isso pode ser visto em qualquer controle através do menu de contexto do objeto pela opção Edit Default Style. Ao fazer isso uma nova janela é aberta, denominada Style Designer, aonde o IDE exibe uma cópia exata do código interno que define o estilo. Exemplificando, o estilo padrão de um TEdit qualquer contido na aplicação de exemplo é mostrado na Figura 13.

Este estilo aparece nomeado como editstyle, referenciando a classe TLayout. Esta linha representa efetivamente o controle em si. Ainda sobre a estrutura apresentada, mesmo se tratando de um simples componente sua composição se mostra um tanto quanto complexa em vista de seus sub-elementos de variados tipos. Fazendo menção a alguns destes sub-elementos, o de nomeação background faz referência a um TRectangle, que dá forma à aparência retangular de fundo do controle. Conforme pode ser visto, ele contém dois elementos internos do tipo TColorAnimation, responsáveis pela animação de cores disparada pelo passar do mouse sobre o controle, causando um efeito visualmente agradável. Seguindo essa mesma linha de raciocínio os demais elementos são auto-denominativos, como content que define a área de conteúdo do controle e selection que determina a cor a ser utilizada pelo controle no momento de sua seleção.

Estilo padrão de um TEdit

Figura 13. Estilo padrão de um TEdit

A própria instalação do IDE já traz nativamente alguns destes arquivos de estilo, prontos para serem utilizados. Por defaul, eles ficam localizados na pasta de documentos públicos do Rad Studio, denominada Styles (C:\Users\Public\Documents\RAD Studio\9.0\Styles, em uma instalação em inglês). Apenas para citar, a própria nomenclatura destes arquivos dão uma idéia do que se pode esperar em termos visuais, tais como FMX.Platform.Mac.style, FMX.Platform.iOS.style e FMX.Platform.Win.style.

Vendo isso na prática iremos então adicionar o recurso de estilização em nossa aplicação de exemplo, que até o momento já está totalmente funcional. Em termos visuais apenas será necessário o acréscimo de um TButton. Será através dele que o usuário poderá então selecionar um novo estilo a ser aplicado instantaneamente na aplicação. Como será necessária uma seleção de arquivo, isso pode ser feito através do uso de um componente TOpenDialog já direcionado para o tipo de arquivo do estilo (.style), e apontado para o caminho padrão onde estão localizados. A seguir, é exibida a configuração das propriedades do objeto.


object OpenDialog1: TOpenDialog
    DefaultExt = '*.style'
    FileName = '*.style'
    Filter = 'Style(*.style)'
    InitialDir = 'C:\Users\Public\Documents\RAD Studio\9.0\Styles'
... 

Por fim, o diferencial nesta etapa se faz pela adição de um novo componente exclusivo às aplicações FireMonkey, denominado TStyleBook. Ele será o responsável por carregar o arquivo de estilo a ser aplicado na aplicação, podendo assim prover uma coleção de estilos ao formulário. Cada objeto TForm, por sinal, possui uma propriedade StyleBook, que recebe um objeto do tipo TStyleBook. Portanto, com o acréscimo de um objeto deste ao formulário de cadastro do projeto, a codificação do evento OnClick do botão deverá ser a apresentada na Listagem 4.


procedure TfrmCadContatos.btnStyleClick(Sender: TObject);
begin
  if OpenDialog1.Execute then
    StyleBook1.FileName := OpenDialog1.FileName;
end;
Listagem 4. Codificação do evento OnClick do botão referente a Style

Dentre as propriedades do componente TStyleBook a que interessa neste ponto é a FileName, que deverá receber o nome do arquivo de estilo, conforme mostra a listagem apresentada. A Figura 14 mostra a aplicação de exemplo estilizada com o arquivo FMX.Platform.iOS.style. A diferença visual é perceptível, em que alguns detalhes podem ser notados, como os cantos arredondados dos controles e as cores dos botões.

Aplicação de exemplo em execução e estilizada
Figura 14. Aplicação de exemplo em execução e estilizada

Ainda sobre o componente TStyleBook, um Form pode possuir N objetos deste tipo, no entanto, sua propriedade StyleBook pode fazer referência a somente um por vez. Esta propriedade nativamente apresenta-se sem valor algum definido, fazendo com que o Form faça uso do seu estilo padrão. Sendo assim, temos uma maneira facilitada de “limpar” qualquer estilização que tenha sido aplicada. Colocando esta ação em um botão, poderia se usar uma codificação semelhante à Listagem 5, onde é atribuído nil à propriedade StyleBook do formulário de cadastro da aplicação de exemplo.


procedure TfrmCadContatos.btnLimparEstiloClick(Sender: TObject);
begin
  Self.StyleBook := nil;
end;
Listagem 5. Codificação do evento OnClick do botão para se voltar à estilização padrão

Conclusão

Desde o lançamento da recente versão do Delphi, a XE2, estamos cada vez mais acompanhando suas inúmeras novidades, principalmente através da Web e de palestras, através dos eventos oficiais realizados pela própria Embarcadero. Ao mesmo tempo, a Clube Delphi mantém o compromisso em trazer ao leitor tudo o que está acontecendo no meio Delphi, tornando-se também uma fonte de informação à comunidade. O primeiro passo foi dado com o artigo que apresentou um overview das principais novidades dessa nova versão do IDE. A partir dele, abordagens dedicadas a assuntos específicos serão os temas de artigos futuros, assim como o presente artigo, onde o foco foi o FireMonkey.

O FireMonkey (ou FMX), assim como o LiveBindings, certamente foram duas das novidades que causaram mais frisson na comunidade, muito antes mesmo do lançamento efetivo da versão XE2, ainda no momento de seu anúncio. Isto se justifica pelo fato de ambos serem recursos relativos a áreas até então inexploradas pelo Delphi: criação de interfaces de usuário visualmente mais ricas e multi-plataforma e ligação de dados entre objetos através de expressões. Dessa forma, somente com esta premissa, os desenvolvedores puderam enxergar novas possibilidades de estudos e de negócios, causando uma expectativa enorme e inédita. Com a chegada do Delphi XE2, a eficácia destes elementos pôde enfim ser comprovada, e aos poucos os projetos atuais vão ganhando o acréscimo de tais recursos.

Assim sendo, este artigo procurou explorar um pouco mais a fundo esta mais recente plataforma de desenvolvimento da Embarcadero, o FireMonkey, culminando num exemplo prático onde foi exposto o seu uso com banco de dados. Em função disso, pôde ser vista a necessidade do uso de LiveBindings para a ligação entre controles visuais e componentes de dados, definindo assim a proximidade existente entre as duas novas tecnologias. Outro ponto a ser mencionado é que por se tratar de uma nova forma de desenvolvimento, o artigo teve a preocupação em traçar sempre que possível, paralelos com o desenvolvimento tradicional com a VCL. Indo um pouco além, a partir do que foi mostrado, fica fácil você começar a construir suas primeiras aplicações em FireMonkey, com o acréscimo de dbExpress e LiveBindings.


Saiba mais sobre Delphi ;)


Mais da DevMedia

  • O que é Delphi?: Este curso tem como objetivo apresentar uma tecnologia que está sempre se renovando para acompanhar as necessidades e tendências do mercado de desenvolvimento de software: o Delphi.
  • Guia de Referência Começando no Delphi: Neste Guia de Referência você encontrará o conteúdo que precisa para iniciar seus estudos em Delphi.
  • Boas práticas no Delphi: Neste guia você encontrará diversos materiais que lhe auxiliarão na aplicação de boas práticas de programação no Delphi. Com as melhores metodologias e padrões você poderá obter maior reusabilidade e qualidade do seu código.