Pages

Sunday, February 5, 2012

Pyjamas: Um Web Toolkit prático e simples para o desenvolvimento de aplicações AJAX

Nesse novo post, gostaria de demonstrar um pouco sobre uma ferramenta que caiu como uma luva em um dos projetos que iniciei a pouco tempo: o framework Pyjamas. O Pyjamas se auto define como um compilador Python-to-JavaScritp. Isso significa, na verdade, que ele é capaz de gerar um script em JavaScript a partir de códigos feitos em Python.

Inclusive, as bibliotecas do Pyjamas incorporam um Web Toolkit capaz de gerar Web Widgets. Em outras palavras, com o Pyjamas você pode criar sites com visuais no estilo Desktop, por exemplo. Sites com menus dinâmicos, botões, barras, diálogos, etc. Por esse motivo, pode se dizer que o Pyjamas é uma ferramenta quase alternativa ao Google Web Toolkit (GWT). Só não é por completo pelo fato daquela utilizar chamadas das bibliotecas do GWT para suprir algumas deficiências que ela ainda possui.

No nosso caso, construir todo um sistema Web fazendo uso de AJAX, HTML e CSS seria muito custoso e levaria a muito tempo de desenvolvimento. Com esse Web Toolkit, nos preocupamos somente com a disposição dos elementos do site e com o estilo dele (CSS). Sobrando um enorme tempo para nos dedicar a funcionalidade e operacionalidade do sistema.


Exemplo do uso

Irei, a seguir, somente mostrar um breve exemplo do uso do Pyjamas, uma vez que você encontra muito material com qualidade no site da ferramenta.

Para inicio, você precisa obviamente da própria ferramenta. Há três modos de obtê-la: via apt-get (em sistemas Debian-like), fazendo o Download via link ou baixando o repositório git pelo,

git clone git://pyjs.org/git/pyjamas.git

Eu recomendaria o Download tanto do código-fonte quanto do repositótio git. A versão da ferramenta via apt-get é mais antiga e dá mais problemas na construção do que as citadas anteriormente.

Siga toda a instrução de compilação e construção do Pyjamas descrita nos arquivos do framework e pronto. Após construído, note que fora criado a pasta 'bin'. Todas as ferramentas provenientes do Pyjamas se encontram neste diretório:
  • pyjsbuild: compila o código em Python e constrói toda a sua página web com JavaScript;
  • pyjd: um Depurador (Debugger);
  • pyjscompile: o próprio compilador sem construção de output;
  • pyjampiler: também é (alternativo) um compilador um pouco menor que o pyjscompile;
Podemos construir cada classe em um arquivo separado fazendo as importações necessárias, porém iremos montar o script em um único arquivo para facilitar o exemplo.

Para iniciarmos nosso script, importamos as bibliotecas que serão utilizadas,

from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.SimplePanel import SimplePanel
from pyjamas.ui.HorizontalPanel import HorizontalPanel
from pyjamas.ui import HasAlignment
from pyjamas.ui.Image import Image
from pyjamas.ui.Button import Button
from pyjamas.ui.ToggleButton import ToggleButton
from pyjamas.ui.MenuBar import MenuBar
from pyjamas.ui.MenuItem import MenuItem
from pyjamas import Window

Nesse exemplo, iremos mostrar a criação de uma Barra de Menus e dois botões, um normal e um toggle.

Começaremos pela classe que irá representar a Barra de Menus.

class MenubarExample(SimplePanel):
    def __init__(self):
        SimplePanel.__init__(self)
     
        menu1 = MenuBar(vertical=True)
        menu1.addItem("Open", getattr(self, "onMenuItemOpen"))
        menu1.addItem("Save As...", getattr(self, "onMenuItemSaveAs"))

        menu2 = MenuBar(vertical=True)
        menu2.addItem("Undo", getattr(self, "onMenuItemUndo"))
        menu2.addItem("Redo", getattr(self, "onMenuItemRedo"))
             
        menu3 = MenuBar(vertical=True)
        menu3.addItem("Help", getattr(self, "onMenuItemHelp"))
        menu3.addItem("About", getattr(self, "onMenuItemAbout"))

        menubar = MenuBar(vertical=False)
        menubar.addItem(MenuItem("File", menu1))
        menubar.addItem(MenuItem("Edit", True, menu2))
        menubar.addItem(MenuItem("About", True, menu3))
     
        self.add(menubar)

    def onMenuItemOpen(self):
        Window.alert("Item Open selected")

    def onMenuItemSaveAs(self):
        Window.alert("Item Save As selected")

    def onMenuItemUndo(self):
        Window.alert("Item Undo selected")

    def onMenuItemRedo(self):
        Window.alert("Item Redo selected")
    
    def onMenuItemHelp(self):
        Window.alert("Item Help selected")
 
    def onMenuItemAbout(self):
        Window.alert("Item About selected")

