Documentação do Tdk

   Tutorial / Módulo de Interface com o Usuário
Este tutorial tem como objetivo apresentar o módulo interface com o usuário, mostrando exemplos práticos de suas funcionalidades e observando suas particularidades.

Em construção a seção 4 !!!


 
Introdução

 

Este capítulo do tutorial apresentará os controles de interface gráfica de usuário. Ou seja, apresentará os widgets (ou controles). Um widget é um elemento da interface que o usuário interage como um canvas, uma janela, uma caixa de texto, um botão, um menu, etc.

A aplicação de exemplo que vamos utilizar neste tutorial é o VIPE (Visualização, Impressão, Processamento e Edição). Ele foi feito para testar as funcionalidades implementadas no Tdk.

Esta etapa do tutorial está dividida em 5 seções:


Seção 1

Na primeira seção, você conhecerá as funcionalidades implementadas no VIPE. Seguiremos os seguintes passos:

  • Instalação do VIPE
  • Visualização de um projeto exemplo no VIPE
  • Apresentação dos modos da aplicação: mapa, layout e impressão
  • Utilização da legenda
    • Ligar e desligar tema
    • Selecionar tema
    • Criar tema
    • Enquadrar tema
    • Mudar estilo dos objetos do tema
    • Mudar as propriedades do tema
    • Excluir um tema
    • Mover (para cima e para baixo) um tema
  • Apresentação das principais funcionalidades do modo de mapa:
    • Zoom, pan, fit, seleção de objeto
    • Inserir um objeto. Mostraremos como exemplos de objetos: ponto, linha, polígono e texto.
  • Apresentação das principais funcionalidades do modo de layout:
    • Zoom de papel, zoom no objeto mapa, pan, fit
    • Inserir um objeto. Mostraremos como exemplos de objetos: ponto, linha, polígono, texto, imagem.
    • Arrastar, redimensionar e rotacionar um objeto
  • Como imprimir utilizando o modo de impressão 

Seção 2

Na segunda seção, você aprenderá os conceitos básicos para interação com o canvas

  • Árvore VIX
    • Definição
    • Benefício 
  • Árvore de eventos TDK
    • Definição
    • Tratamento de eventos (mouse click, mouse move e teclado) na árvore
  • Estado de Aplicação
    • O que é um estado de aplicação
    • Como criar um novo estado de aplicação
    • Como registrar um estado de aplicação
    • Como criar um novo interador e uma nova tarefa

Seção 3

Na terceira seção, mostraremos como utilizar o TDK no modo de layout e de impressão.

  • Introdução
  • Exemplo de Criação de Novo Tipo de Objeto de Layout
    • Criação do Novo Tipo de Objeto de Layout
    • Utilização do Novo Tipo de Objeto de Layout - Criação e Registro de Estado de Interação, Criação de Tarefa e Criação de Interador

 


Seção 4
Na quarta seção, mostraremos como utilizar o TDK no modo de mapa

 


Seção 1 - VIPE

Nesta seção do tutorial veremos algumas funcionalidades do VIPE, através da descrição de etapas que vão desde a instalação da aplicação até a manipulação de objetos de um projeto.

 

1.1) Instalando e Executando o VIPE

Considerando que SVN_ROOT é o diretório onde foi feito o checkout do tdk pelo svn, o arquivo de solução que deve ser compilado é o SVN_ROOT\iupvipe\mak.vc71\iupvipe.sln. Temos então que compilar o arquivo da solução utilizando o Visual Studio .NET 2003. Para isso, acesse o menu Build -> Build Solution e aguarde a compilação das bibliotecas.

Para executar o VIPE pelo Visual Studio, após a compilação, aperte a tecla "F5" ou acesse pelo menu: Debug -> Start.   

Para executar fora do Visual Studio, clique duas vezes no nome do arquivo SVN_ROOT\bin\mtdebug\vc71\iupvipe\iupvipe.exe (conforme a figura abaixo). Este arquivo foi  gerado na compilação do projeto usando o Visual Studio.



1.2) Visualização de um projeto exemplo no VIPE

Agora com o VIPE executando precisamos nos conectar a banco de dados de exemplo. Utilizaremos neste tutorial o banco de dados ALPHA_Sergipe_2006_V1_04.mdb localizado no link disponibilizado.


Download do Banco:
ALPHA_Sergipe_2006_V1_04.mdb (32.4 Mb)

Para se conectar com o banco clique em Arquivo -> Conectar -> Access. Veja na figura abaixo.



Selecione então o banco no diretorio especificado.



Após a escolha do banco de dados, precisamos especificar o projeto que será utilizado. O projeto será o TerraEditProject.



O projeto será aberto e uma tela como a imagem a seguir será apresentada:



1.3) Os modos da aplicação: Mapa, Layout e Impressão

O VIPE possui três modos de visualização do projeto, cada um com suas respectivas funcionalidades, são eles: modo de visualização (ou modo mapa), modo de layout, e modo de impressão.

O modo mapa é utilizado para visualização e edição de objetos geográficos, ou seja, é possível manipular tanto a geometria dos objetos quanto seus atributos.

O modo de layout é utilizado para preparar a impressão ou geração de uma carta cartográfica. Neste modo é possível mexer em um "papel" que tem o mapa fazendo operações de zoom e de rotacionar.  Uma carta cartográfica é composta basicamente do mapa e de informações relacionadas a este mapa como legenda, norte (rosa dos ventos), escala gráfica, etc.

O modo de impressão permite a impressão do que foi definido através do layout. Ele funciona como um print preview, retratando exatamente o que do modo de layout será impresso.

Ao abrir um projeto no VIPE, ele o apresentará no modo de mapa. Para alternar entre os modos basta selecionar os botões referentes a cada um deles localizados no canto inferior direito da tela, conforme indicado na figura abaixo. Observe que para cada modo de visualização teremos funcionalidades ativadas ou desativadas.



Estaremos apresentando as principais funcionalidades dos três modos.

1.4) Utilizando a Legenda

A legenda é a visualização dos metadados de um projeto. Ela é apresentada no canto esquerdo da tela da aplicação, representando os objetos que compõe o projeto.

Um projeto é composto por visões (View). NO VIPE é possível ver apenas um projeto com uma visão.

Uma visão por sua vez é composta por temas ou grupos de temas.

O VIPE permite agrupar os objetos de um tema para visualizá-los em um mapa temático. O agrupamento é feito por atributos. Se for um atributo numérico por exemplo, o agrupamento pode ser feito por valor ou por intervalos.

Na figura ao lado, o projeto possui a visão "Mapa1". A visão por sua vez possui, o tema "Setas" e o grupo de temas "Recursos Socioeconômicos", e o tema  "Toponímia" dividido em temáticos.

(A definição de projeto, de Visão e de temas, pode ser encontrada no capítulo Modelo de Dados do Tdk)

 



Principais Funcionalidades:

