M.P.I - 1998/99 - Trabalho Prático Nr. 2 | |
---|---|
[ DI/UM ] |
Este trabalho deve ser realizado por grupos com um máximo de três alunos. O trabalho deve ser entregue até ao dia 27 de Novembro na recepção do Departamento de Informática e nele deve constar a listagem do código escrito assim como um pequeno relatório.
No presente caso vai ser realizada a interligação HASKELL -XFIG. O XFIG é uma aplicação gráfica popular entre os utilizadores de sistemas UNIX e que vamos utilizar como visualizador de uma linguagem simples, a 2 dimensões, que definiremos em HASKELL .
Pressione aqui para obter um pacote de programas desenvolvido pela equipa docente para facilitar a realização do trabalho. Recomenda-se a leitura daqueles que vão escritos em HASKELL .
Pretende-se neste trabalho definir uma linguagem gráfica ``brinquedo'' a duas dimensões (2D) capaz de especificar e desenhar agregações de caixas que contêm informação textual. Vamos designar essa linguagem por L2D e vamos defini-la como um tipo em HASKELL :
type L2D = X Caixa Tipoonde X é a estrutura de dados
data X a b = Unid a | Comp b (X a b) (X a b)Repare-se que esta estrutura de dados generaliza a que foi assunto do trabalho prático Nr.1 . Em ambos os casos temos árvores binárias. Mas neste caso as folhas deixam de ser vazias e passam a conter informação do tipo a. Em LD2 este parâmetro é instanciado com o tipo Caixa:
type Caixa = ((Int,Int),(Texto,Cor))onde
type Texto = String data Cor = Vermelha | Azul | Verde | AmarelaAssim, cada caixa de texto é especificada pela sua largura, altura, o seu texto e a sua côr. (Pode relacionar Caixa com as caixas de texto usadas nos jornais ou com 'frames' da linguagem HTML usada na Internet.) Por exemplo,
((1200,2000),("Caixa azul",Azul))designa a caixa
(1200,2000) | |
(0,0) |
data Tipo = V | Vd | Ve | H | Ht | Hbcom o seguinte significado:
Como LD2 instancia o parâmetro b de X com Tipo, é fácil de ver que cada ``frase'' da linguagem LD2 é representada por uma árvore binária em que cada nó indica qual o tipo de agregação a aplicar às suas duas sub-árvores.
Vamos dar um exemplo: a frase
ex2=(Comp Ht (Unid ((1000,2000),("A",Azul))) (Unid ((300,600),("B",Verde))))deverá corresponder à imagem
E poderá ir tão longe quando a linguagem o permite... Por exemplo, pense na estrutura da frase que representa o 'layout' seguinte:
É importante notar que cada ``caixa'' não dispõe informação relativa ao seu posicionamento final na figura. De facto, é a posição relativa que deve ocupar face às restantes caixas que irá determinar a sua posição final. Este é um dos objectivos deste trabalho: calcular o posicionamento absoluto de cada uma das caixas por forma a respeitar as restrições impostas pelas diversas agregações . Para isso vamos considerar um novo tipo de dados que comporta a informação de todas as caixas devidamente posicionadas (i.e. com a informação adicional da origem onde a caixa deve ser colocada).
data Fig = Fig Ponto [Obj] type Obj = (Ponto,Caixa)
A informação mais relevante deste tipo é a referente à lista de ``caixas posicinadas'' (tipo [Obj]). Regista-se aí a origem da caixa que, com a informação da sua altura e comprimento, permite definir todos os seus pontos (consideramos as caixas sempre paralelas aos eixos). O primeiro argumento do constructor (com tipo Ponto) regista a ``bounding box'' de todas as caixas contidas na lista (quando realizar as funções pretendidas reconhecerá o interesse desse argumento).
desenho :: L2D -> Fig desenho (Unid c) = desUnid c desenho (Comp t a b) = desComp t (desenho a) (desenho b)
Um segundo problema neste projecto é descobrir como visualizar a informação gráfica calculada por desenho . Duas alternativas parecem legítimas nesta fase:
Neste trabalho será adoptada a segunda solução (deixa-se a primeira como sugestão para valorização). Propomo-nos então a usar o XFIG , uma ferramenta de edição gráfica 2D popular entre os sistemas UNIX .
A utilização de uma ferramenta externa pressupõe algum trabalho de ``interligação'': o XFIG opera sobre formatos próprios e devemos adaptar a nossa informação para se enquadrar nesse formato. É fornecido um módulo em HASKELL que realiza grande parte dessa tarefa. Nesse módulo são definidos tipos que suportam a informação contida num documento XFIG e definem-se estes como instâncias das classes Show e Read, de tal forma que a representação textual desses tipos coincide com o formato dos ficheiros utilizados por essa ferramenta.
Deve, então, utilizar as funções:
defaultXFigDoc :: [Object] -> XFigDoc geraXFcaixa :: Ponto -> Ponto -> Cor -> Object geraXFtexto :: Ponto -> String -> Object
onde XFigDoc é o tipo de dados para interligação com o XFIG e Object é o tipo de dados dos objectos do XFIG . A função de geração do texto centra-o no ponto dado.
Comentário: o XFIG utiliza um sistema de coordenadas com a origem no canto superior direito. Para utilizarmos nas nossas estruturas de dados as coordenadas mais usuais (origem no canto inferior esquerdo) devemos fazer o ajuste na invocação dessas funções. Sugere-se que numa primeira fase se adoptem as coordenadas ``à la XFIG '' e, como valorização, se considere a adaptação para coordenadas standard.
Este trabalho irá utilizar intensivamente funções de Entrada/Saída dado que deverá produzir ficheiros que possam ser interpretados por programas externos. Vamos por isso utilizar os mecanismos próprios do HASKELL para 'I/O', i.e. a mónada IO . Já referimos que a geração dos ficheiros no formato XFIG se reduz à escrita da representação textual da estrutura de dados apropriada. De facto, no módulo fornecido encontra-se a definição
writeXFigFile :: XFigDoc -> String -> IO () writeXFigFile fig f = writeFile f (show fig)
No programa final constará por certo uma invocação a esta função, e.g. deveremos ter alguma coisa que se assemelhe a:
main :: IO () main = do -- tudo que o programa deve fazer -- ... writeXFigFile (--*XFigDoc*--) (--*Nome ficheiro*--) -- etc.
Dá-se total liberdade no que se refere à restante operacionalidade do trabalho, por exemplo quanto à interacção com o utilizador; se o programa opera sempre sobre determinados dados de exemplo ou se se permite ao utilizador interferir nesse processo; etc. Evidentemente que a valorização do trabalho considerará esses pontos.
Os utilizadores do sistema operativo MS-WINDOWS dispoem de um problema adicional: o XFIG é popular no ``mundo UNIX '' mas não se encontra normalmente disponível nos sistemas WINDOWS. Para tornear essa dificuldade fornece-se um applet que permite visualizar o desenho num cliente WWW (e.g. MS-EXPLORER ou NETSCAPE). Para isso deve-se utilizar a função de 'I/O' que cria um ficheiro com formato adequado:
writeXFigHtmlFile :: XFigDoc -> String -> IO()