E a classe que corresponde a barra com os dois botões é apresentada a seguir:

class PanelExample(SimplePanel):
    def __init__(self):
        SimplePanel.__init__(self)
     
        hPanel = HorizontalPanel(BorderWidth=0,
                        HorizontalAlignment=HasAlignment.ALIGN_CENTER,
                        VerticalAlignment=HasAlignment.ALIGN_MIDDLE,
                        Width="110px",
                        Height="20px")
         
        newButton = Button("Click Me",
                        getattr(self, "onNewButtonClick"))
     
        newToggleButton = ToggleButton("Up", "Down",
                        getattr(self, "onToggleButtonClick"))
     
        hPanel.add(newButton)
        hPanel.add(newToggleButton)
        self.add(hPanel)

    def onNewButtonClick(self):
        Window.alert("New Button Selected ")

    def onToggleButtonClick(self):
        Window.alert("Toggle Button Selected")

Por fim, é necessário implementar uma classe que possua a função onModuleLoad() que incluirá os paineis e menus criados.

class ControlExample:
    def onModuleLoad(self):
        menubar = MenubarExample()
        RootPanel().add(menubar)
     
        panel = PanelExample()
        RootPanel().add(panel)

Finalizando, criaremomos a função main.

if __name__ == '__main__':
    app = ControlExample()
    app.onModuleLoad()

Este script pode ser construído via 'pyjsbuild nome_do_script.py'. Todos os arquivos produzidos estarão no diretório 'output'. Para debugá-lo, basta inserir o parametro '-d' no comando acima.

No arquivo HTML você pode incluir o CSS para melhorar a aparência de sua página. Um exemplo seria,

.gwt-MenuBar {
   background-color: #FFF;
   border: 1px solid #333;
   cursor: default;
}

.gwt-MenuBar .gwt-MenuItem {
   padding: 1px 4px 1px 4px;
   font-size: smaller;
   cursor: default;
}

.gwt-MenuBar .gwt-MenuItem-selected {
   background-color: #EEE;
}

A saída produzida por nosso código, juntamente com o CSS acima, pode ser mostrada na figura abaixo.

Barra de Menus, um botão comun e um toggle.
Concluíndo, procuramos introduzir neste artigo  uma ferramenta extremamente prática na construção de sites mais dinâmicos ou sistemas Web. Com a utilização do framework Pyjamas, o desenvolvedor ganha muito mais tempo no desenvolvimento das suas aplicações.

Para quem gosta da linguagem Python e de desenvolvimento Web, vale a pena experimentar o Pyjamas.


Referências


Monday, January 30, 2012

Uma visão básica e essencial sobre Autotools - Parte II


Nessa segunda parte veremos como gerar um makefile a partir do comando Automake, inserir bibliotecas e outros comandos e informações necessárias.

Na Parte I, geramos um script que verifica as dependências e configurações do sistema para a compilação dos códigos-fonte: o 'configure'. A partir da execução desse script, temos a geração do Makefile e assim podemos compilar nosso código.

Antes de continuarmos, vamos sanar o problema da falta do arquivo "config.h.in". Para isso, executamos simplesmente,

autoheader

Verificamos que, se executarmos o script 'configure' novamente, o erro "config.status: error: cannot find input file: `config.h.in'" não será exibido e ao invés disso, ele criará o arquivo "config.h".

Tal arquivo é o que garante a portabilidade do código no momento da compilação. Nele é possível colocar as definições necessárias para as diretivas de compilação, por exemplo.


Gerando um Makefile a partir do Automake

Uma das características mais interessantes dessas ferramentas, na minha opinião, é justamente essa: poder gerar um makefile completo e de forma automática. Primeiramente, devemos incluir o comando no nosso script que indica a criação de um Makefile automatico. Portanto, no arquivo "configure.ac" incluímos o seguinte trecho,

...
C_PREREQ([2.67])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([src/helloworld.c])
AC_CONFIG_HEADERS([config.h])
...

Continuando, devemos agora renomear nosso simples Makefile criado inicialmente para 'Makefile.in',