Para ligar e desligar um tema basta clicar duas vezes sobre um tema específico com o botão esquerdo do mouse. Outra forma é clicar com o botão direito sobre o tema e selecionar Exibir/Esconder Tema(s). É interessante observar as alterações no mapa da visão após ligar ou desligar um tema. Os grupos de temas também podem ser ligados e desligados apenas com o duplo click. Já os temáticos não podem ser ligados ou desligados.

Para selecionar um tema, clique com o botão direito sobre o tema e selecione a opção Selecionar Tema.  Note que os temáticos e os grupos de temas não podem ser selecionados.

Para criar um tema, clique com o botão direito do mouse sobre a view e selecione e opção Novo tema. A tela seguinte aparecerá.

Na tela de criação de tema, devemos especificar o nome do novo tema, selecionar a sua view correspondente e o seu Layer.
Podemos Também criar uma restrição sobre os campos de tabelas do Layer selecionado. Para isso utilizamos o campo Restricao SQL. Ao clicar-mos no botão Editar Restricao uma nova janela surgirá com ferramentas para auxiliar a composição da restrição.


     

                                                        Criando tema                                                                        Editando Restrição SQL


Para enquadrar um tema da view, basta clicar com o botão direito do mouse sobre o tema e selecionar a opção Enquadrar Tema .

O VIPE também nos permite alterar o estilo dos objetos de um tema (ponto, linha, polígono e texto). Para isso clique com o botão direito do mouse sobre um tema e selecione a opção Estilo de Objetos. Também é possível editar apenas aos estilos de objetos selecionados. Para isso na visão mapa clique sobre um objeto para selecioná-lo e agora sobre o tema clique com o botão direito e selecione a opção Estilo de Objetos Selecionados.



Para excluir um tema da view, basta clicar com o botão direito sobre a view desejada e selecionar a opção Excluir. Uma mensagem de Alerta aparecerá pedindo a confirmação da operação.

Para mover um tema para cima ou para baixo na estrutura da visão, basta clicar com o botão direito sobre o tema e selecionar uma das opções Mover para Cima ou Mover para baixo. Os grupos de temas também podem ser movidos dentro da estrutura da view do projeto e os temáticos pode ser movidos "para cima" ou "para baixo" na estrutura do tema.

1.5) Principais funcionalidades do modo mapa:
Zoom

 

A primeira ferramenta realiza o zoom da imagem, considerando um ponto ou uma área especificada pelo usuário (posição da lupa).
Para determinar uma área para zoom, com a ferramenta selecionada clique, arraste o mouse e solte-o.

Realiza a redução do zoom, considerando o ponto especificado pelo usuário (posição da lupa) como o centro da operação.

A terceira ferramenta, que também possui o nome de "mais zoom", realiza a mesma operação que a lupa de "mais zoom", mas considerando como ponto para a operação o centro da tela e não uma posição ou área especificada pelo usuário.

Realiza a operação de "menos zoom" considerando como ponto para a operação o centro da tela e não uma posição especificada pelo usuário.
Pan

 

Move o mapa da visão para a esquerda.

Move o mapa da visão para a Cima.

Move o mapa da visão para a Baixo.

Move o mapa da visão para a direita.

Move o mapa para uma posição determinada pelo usuário.
Com a ferramenta selecionada clique sobre o mapa da visão e arraste o mouse até a posição desejada.
Fit

 

Serve para se obter uma visão geral de todo o mapa (todo o mapa é enquadrado na tela).

Altera a visão do mapa realizando zoom nos objetos selecionados e enquadrando-os na tela.
Veremos adiante como selecionar um objeto no modo mapa.
Seleção de objeto

 

Com a ferramenta "Selecção de Objetos"(seta) selecionada clique com o botão direito sobre um objeto no mapa da visão e selecione a opção Seleciona o Objeto.

        

Selecionando área para zoom                                                     Selecionando Objeto

Para os exemplos de inserção de objetos criaremos um tema de exemplo (nome "Exemplo") na visão "Mapa1" seguindo as etapas de criação de tema já esplicados (item 1.4 Utilizando a Legenda), não sendo necessária a definição de restrições sql.

Para a inserção de novos objetos, é necessário que um tema esteja selecionado, por tanto antes de prossegir selecione o tema de exemplo criado

Ao clicar no Menu Inserir serão apresentados os tipos de objetos que podem ser inseridos (ponto, linha, polígono e texto).



Para inserir um ponto selecione Inserir -> ponto e clique em uma posição do Mapa para desenhar o objeto.



Para inserir uma linha selecione Inserir -> Linha. Cada Clique com o botão esquerdo do mouse irá inserir um ponto da linha no mapa. Para terminar o desenho clique com o botão direito do mouse. 

Para inserir um polígono selecione Inserir -> Polígono. Assim como no caso da linha, cada clique com o botão esquerdo do mouse irá inserir um novo ponto do polígono. Para terminar o desenho clique com o botão direito do mouse. 

Para inserir um texto selecione Inserir -> Texto. Clique na área do mapa onde o texto será inserido. Aparecerá então um tela para a entrada da mensagem texto. 

1.6) Principais funcionalidades do modo de layout:

É interessante observar que o modo de layout possui duas representações do mapa. A maior representa a visão do mapa no modo mapa. A menor apresenta uma visão de todo o mapa, apresentando uma área hachurada em vermelho que é correspondente ao mapa da representação maior.

Zoom de papel

Os botões de zoom de papel possuem funções análogas as do zoom de mapa, só que estas se aplicam ao papel representado no modo de layout, ou seja a toda a área de visão do modo de layout e não apenas ao mapa.

A primeira ferramenta realiza o zoom da imagem, considerando um ponto especificado pelo usuário (posição da lupa). Note que, como ja explicado, é realizado um zoom sobre o ambiente de layout e não sobre o mapa da visão (o mesmo vale para todas as operações de zoom de papel).

Operação inversa da anterior, realiza a redução do zoom, considerando o ponto especificado pelo usuário (posição da lupa) como o centro da operação.

A terceira ferramenta, que também possui o nome de "mais zoom", realiza a mesma operação que a lupa de "mais zoom", mas com ela o ponto de zoom é o centro da tela e não um ponto determinado pelo usuário.

Realiza a operação de "menos zoom" considerando o centro da tela e não um ponto especificado pelo usuário.
Zoom no mapa

 

  Possuem as mesmas funcionalidades das apresentadas no módulo mapa, só que no modo layout, para utiliza-las é preciso primeiro selecionar o mapa, ou seja a representação maior do mapa da visão. Para selecionar o mapa utilize a ferramenta "seta" . Mais uma vez é interessante observar o mapeamento da visão selecionada sobre a visão total do mapa, apresentada pelo mapa menor do modo de layout.
Pan:
 

