INTRODUÇÃO
Bom pessoal, pretendo com esta série de artigos mostrar como criar uma aplicação usando tecnicas modernas de desenvolvimento em Perl fazendo uso do modulo MooseX::Declare.
Para isso resolvi que iria tramalhar com uma aplicação desktop e não com algo web. Usaremos para esta empreitada um modulo que nos permite criar telas de forma bem rápida e simples, o Tk (Toolkit).
Como não pretendo me prender a aspectos basicos da linguagem e tão pouco ao uso do módulo, imagino que o aspirante tenha conhecimentos em Perl (basicos~intermediarios) e que tenha uma boa base em desenvolvimento e estruturas de aplicações orientadas a objetos.
COMEÇANDO DO COMEÇO
Obviamente espero que voce tenha o MooseX::Declare instalado em sua maquina. Caso não o tenha, siga os simples passos a seguir:
$ sudo perl -MCPAN -e "install MooseX::Declare"
Importante lembrar que este modulo depende do Moose e sendo assim este será instalado para que o MooseX::Declare possa ser usado.
Agora vamos instalar o Tk:
$ sudo perl -MCPAN -e "install Tk"
Simples? Apos tudo instalado podemos começar.
ESTRUTURA
Abaixo vamos falar um pouco sobre a estrutura da aplicação. Pode não ser a melhor estrutura para fazermos uso mas é bem didática e isso garantirá um compreendimento por um maior numero de leitores.
+ – /calc
– calc.pl
+ – /App
+ /Form
– Base.pm
– Main.pm
SOBRE A ESTRUTURA
A aplicacao sera inicializada pela classe calc.pl que executará o nosso formulario principal (Main.pm), que por sua vez herdará habilidades comuns para as classes de formulários implementadas na classe Base.pm
CHAMANDO O FORMULÁRIO PRINCIPAL
Vamos criar nosso arquivo chamado calc.pl que fará a chamada do nosso formulário principal.
#!/usr/bin/perl
use strict;
use warnings;
use App::Form::Main;
my $app = App::Form::Main->new;
$app->start;
=> Explicando:
Neste arquivo nos criamos uma instancia da classe que representa nosso formulário (tela) principal e invocamos o metodo C que faz com que a tela seja apresentada ao usuário.
A BASE DE TODOS OS FORMS
Neste momento vamos criar uma classe que servirá de base para todos os outros FORMs. Esta classe terá metodos comuns que serão usados pelas telas do sistema.
use MooseX::Declare;
# start Tk base class
class App::Form::Base {
use Tk;
# Tk class attribute
has "window" => (
is => 'rw',
lazy => 1,
default => sub {
return MainWindow->new;
}
);
# method that config window widgets
method init {
die "Not implemented";
}
# method that start main window
method start {
$self->init;
return MainLoop;
}
}
=> Explicando:
Nesta classe nos temos uma implementação generica que disponibiliza um atributo que retorna uma instancia de uma janela.
O metodo C será utilizado para configurar os widgets (botoes, caixas de texto, menus, etc), e o C “executará” a criacao da janela propriamente dita.
CONSTRUINDO NOSSA TELA
Neste momento construiremos a nossa tela propriamente dita.
use MooseX::Declare;
# start Tk main window class
class App::Form::Main extends App::Form::Base {
# class attributes
has 'content' => ( is => 'rw' );
has 'display' => ( is => 'rw' );
has 'buttons01' => ( is => 'rw' );
has 'buttons02' => ( is => 'rw' );
has 'buttons03' => ( is => 'rw' );
has 'buttons04' => ( is => 'rw' );
has 'buttons05' => ( is => 'rw' );
has 'buttons06' => ( is => 'rw' );
has 'buttons07' => ( is => 'rw' );
has 'buttons08' => ( is => 'rw' );
has 'buttons09' => ( is => 'rw' );
has 'buttons00' => ( is => 'rw' );
has 'dot' => ( is => 'rw' );
has 'percent' => ( is => 'rw' );
has 'plus' => ( is => 'rw' );
has 'minus' => ( is => 'rw' );
has 'multiply' => ( is => 'rw' );
has 'divide' => ( is => 'rw' );
has 'c' => ( is => 'rw' );
has 'ce' => ( is => 'rw' );
has 'back' => ( is => 'rw' );
has 'equals' => ( is => 'rw' );
# method that start main window
override init {
my $menu = $self->window->Menu();
# config main window
$self->window->title('Modern Perl - Calculator');
$self->window->configure(
-menu=>$menu
);
# setting up menu
my $help = $menu->Menubutton(-text=>'Ajuda');
$help->command(-label=>'Sobre');
# calculator content
$self->content($self->window->Frame(
)->pack( -fill=>'both', -expand=>1, -ipadx=>135, -ipady=>145 )
);
# display screen
$self->display($self->content->Entry(
-text=>'',
-background=>'white',
)->place(
-y=>10,
-x=>10,
-height=>50,
-width=>250,
)
);
# clear button
$self->c($self->content->Button( -text=>'C', -command=> sub{ $self->clear_all }
)->place( -x=>216, -y=>75, -width=>42, -height=>42)
);
# ce button
$self->ce($self->content->Button( -text=>'CE', -command=> sub{ }
)->place( -x=>216, -y=>127, -width=>42, -height=>42)
);
# back button
$self->back($self->content->Button( -text=>' sub{ }
)->place( -x=>216, -y=>179, -width=>42, -height=>42)
);
# equals button
$self->equals($self->content->Button( -text=>'=', -command=> sub{ }
)->place( -x=>216, -y=>229, -width=>42, -height=>42)
);
# plus button
$self->plus($self->content->Button( -text=>'+', -command=> sub{ }
)->place( -x=>164, -y=>229, -width=>42, -height=>42)
);
# plus button
$self->plus($self->content->Button( -text=>'+', -command=> sub{ }
)->place( -x=>164, -y=>229, -width=>42, -height=>42)
);
# minus button
$self->minus($self->content->Button( -text=>'-', -command=> sub{ }
)->place( -x=>164, -y=>177, -width=>42, -height=>42)
);
# multiply button
$self->multiply($self->content->Button( -text=>'x', -command=> sub{ }
)->place( -x=>164, -y=>125, -width=>42, -height=>42)
);
# divide button
$self->divide($self->content->Button( -text=>'/', -command=> sub{ }
)->place( -x=>164, -y=>75, -width=>42, -height=>42)
);
# percent button
$self->percent($self->content->Button( -text=>'%', -command=> sub{ }
)->place( -x=>112, -y=>229, -width=>42, -height=>42)
);
$self->dot($self->content->Button( -text=>'.', -command=> sub{ $self->set_value( '.' ); }
)->place( -x=>62, -y=>229, -width=>42, -height=>42)
);
$self->buttons00($self->content->Button( -text=>'0', -command=> sub{ $self->set_value( 0 ); }
)->place( -x=>10, -y=>229, -width=>42, -height=>42)
);
$self->buttons01($self->content->Button( -text=>'1', -command=> sub{ $self->set_value( 1 ); }
)->place( -x=>10, -y=>177, -width=>42, -height=>42)
);
$self->buttons02($self->content->Button( -text=>'2', -command=> sub{ $self->set_value( 2 ); }
)->place( -x=>62, -y=>177, -width=>42, -height=>42)
);
$self->buttons03($self->content->Button( -text=>'3', -command=> sub{ $self->set_value( 3 ); }
)->place( -x=>112, -y=>177, -width=>42, -height=>42)
);
$self->buttons04($self->content->Button( -text=>'4', -command=> sub{ $self->set_value( 4 ); }
)->place( -x=>10, -y=>125, -width=>42, -height=>42)
);
$self->buttons05($self->content->Button( -text=>'5', -command=> sub{ $self->set_value( 5 ); }
)->place( -x=>62, -y=>125, -width=>42, -height=>42)
);
$self->buttons06($self->content->Button( -text=>'6', -command=> sub{ $self->set_value( 6 ); }
)->place( -x=>112, -y=>125, -width=>42, -height=>42)
);
$self->buttons07($self->content->Button( -text=>'7', -command=> sub{ $self->set_value( 7 ); }
)->place( -x=>10, -y=>75, -width=>42, -height=>42)
);
$self->buttons08($self->content->Button( -text=>'8', -command=> sub{ $self->set_value( 8 ); }
)->place( -x=>62, -y=>75, -width=>42, -height=>42)
);
$self->buttons09($self->content->Button( -text=>'9', -command=> sub{ $self->set_value( 9 ); }
)->place( -x=>112, -y=>75, -width=>42, -height=>42)
);
}
# Action that set method to Entry display
method set_value ( $value ){
$self->display->insert('end', $value);
# DEBUG: remove it
print "$value - ". $self->display->get() ."\n";
}
# Action that clear last number
method clear_last {
# TODO: get all display value, split by operators and remove last number
}
# Action that clear all display value
method clear_all {
$self->display->delete('0', 'end');
}
}
=> Explicando:
Esta classe cria a nossa tela, que e a de uma calculadora simples onde implementaremos a nossa solução.
O desenvolvimento da tela não existe segredo, nos só declaramo as propriedades da classe (uma para cada widget), contruimos e configuramos os widgets conforme a nossa necessidade.
CONCLUSÃO
Com este exemplo simples, podemos ver o quanto foi simples e rápido escrever uma app usando o MooseX::Declare. No próximo artigo, pretendo abordar a implementação das rotinas de calculo deste exemplo.