mv Makefile Makefile.in

Ou seja, nosso makefile servirá como input para a criação do novo arquivo. E, antes de executar o comando principal, executamos,

aclocal

A execução cria o arquivo aclocal.m4 que por sua vez une todas as macros necessárias para a compilação, inclusive as definidas pelo programador, em um único arquivo.

Criamos o arquivo 'Makefile.am' para especificar os parametros a serem definidos pelo Automake. Abaixo um exemplo para nosso programa "hello world".

# Exemplo de Makefile.am

bin_PROGRAMS=helloworld
helloworld_SOURCES=src/helloworld.c

CLEANFILES=./*.o \
        helloworld

Enfim, executamos,

automake --add-missing --copy

Os parametros "--add-missing" e "--copy" fazem com que o automake copie arquivos necessários como o "install-sh" e "missing" que ainda não estão presente no nosso projeto.

A Saída da execução do comando em questão identificará a falta de alguns arquivos. A simples criação deles resolve o problema!

touch ./NEWS ./README ./AUTHORS ./ChangeLog

Os nomes dos arquivos são bem sugestivos às suas reais finalidades.


Incluindo bibliotecas específicas

Muitas vezes, nosso projeto necessita da importação de algumas bibliotecas e como elas são inseridas na configuração e geração do Makefile? A resposta é continuação desse tutorial.

Iremos utilizar duas bibliotecas a "math.h" e as bibliotecas da Glib.

Começando pela "math.h", alteremos o código do helloworld.c na pasta 'src/'.

// helloworld.c com Math.h

#include <stdio.h>
#include <math.h>

#define PI 3.1415926

int main(int argc, char *argv[]) {

float x = sin(PI/6);

printf("Seno de 60: %f\n", x);

return 0;
}

Inicialmente, devemos abrir o arquivo "configure.ac" e inserir o seguinte trecho em vermelho.

...
# Checks for libraries.
AC_CHECK_LIB(m, sin)
...

Lembre-se que quando compilamos, passamos o parâmetro "-lm" para incluir a "math.h". Logo o "m" representa tal parametro. A segunda entrada checa se existe a função "sin()" na biblioteca verificada.

Salve o arquivo "configure.ac" e execute,

autoreconf
make
./helloworld

Agora, a biblioteca "math.h" pode ser usada tranquilamente no projeto.

E se por um acaso, as libs estão em pastas específicas? Você pode adicioná-las antes da checagem acima usando,

LDFLAGS = "$LDFLAGS -L/local_da_sua_lib/"
CFLAGS = "$CFLAGS -I/local_da_sua_lib/"

No caso da Glib, quando pretendemos compilar um código-fonte que faz o uso da biblioteca usamos comumente o pkg-config passando o parametro: `pkg-config --cflags --libs glib-2.0`.

Para configurá-lo adequadamente devemos inserir o seguite código no arquivo 'configure.ac',

...
AC_CONFIG_HEADERS([config.h])

# Check libraries with pkg-config
PKG_CHECK_MODULES(GLIB, glib-2.0)

# Checks for programs.
AC_PROG_CC
...

Dessa forma, o script 'configure' irá verificar as dependências e adicionar o parâmetro citado automaticamente no Makefile gerado.

Por fim, toda a configuração necessária para incluir uma biblioteca na configuração do Automake usando duas maneiras diferentes de inclusão foi demonstrada acima.


O diretório autom4te.cache

Como fora dito na Parte I, nota-se que quando é executado o 'autoconf' uma pasta chamada autom4te.cache é criada. O intuito dela é guardar informações para que a execução de outras ferramentas como o 'autoheader' e o 'automake' seja facilitada. Ou seja, quando reconfiguramos alguns arquivos referentes ao 'automake' não é necessário executar toda vez o 'autoconf' porque os dados necessário já estão salvos (cached) no diretório 'autom4te.cache'. A sua presença não é vital para o projeto, mas a sua remoção força a execução do 'autoconf' toda vez que um comando precisar dos dados de saída do mesmo.


Conclusão

O Tutorial apresentado foi uma visão extremamente básica sobre a ferramenta GNU Autotools para que qualquer desenvolvedor interessado possa já configurar seu projeto facilmente e torná-lo portável. Há materiais na literatura e na internet de fácil acesso que abordam assuntos mais aprofundados. Inclusive, o próprio manual da ferramenta (como exemplo o Autoconf Manual) é um excelente guia de estudo avançado.


Referências Extras