Assim com no caso do zoom, a funcionalidade do botão pan do modo layout é análoga a funcionalidade do botão mover mapa, mas voltada para realizar modifições no ambiente da visão do layout e não no mapa.
Move a visão do modo de layout para uma posição determinada pelo usuário. Com a ferramenta selecionada clique sobre a visão do layout e arraste o mouse até a posição desejada.
As fucionalidades de pan do mapa assim como o zoom, podem ser utilizadas no modo layout, selecionando a representação do mapa na visão.
Fit:
 

Serve para se obter uma visão geral de todo o modo layout (todo o layout é enquadrado na tela).
Funcionalidades de fit no mapa selecionando a representação da visão, assim como explicado para as outras funcionalidades.

 

Exemplo Zoom de papel


     

Exemplo Zoom no Mapa Layout                                                             Exemplo Pan Layout


O modo de layout além da opção de inserir objetos através do menu Inserir, apresentado no modo mapa, possui botões para realizar estas operações.

Os objetos podem ser criados em qualquer parte do ambiente do modo de layout, não apenas no "papel", e possuem as mesmas funcionalidades das opções do menu Inserir.

Exemplo inserção Texto, Ponto, Linha e Polígono.

 

Além dos tipos de objetos já falados, O modo de layout possui a funcionalidade inserir figura, veja que agora a opção Figura no menu Inserir está ativa.

Assim como para a inserção dos outros objetos o modo de mayout disponibiliza um botão para acesso rápido à funcionalidade de inserir figura  .

Após clicar no botão clique na área do ambiente do modo de layout. Aparecerá então uma tela solicitando informações da figura a ser inserida. Após a confirmação a imagem será desenhada.

 
Opção Menu Inserir Figura

 
Selecionar Figura

 
Exemplo desenho Figura

Para arrastar um objeto do modo layout selecione a ferramenta de seleção ("seta"), clique e mantenha pressionado o botão esquerdo do mouse sobre o objeto, arraste o mouse até a posição desejada e então libere o botão.

Exemplo arrastando um Polígono:

          

   

Observe que com a ferramenta de seleção ("seta"), ao clicar sobre um objeto, oito pontos aparecem ao redor de sua caixa de seleção.

Para redimensionar um objeto basta clicar sobre um destes pontos, arrastar o mouse até que a figura fique com a forma desejada e então libere o botão.

              

   

Como já comentado, ao clicar sobre um objeto com a ferramenta de seleção "seta" oito pontos aparecem ao redor de sua caixa de seleção. Ao clicar novamente sobre o objeto estes pontos mudam de formato, circulo, o que indica a mudança de funcionalidade.

Para rotacionar um objeto então, clique sobre um dos pontos em formato de círculo, arraste o mouse até a posição desejada e então libere o botão.

              

   
1.7) Como imprimir utilizando o modo de impressão:

Observe que ao mudarmos o modo de visualização do projeto para o modo de impressão, o botão da impressora fica ativo.

 



Para imprimir então a visão do layout no modo de impressão, basta clicar neste botão e então será apresentado o assistente para as prefências de impressão.




Seção 2 - Interação com o Canvas
 2.1 A Arquitetura VIX

 

Os sistemas gráfico-interativos que utilizam o TDK utilizam diversas ferramentas que facilitam a sua construção, como bibliotecas gráficas (p.ex. [Nye90, TeC89, TeC96c]) e de interface (p.ex. [Ope91, Pet, LdFG+96]). Os sistemas de interface suportam, normalmente, um conjunto padronizado de objetos (widgets) que oferecem o que já foi chamado de "um pouco mais que um sistema de menus glorificado" [MR93].

Com a necessidade de utilização de dois sistemas, as aplicações gráfico-interativas lidam, em geral, com uma dicotomia: uma biblioteca se propõe a fornecer primitivas de desenho para a representação visual dos objetos particulares da aplicação, e outra os widgets e eventos de interface para dar suporte a interação. Como consequência dessa dicotomia, o programador precisa, muitas vezes, combinar esses dois sistemas no nível da aplicação, tendo que lidar com paradigmas diferentes.

Uma forma de minimizar a dicotomia entre os sistemas gráficos e de interface vem do conceito de objetos visuais interativos [BCCI94, CI95]. Sucintamente, tais objetos são entidades da aplicação que são exibidas e manipuladas pelo usuário. Além disso, encapsulam, em um único tipo abstrato de dados, suas representações e comportamentos, facilitando sua programação de forma modular e reutilizável.

A implementação do conceito de objetos visuais interativos pode ser feita sob uma arquitetura que defina um protocolo extensível de interação usuário-objetos. Uma vez implementada essa arquitetura, um objeto pode ser tratado como um componente de software que, uma vez confeccionado, pode ser reutilizado por diversas aplicações. Ao reutilizar comportamentos de objetos, as interações de manipulação direta podem ser tratadas por um protocolo genérico que se aplique a qualquer tipo de objeto. Logo, uma vez construídas essas interações, elas também podem ser guardadas para reuso em outros programas.

Com a confecção deste tipo de arquitetura, programas com recursos gráfico-interativos podem ser construídos de forma reutilizável, modular e sem ter que lidar com dois paradigmas distintos. Seguindo esta idéia, [Santos, 2005] propôs a  arquitetura VIX, um framework para suporte a objetos visuais interativos.

O VIX utiliza o termo visual object, ou simplesmente VO, para tratar objetos visuais. O conceito de VO modela objetos gráficos ativos que oferecem métodos de desenho e de resposta a ações do usuário. O tratamento desses objetos não  é restrito somente aos objetos gráficos de uma aplicação. Pode-se entender como VO qualquer objeto que possua uma representação e um comportamento. A funcionalidade mínima de um VO é a sua capacidade de responder a determinadas ações e saber representar-se gra camente. Desta forma, sua interface contém somente ações de respostas ao usuário e de redesenho, ou seja, feedback de suas alterações.

Dado que um objeto visual é determinado por seu comportamento e representação, é necessária a existência de uma entidade que transmita os eventos do usuário e ofereça recursos para que o objeto seja desenhado. O conceito de espaço visual/ visual space, ou simplesmente VS, mapeia entidades que transmitem eventos para VOs e fornecem uma superfície de visualização onde eles são posicionados. Os VSs devem ser encarados como elementos de ligação entre o usuário e o VO que ele está manipulando, de forma que o usuário enxerga e manipula seu objeto através de recursos do VS.

 

No processo de comunicação entre estes objetos, são utilizadas mensagens. Através delas, os objetos podem trocar dados uns com outros (o VO deve saber responder às requisições do VS). O envio de mensagens é feito pelos métodos sendVO ou sendVS. A aplicação do método send em uma mensagem implica no envio desta para o tratador do objeto envolvido. Os métodos handlers , por sua vez, retornam se a mensagem foi tratada ou não.

Os filtros servem para modelar objetos que fazem a interface entre um VS e um VO. Um filtro repassa para o seu VO associado os eventos gerados em seu VS, podendo dar algum tratamento especial a esses eventos.

 

 2.2 Árvore de Eventos

 

Com o intuito de tratar os eventos de maneira uniforme, independente do tipo de ação que ele irá ocasionar, o TDK implementa a arquitetura VIX para dar suporte ao tratamento de eventos das aplicações. A implementação no TDK é chamada de árvore de eventos. Esta árvore possui os nós esquematizados na figura seguinte e classificados da seguinte forma:

 

Classe Descrição

Controle da Aplicação

TdkApplicationController gerencia a estrutura da árvore de eventos

Controle de Interação

TdkInteractorController capta eventos no handle do canvas

Controle de Modo

TdkModeController gerencia um modo de operação do TDK

Interador

TdkInteractor traduz os eventos de mouse e teclado em informações de interação

Tarefa

TdkTask executa uma funcionalidade bem definida para tratar um evento que trafega pela árvore

Visualizador

TdkDisplay realiza operações de manipulação (como zoom, pan e fit) de visualização no canvas e desenha objetos no canvas de acordo com o modelo de dados

Objeto

TdkObject representa um objeto da camada de modelo de dados do Tdk.

A aplicação possui apenas uma instância da classe do Controle da Aplicação e uma instância da classe do Controle de Interação. Já o Controle de Modo varia de acordo com o modo da aplicação do Tdk, que atualmente pode ser de três tipos: Controle de Modo de Mapa, Controle de Modo de Layout e Controle de Modo de Impressão.

A classe TdkApplicationController é responsável por fazer a troca de estado da aplicação e a troca de modo de operação.  

A classe base que representa todos os interadores presentes no TDK é a TdkInteractor. Para criar um novo interador basta criar uma classe que estenda TdkInteractor e sobrescrever os métodos de captura de eventos, handleVSEvent e handleVOEvent (estes métodos serão explicados abaixo). Dado um determinado estado da aplicação (explicado abaixo), é de responsabilidade do interador traduzir uma sequência de eventos básicos em um evento mais sofisticado que define exatamente o que o usuário deseja que o sistema faça. Por exemplo, ao acumular uma sequência de eventos de mouse click e mouse move, o interador a traduz em um único evento de zoom in a ser repassado para as tarefas responsáveis por sua execução.

A classe base que representa todas as tarefas presentes no TDK é a TdkTask. Para criar uma nova tarefa basta criar uma classe que estenda TdkTask e sobrescrever os métodos de captura de eventos, handleVSEvent e handleVOEvent (estes métodos serão explicados abaixo). É de responsabilidade da tarefa capturar os eventos e executar as ações necessárias para a execução de uma funcionalidade bem definida, como a inserção de um ponto no banco de dados em uma tarefa de criação de ponto, por exemplo.

Um determinado interador e o seu conjunto de tarefas define um estado da aplicação. Além disso, o estado da aplicação só é válido para um certo modo da aplicação. O estado da aplicação varia de acordo com a interação que o usuário faz com a aplicação. Por exemplo, ao "pedir" ao sistema para fazer um zoom in em um mapa, a aplicação possui o interador TdkZoomInInteractor e um conjunto de tarefas associado que tratará deste pedido. Ao "pedir" ao sistema para fazer um pan, existe outro interador (TdkPanInteractor) com o seu respectivo conjunto de tarefas associado que tratará deste pedido.

O serviço do Tdk responsável por criar e registrar um estado de aplicaçãoremover um estado de aplicaçãoobter o estado corrente da aplicação é feito pela classe TdkApplicationConfigService através dos métodos registerApplicationState, unregisterApplicationState e getApplicationState, respectivamente. Como qualquer outro serviço, a  TdkApplicationConfigService é implementada por classes básicas, internas ao Tdk. No caso, a TdkApplicationConfigService usa a classe TdkApplicationStateManager que, na verdade, é a classe responsável por fazer as tarefas de criação, remoção e obtenção do estado da aplicação.

Desta forma, para criar um estado de aplicação é preciso chamar o método registerApplicationState passando como parâmetros um interador,  um vetor de tarefas  e qual o modo de aplicação (mapa, layout ou impressão) para qual este estado vai ser utilizado.

Para alterar um estado de aplicação, é necessário utilizar o método ... da classe ...  No VIPE, por exemplo, para mudar ...

Um mesmo interador pode estar associado a um conjunto de tarefas diferentes definindo vários estados de aplicação. De forma análoga, uma mesma tarefa pode estar associada a diferentes interadores. Esta é uma das grandes vantagens da utilização da árvore de eventos pois permite a modularização do sistema e o reuso de seus componentes.

O Visualizador e o conjunto de objetos do modelo de dados do Tdk também variam durante a execução da aplicação.

 

No TDK definimos a interface única TdkEventHandler para encapsular o código referente a troca de mensagens entre os nós da árvore. Desta forma, todos os nós da árvore implementam a interface TdkEventHandler e possuem os métodos sendVS(TdkEvent), handleVSEvent(TdkEvent), sendVO(TdkEvent), handleVOEvent(TdkEvent) conforme especificado pela arquitetura VIX.

 

 

De forma geral, o método sendVS(TdkEvent) de um nó filho chama o método handleVOEvent(TdkEvent) dos seus nós pais. No exemplo abaixo o método sendVS(TdkEvent) do visualizador chama o método handleVOEvent(TdkEvent) de suas tarefas.

O método sendVO(TdkEvent) de um nó pai chama o método handleVSEvent(TdkEvent) dos seus nós filhos.   No exemplo abaixo o método sendVO(TdkEvent) do interador chama o método handleVSEvent(TdkEvent) das suas tarefas.

 

 

Abaixo está um pseudo-código para ilustrar a criação de um ponto no modo de mapa. Quando o usuário clica no mouse solicitando a criação de um ponto, o IUP captura o evento de mouse click e repassa para o TdkInteractController. A partir daí, a comunicação entre os nós da árvore é feita através das chamadas dos métodos explicados na figura anterior, ou seja, cada nó pai em seu método sendVO chama o método handleVSEvent dos seus filhos.

Na criação de ponto no mapa, o estado da aplicação inclui o TdkPointInteractor e as tarefas TdkRedrawTask e TdkCreatePointTask, por exemplo. Antes de repassar o pedido para o um nó filho, o nó pai pode fazer um tratamento. Veja que neste caso, o TdkPointInteractor transforma o evento de mouse (TdkMouseEvent) em um evento de criação de ponto (TdkPointEvent). O TdkPointInteractor repassa este evento para todas as suas tarefas. Entretanto, somente a TdkCreatePointTask saberá tratá-lo.

 

 

Abaixo um outro pseudo-código que mostra além da comunicação entre um nó pai e filho, também a comunicação entre nó filho e nó pai utilizando os métodos sendVS e handleVOEvent. Este exemplo trata da criação de diálogo no modo de mapa que depois será utilizado para o usuário escrever um texto. Da mesma forma que no exemplo anterior, depois que o usuário interage com o sistema e o IUP capta o evento, o evento é repassado para cada um dos nós da árvore responsáveis pelo tratamento deste evento. No caso o interador responsável é o TdkSimplePointInteractor e a tarefa é a TdkCreateTextTask. Note que no método sendVS da tarefa é chamado o método handleVOEvent do seu pai, que no caso é o TdkSimplePointInteractor. Repare também que os eventos tratados por cada um dos nós da árvore são diferentes. O método handleVSEvent do TdkMapController e do TdkSimplePointInteractor recebem o evento TdkMouseEvent, enquanto o TdkCreateTextTask recebe o evento TdkPointEvent.

 

 2.3 Exemplo de Criação de Novo Estado de Interação, Novo Interador e Nova Tarefa

 

Como exemplo de utilização dos conceitos apresentados anteriormente veremos a aplicação AppSample.

Considerando que SVN_ROOT é o diretório onde foi feito o checkout do Tdk pelo SVN, o arquivo de solução que deve ser compilado é o SVN_ROOT\iupvipe\examples\appsample\build\\mak.vc71\appsample.sln. No Visual Studio .NET 2003  abra o arquivo da solução, acesse o menu Build -> Build Solution e aguarde a compilação das bibliotecas.

Para executar o AppSample pelo Visual Studio, após a compilação, aperte a tecla "F5" ou acesse pelo menu Debug -> Start.   

Para executar fora do Visual Studio, clique duas vezes no nome do arquivo SVN_ROOT\iupvipe\examples\appsample\build\\mak.vc71\Debug\appsample.exe. Este arquivo foi  gerado na compilação do projeto usando o Visual Studio.

A AppSample é uma versão simplificada do VIPE que apresenta apenas o modo de mapa e algumas funcionalidades básicas.

Para ilustrar a criação de um novo estado de interaçãode um novo interador e de uma nova tarefa, esta aplicação contempla uma funcionalidade para o espelhamento de uma linha.

Para começar, abra a aplicação de exemplo como descrito acima. Então acesse o menu Arquivo -> Conectar -> Access. Escolha o arquivo TesteAS.mdb localizado na pasta SVN_ROOT\iupvipe\examples\data . Uma caixa de diálogo para escolha do projeto a ser visualizado aparecerá. Escolha o projeto TerraEditProject

Agora que o projeto de teste foi carregado, para espelhar uma linha você deve primeiro selecionar a ferramenta de espelhamento de linha clicando com o mouse no ícone de espelhamento como mostra a figura abaixo.

 

Para exercitar este exemplo você não precisará fazer download por aqui.
Este exemplo (tanto a aplicação quanto o banco de dados) já está disponível junto com o código do Tdk que você fez download do SVN como dito anteriormente.

 

Em seguida você deve selecionar, com o botão esquerdo do mouse, a linha que deseja espelhar.

 

 

Agora você deve clicar com o botão esquerdo do mouse em algum ponto do canvas, para gerar a linha base do espelhamento. O padrão é a geração de uma linha horizontal. Para gerar uma linha vertical, matenha a tecla CTRL pressionada ao criar a linha base.

 

 

Finalmente, para efetuar o espelhamento, mantenha a tecla SHIFT pressionada e clique com o botão esquerdo do mouse em qualquer lugar do canvas.

 

 

O estado de aplicação Espelhamento de Linha , identificado pelo inteiro lineMirrorState_, responsável pela funcionalidade de espelhamento de linha é formado pelo interador ASLineMirrorInteractor e um vetor de tarefas contendo as tarefas TdkRedrawTask, TdkSelectMapObjectsTask, TdkFeedbackTask e ASLineMirrorTask.

O registro do estado pode ser visto no código abaixo, retirado da classe ASApplicationController. Veja que o registro é feito pela classe  TdkApplicationConfigService através do método registerApplicationState.

 

/*
keywords 
-------------------
ApplicationMode InteractionState InteractionStateRegistration Task Interactor
ApplicationController TdkApplicationConfigService RegisterApplicationState OperationMode
-------------------
description: Tutorial of the Interaction Module that shows how to register a new interaction state.
*/

void ASApplicationController::registerASStates()
{
    /// To register an application state, it must have an interactor and
    /// some tasks (more than zero) for an operation mode. In this case,
    /// the operation mode is the map (opmMap).
    TdkTaskVector mapLineMirrorTasks;

    /// The task ASLineMirrorTask will handle events to mirror some line.
    mapLineMirrorTasks.push_back(_asLineMirrorTask);

    /// The task TdkRedrawTask is used to redraw the map. This is done when
    /// a redraw event is sent.
    mapLineMirrorTasks.push_back(_tdkRedrawTask);

    /// The task TdkSelectMapObjectsTask is used to selected map objects. The
    /// application state uses a selected line to mirror.
    mapLineMirrorTasks.push_back(_tdkSelectMapObjectsTask);

    /// The task TdkFeedbackTask is used to draw the interaction feedback. In
    /// this case, is drawn the axis to mirror the line.
	mapLineMirrorTasks.push_back(_tdkFeedbackTask);

    /// Creating the line mirror interactor.
    TdkInteractor* interactor = new ASLineMirrorInteractor();

    /// To register the application state, it must use the 
    /// TdkApplicationConfigService.
    lineMirrorState_ =
        TdkApplicationConfigService::registerApplicationState(opmMap,
        interactor, mapLineMirrorTasks);
}
									

 

Neste exemplo foram criados o interador ASLineMirrorInteractor e a tarefa ASLineMirrorTask. Este novo interador e esta nova tarefa não fazem parte do Tdk, mas sim da própria aplicação.

Como exposto anteriormente, para se criar o ASLineMirrorInteractor foi estendida a classe TdkLineInteractor, que por sua vez estende a classe TdkInteractor . Basicamente foram sobrescritos os métodos de tratamento de eventos handleVSEvent, como exemplificado nos trechos de código a seguir. Nota-se que este método recebe uma seqüência de eventos básicos do tipo TdkMouseClickEvent e os traduz em um evento do tipo ASLineMirrorEvent.

 

/*
keywords 
-------------------
VIXEventModel Event MouseButton MouseClickEvent KeyboardState EventTranslation
sendVO handleVSEvent LineMirrorEvent
-------------------
description: Tutorial of the Interaction Module that shows how to extend a Interactor.
*/

void ASLineMirrorInteractor::handleVSEvent(TdkMouseClickEvent& event)
{
    TdkButton button = event.getButton();
    TdkButtonState buttonState = event.getButtonState();
    TdkKeyboardState keyboardState = event.getKeyboardState();

    /// If any mouse button was not pressed, exit.
    if (buttonState == btsUnpressed)
		return;

    /// If the right mouse button was pressed, reset the interaction.
    if (button == btnRight)
    {
        reset();
        return;
    }

    /// If the keyboard key shift and the left mouse button was pressed, try
    /// to mirror the selected line using the axis.
    if (keyboardState == kbsShift && button == btnLeft)
    ...
    
    ASLineMirrorEvent lineMirrorEvent(getLine());
    lineMirrorEvent.addAttender(selectedLine_);
    sendVO(lineMirrorEvent);
    
    ...

 

A tarefa ASLineMirrorTask foi implementada estendendo-se a classe TdkTask e sobrescrevendo os métodos de tratamento de eventos handleVSEvent, como pode ser visto no trecho de código a seguir. A efetiva transformação da linha é executada pelo método mirrorLineObject.

 

/*
keywords 
-------------------
VIXEventModel Event Task TaskExecution
sendVO handleVSEvent 
-------------------
description: Tutorial of the Interaction Module that shows how to extend a Task.
*/

void ASLineMirrorTask::handleVSEvent(ASLineMirrorEvent& event)
{
    /// The line mirror event that is sent by the interactor arrives here.
    /// Gets the selected line and the axis and validate them.
    
    TdkEventHandlerVector& attenders = event.getAttenders();
    if (attenders.size() == 0)
		return;
	
    TdkGeographicObject* object = (TdkGeographicObject*)attenders[0];
    if (object == NULL)
		return;
	
    TeLine2D& axis = event.getLine();

    /// Mirror the line.
    mirrorLineObject(object, axis);
}
									

 

Note que no registro do estado usamos tarefas ( TdkRedrawTask, TdkSelectMapObjectsTask, TdkFeedbackTask) que já existiam e que foram reusadas para criar este novo estado de interação. Isto ilustra o reuso de código e a vantagem da utilização da árvore de eventos.


Seção 3 -  Modo de Layout  

 

Nesta seção do tutorial veremos como usar e estender o modo de Layout.

 

3.1) Introdução

 

Como vimos anteriormente, uma aplicação TDK tem basicamente três modos de operação: Visualização, Layout e Impressão. Nesta seção estaremos demonstrando o uso das funcionalidades dos módulos de Layout, assim como sua extensão, mostrando como incluir um novo tipo de objeto de layout.

O Modo de Layout é o modo de operação do TDK para criação e edição de cartas. As cartas são normalmente compostas de uma visualização de mapa e outros objetos como legendas, caixa de texto e figuras decorativas.

Abaixo encontra-se um exemplo de uma carta, apresentada no modo de Layout do VIPE.

Todos os objetos visualizados no canvas principal acima (marcado com um retângulo em vermelho) são subclasses da classe TDKLayoutObject.  Para a composição de cada carta é possível adicionar, excluir e editar esses objetos. As operações de edição como translação, redimensionamento e rotação são definidas pela classe abstrata TdkEditableObject, uma superclasse da classe TdkLayoutObject.

Toda a interação do usuário no modo de Layout também é feita através da árvore de eventos apresentada anteriormente, porém com TdkLayoutObject's na base da árvore, ao invés de TdkObject's (que são utilizados no modo de visualização de mapa como apresentado na seção 2) . Para isso o TdkLayoutObject também é subclasse do TdkEventHandler.

O TDK já oferece alguns tipos de objetos de layout bastante usuais. Estes tipos estão separados em basicamente duas classes, a TdkApplicationLayoutObject e a TdkGeometricLayoutObject. Os objetos podem ser agrupados através da TdkLayoutObjectCollection.

 

 

O TdkGeometricLayoutObject, como o próprio nome indica, representa tipos geométricos básicos (como ponto, linha e polígono) que podem ser adicionados ao layout. Esses tipos podem ser agrupados, formando figuras mais complexas, usando a coleção TdkGeometricLayoutObjectCollection.

 

 

Para outros tipos de objetos temos a classe TdkApplicationLayoutObject. Eles representam objetos mais específicos de cada aplicação e estão subdivididos em duas classes: TdkViewLayoutObject e TdkImageLayoutObject. A  TdkImageLayoutObject representa uma imagem enquanto TdkViewLayoutObject representa objetos mais complexos como mapas e legendas. 

 

 

Na seção a seguir vamos mostrar como estender o atual modelo para a inclusão de um novo tipo de objeto de layout.

 

3.2) Exemplo de Criação de Novo Tipo de Objeto de Layout

 

Nesta seção vamos mostrar um exemplo de extensão do modo de layout. Apresentaremos todos os passos necessários para criarmos e depois adicionarmos um novo tipo de objeto de layout. Esta seção está dividida em duas partes: na seção 4.2.1 mostraremos a camada do modelo de dados com o novo tipo de objeto de layout (ou seja, vamos mostrar a criação de um novo tipo de objeto de layout), na seção 4.2.2 mostraremos como uma aplicação pode utilizar este novo tipo de objeto (ou seja, vamos mostrar como este novo tipo de objeto pode ser adicionado ao canvas principal do modo de layout).

 

3.2.1) Criação do Novo Tipo de Objeto de Layout

 

O primeiro passo então é a criação de uma nova classe, que estenda a TdkLayoutObject ou uma de suas subclasses. No nosso exemplo como o objeto a ser adicionado será um simples retângulo, chamado de ASLayoutObject , vamos estender a TdkGeometricLayoutObject, como esquematizado no diagrama abaixo e demonstrado no código seguinte.

 

/*
keywords 
-------------------
Layout LayoutObject LayoutObjectExtension

-------------------
description: Tutorial of the Interaction Module that shows how to extend a LayoutObject.
*/


/// The string that identifies the ASLayoutObject
#define _AS_LAYOUT_OBJECT_TYPE_ "AS_LAYOUT_OBJECT_TYPE"

/// The string that indentifies this object template type
#define _AS_LAYOUT_OBJECT_NAME_ "TASLAYOUTOBJECT"

/// the string that serves as basename for all objects of this type
#define _AS_LAYOUT_OBJECT_BASE_NAME_ "aslayoutobject"

/// This is the sample group.
/// @defgroup AppSample

/// ASLayoutObject class.
/// 
/// @ingroup AppSample

class ASLayoutObject : public TdkGeometricLayoutObject
{
public:
    ASLayoutObject(std::string name, TeBox& bBox);
    ASLayoutObject(ASLayoutObject& geometricLayoutObject);

    virtual ~ASLayoutObject();


    virtual TdkLayoutObject* copy();

    virtual std::string getType();
    
    virtual std::string getTemplateName();
   

    // Persistence methods.
    virtual void insert(TeDatabase* driver, std::string layoutName);
    virtual void load(TeDatabase* driver, std::string layoutName);
    virtual void update(TeDatabase* driver, std::string layoutName);
    virtual void remove(TeDatabase* driver, std::string layoutName);

    // This method is called to ask the object to update it´s bounding box, represented
    // by the protected atribute bBox_ .
    virtual void updateBBox();

    /// This method is responsable for translating, resizing and rotating the object
    virtual void transform(TdkMathMatrix& matrix);

    /// This method returns the vertex index that is in the 
    /// surroudings of a given coord
    virtual int vertexPoint(TeCoord2D& coord);
    
    /// This methods gives the two vertexes indexes that defines a 
    /// line of this object, that is in the surroundings of the given coord
    virtual void segmentVertexes(TeCoord2D& coord, int& vertex1, int& vertex2);
       
    virtual void point2Line(TeCoord2D& coord, int vertex1, int vertex2);
	
protected:

    // This method is responsible for drawing the content of the object
    virtual void paint(TdkCanvas* display);									
    
}
    
    
    

 

Para que um objeto ASLayoutObject seja criado, é necessário utilizar o métodocreateLayoutObjectda classe TdkLayoutObjectFactory. Este método é responsável por controlar a geração de qualquer objeto de layout, gerando nomes únicos a partir de um nome base definido. Porém, para que o métodocreateLayoutObject  funcione corretamente, a TdkLayoutObjectFactory  precisa saber como construir cada tipo de objeto. No nosso caso, ela precisa conhecer como construir o ASLayoutObject. Isto é feito através do registro de um método estático que é quem de fato instancia o objeto. No nosso exemplo, este método estático é o createASLayoutObject.

O registro é feito através do método registerLayoutObjectConstructor da classe TdkLayoutObjectFactory. Não há uma obrigatoriedade de onde fazer a chamada do registro, mas é importante que seja feito durante as rotinas de configuração da aplicação. Na aplicação de exemplo, esse registro está sendo feito no método init da classe ASApplication.

 

/*
keywords 
-------------------
Applicaiton LayoutObjectFactory Layout LayoutObject
LayoutObjectConstructorMethod registerLayoutObjectConstructor
-------------------
description: Tutorial of the Interaction Module that shows how to register a LayoutObject constructot method in
the object factory.
*/

bool ASApplication::init()
{  
   ...


    // Here we are registering our ASLayoutObject constructor.
    // The LayoutObjectFactory controls unique name generation for TdkLayoutObjects, given a base name.
    TdkLayoutObjectFactory::registerLayoutObjectConstructor(_AS_LAYOUT_OBJECT_TYPE_,createASLayoutObject);

 ...
}
									

 

Abaixo apresentamos o diagrama de seqüência que ilustra o registro do método construtor e a criação de um novo ASLayoutObject por uma ASCreateASLayoutObjetTask.

 

 

O método createASLayoutObject precisa obedecer a interface TdkLayoutObjectConstructorFunction, pois é a interface padrão dos construtores, onde estes recebem um nome e um blob com os dados iniciais do objeto serializados. Para você utilizar o TdkBlob para representar o blob, é preciso definir um protocolo de serialização dos dados do seu objeto. No nosso exemplo, como é um retângulo, precisamos definir apenas as duas coordenadas em uma ordem conhecida. No caso, a ordem deste exemplo foi definida como x1, x2, y1, y2. Segue no código abaixo o método createASLayoutObject    que mostra como estamos lendo de acordo com este protocolo. A frente você verá o código onde criamos o blob de acordo com o protocolo.

 

/*
keywords 
-------------------
Applicaiton LayoutObjectFactory Layout LayoutObject
LayoutObjectConstructorMethod Blob LayoutObjectDeserialization
-------------------
description: Tutorial of the Interaction Module that shows how to instantiate a new a LayoutObject.
*/
								
TdkLayoutObject* createASLayoutObject(std::string name, TdkBlob* blob)
{
    // Here we will deserialize our layout object
    // Since our object is a simple rectangle, we just read
    // the two points that defines our box.
    
    // So let´s read our geometry
    blob->reset();
    
    double x1;
    double x2;
    double y1;
    double y2;

    blob->readDouble(x1);
    blob->readDouble(x2);
    blob->readDouble(y1);
    blob->readDouble(y2);

    TeBox box(x1,y1,x2,y2);
    
    // Now we get the object style
    TdkVisual* visual = new TdkVisual();
    bool hasAdvancedStyle;
    blob->readBool(hasAdvancedStyle);

    if (hasAdvancedStyle == true)
    {
        TdkPolygonStyle* style = TdkSetup::getPolygonStyleFactory().make(blob);
        visual->setStyle(style);
    }
    else
    {
        
        int type;
        blob->readInt(type);
        visual->style(type);
        int r, g, b;
        blob->readInt(r);
        blob->readInt(g);
        blob->readInt(b);
        visual->color().red_ = r;
        visual->color().green_ = g;
        visual->color().blue_ = b;
        char transparency;
        blob->readChar(transparency);
        visual->transparency(transparency);
        int contourWidth;
        blob->readInt(contourWidth);
        visual->contourWidth(contourWidth);
        blob->readInt(r);
        blob->readInt(g);
        blob->readInt(b);
        visual->contourColor().red_ = r;
        visual->contourColor().green_ = g;
        visual->contourColor().blue_ = b;
        bool fixedSize;
        blob->readBool(fixedSize);
        visual->fixedSize(fixedSize);
    }

    // Here we create a new instance of our layout object
    ASLayoutObject* object = 
        new ASLayoutObject(name, box);

    // And set the object style
    object->setVisual(visual);
    return object;
}
    
    
    

3.2.2) Utilização do Novo Tipo de Objeto de Layout - Criação e Registro de Estado de Interação, Criação de Tarefa e Criação de Interador

 

Neste momento já é possível a criação de uma nova instância do nosso objeto.

Vamos então mostrar como uma aplicação pode utilizar este novo tipo de objeto ou seja, como um usuário final da aplicação, utilizando a interface do sistema, pode adicionar este novo tipo de objeto no canvas principal do modo de layout.

Primeiro criaremos a tarefa que instancia nosso novo objeto e o adiciona ao conjunto de objetos do layout.  Para isso basta estendermos a classe TdkTask sobrescrevendo o método handleVSEvent, como visto na seção 2 deste tutorial. No exemplo criamos a classe ASCreateASLayoutObjectTask como extensão da TdkTask.

Como nosso objeto é um retângulo, vamos reutilizar o interador de retângulo já presente no conjunto de interadores padrão do TDK, o TdkRectInteractor, o qual capturará os eventos de clique e movimento de mouse traduzindo-os para um TdkRectEvent  e enviando-o para essa nossa nova tarefa.

 

/*
keywords 
-------------------
Event RectEvent HandleVSEvent VIX Task Layout LayoutObject LayoutObjectCreation
LayoutController VIXEventModel
-------------------
description: Tutorial of the Interaction Module that shows how create anda add a new Layout object.
*/
								
void ASCreateASLayoutObjectTask::handleVSEvent(TdkEvent& event)
{
    if (event.name().compare(TDK_RECT_EVENT_NAME) == 0)
        handleVSEvent(*((TdkRectEvent*)&event));
}

void ASCreateASLayoutObjectTask::handleVSEvent(TdkRectEvent &event)
{
    // Get the result of the user interaction
    TeBox& viewportBox = event.getRect();

    double wx1;
    double wy1;
    double wx2;
    double wy2;


    // Here we are translating the coords from screen ( viewport) to the Layout View Paper ( world )
    TdkLayoutController::getInstance()->getDisplay()->getCanvas()->viewport2Window(viewportBox.x1(),viewportBox.y1(),wx1,wy1);
    TdkLayoutController::getInstance()->getDisplay()->getCanvas()->viewport2Window(viewportBox.x2(),viewportBox.y2(),wx2,wy2);

    TeBox worldBox(wx1,wy1,wx2,wy2);

    // We serialize this information and passes it to the LayoutObjectFactory
    TdkBlob blob;
    blob.clear();
    blob.reset();
    blob.writeDouble(worldBox.x1());
    blob.writeDouble(worldBox.x2());
    blob.writeDouble(worldBox.y1());
    blob.writeDouble(worldBox.y2());

    ASLayoutObject* asLayoutObject = 
        (ASLayoutObject*)TdkLayoutObjectFactory::
        createLayoutObject(_AS_LAYOUT_OBJECT_TYPE_, _AS_LAYOUT_OBJECT_BASE_NAME_, &blob);

    // Just completing the object information with some default values
    asLayoutObject->setVisual(TdkStyleDecoder::getDefaultVisual(TePOLYGONS,0));


    // Adding the object to the Layout representation
    TdkLayout* layout = (TdkLayout*)TdkLayoutController::getInstance()->getModel();
    layout->addObject(asLayoutObject);

    // drawing the object 
    asLayoutObject->draw(TdkLayoutController::getInstance()->getDisplay());

    TdkRefreshEvent refreshEvent;
    sendVO(refreshEvent);


    // The TdkEventManager is the class wich controls the undo/redo feature.
    // We insert in the manager a especial event that executes our object 
    // creation and deletion specific routines
    ASCreateLayoutObjectEvent* createEvent = new ASCreateLayoutObjectEvent(asLayoutObject);
    createEvent->addAttender((TdkEventHandler*)asLayoutObject);
    TdkCompletedEvent* completedEvent = new TdkCompletedEvent(createEvent);
    TdkEventManager::getInstance()->insertEvent(completedEvent);

}
									

 

Agora vamos registrar um novo estado de interação que representará uma árvore de eventos contendo a nossa nova tarefa ASCreateASLayoutObjectTask, o interador de retângulos TdkRectInteractor  e algumas tarefas auxiliares necessárias. 

Os estados de interação já disponibilizados pelo TDK, são criados e registrados durante a execução do método init da classe TdkApplicationController. Então para criarmos e registrarmos o nosso novo estado de interação, estendemos este método da seguinte forma:

 

/*
keywords 
-------------------
ApplicationController ApplicationControllerInit InteractionStateRegistration
ApplicaitonConfigService TaskVector
-------------------
description: Tutorial of the Interaction Module that shows how to create and register a new interaction state.
*/
								
void ASApplicationController::init()
{
    /// Initializes the states supplied by TDK.
    TdkIupApplicationController::init();

    /// Register the application sample states.
    registerASStates();
}

void ASApplicationController::registerASStates()
{
    /// To register an application state, it must have an interactor and
    /// some tasks (more than zero) for an operation mode. In this case,
    /// the operation mode is the layout (opmLayout).
    TdkTaskVector layoutASObjectCreateTasks;


    /// The task TdkRedrawTask is used to redraw the objects. This is done when
    /// a redraw event is sent.
    layoutASObjectCreateTasks.push_back(_redrawTask);

    /// The task ASCreateASLayoutObjectTask is the responsable for creating our 
    /// Layout Object
    layoutASObjectCreateTasks.push_back(_asCreateASLayoutObjectTask);

    /// The task TdkFeedbackTask is used to draw the interaction feedback. In
    /// this case, is drawn the layout object bounding box.
    layoutASObjectCreateTasks.push_back(_feedbackTask);

    /// Creating the rect interactor.
    TdkInteractor* interactor = new TdkRectInteractor();

    /// To register the application state, it must use the 
    /// TdkApplicationConfigService.
    asLayoutObjectCreateState_ = 
        TdkApplicationConfigService::registerApplicationState(opmLayout,
        interactor,layoutASObjectCreateTasks);

}
									

Pode-se perceber que tanto as tarefas padrões do TDK quanto a nossa nova tarefa não foi instanciada neste método. Para criar e destruir nossa nova tarefa, vamos sobrescrever mais dois métodos do TdkApplicationControllerdeleteAllTasks e instantiateAllTasks.

 

/*
keywords 
-------------------
Task InstantiateTask InstantiateAllTasks DeleteTask DeleteAllTasks
ApplicationController
-------------------
description: Tutorial of the Interaction Module that shows how to initialize and delete a new task.
*/

// This method is responsable by the deletion of all tasks used
void ASApplicationController::deleteAllTasks()
{
    TdkApplicationController::deleteAllTasks();
    TDK_DELETE(_asCreateASLayoutObjectTask);
}

// This method is responsable by the instantiation of all tasks
// tha will be used
void ASApplicationController::instantiateAllTasks()
{
    TdkApplicationController::instantiateAllTasks();
    _asCreateASLayoutObjectTask = new ASCreateASLayoutObjectTask();
}
									

Agora já temos o nosso novo estado de interação criado e registrado. Então para que o usuário comece a usar nossa nova funcionalidade de inserção do nosso objeto de layout, precisamos incluir um botão ou comando para fazer a alteração do estado de interação corrente.

Para isso precisamos fazer uma chamada ao método setCurrentState (da classe TdkApplicationController), usando o identificador recuperado quando registramos o nosso estado de interação.

Em nosso exemplo vamos fazer esta chamada em um método próprio da nossa classe ASApplicationController, onde também vamos enviar um evento para trocar o cursor do mouse, dando ao usuário uma resposta visual indicando que o estado de interação foi configurado.

 

/*
keywords 
-------------------
ApplicationController SetCurrentState ChangeMouseEvent 
-------------------
description: Tutorial of the Interaction Module that shows set a interaction state.
*/
 
void ASApplicationController::setASLayoutObjectCreateState()
{
 //To set the applicaiton state just call the setCurrentState 
 //using the integer indentifier gathered when we registered the 
 //our new layout object

    setCurrentState(asLayoutObjectCreateState_); 
    
    //You can change the mouse icon to give the user a visual feedback 
    //showing that this feature is activated
    TdkChangeMousePointerEvent eventToSend(mprCross);
    
    dispatch(eventToSend);
}
									

 

Após a chamada do método setCurrentState, mostrado acima, o TDK configura toda a árvore de eventos. O diagrama abaixo retrata o estado final da árvore para o nosso exemplo. 

 

 

 

Para saber mais  

Bibliotecas gráficas (desenho):
  • CD
  • java.awt.graphics


    Toolkits gráficos (widgets):
  • Swing
  • QT
  • IUP

  •          Topo ^