Definir o tamanho da tela

20 views
Skip to first unread message

Diogo Augusto Pereira

unread,
Oct 4, 2007, 11:52:16 PM10/4/07
to treelayer-merlin
Olá,

No projeto que estou desenvolvendo, criei um gerenciador de layout que
organiza os controles na tela de acordo com o espaço disponível nela e
a disposição do layout (vertical ou horizontal). Agora estou começando
a desenvolver a parte da geração da tela efetivamente, na qual
adiciono os controles em função das propriedades do objeto.

Pois bem, após adicionar os controles no layout precisaria definir o
tamanho da tela, mas aí vem a questão: como definir isso de forma que
a tela fique com um tamanho adequado?

É uma questão, digamos, um pouco recursiva, já que preciso definir um
tamanho adequado para a tela, a fim de que o gerenciador de layout
organize os controles, mas para determinar o tamanho da tela é preciso
que os controles estejam organizados...

Um exemplo disso: se insiro 10 controles de 200px de largura em uma
tela de 300px de largura, os controles ficarão um abaixo do outro, mas
se eu aumento a tela para 500px, os controles podem ficam em 2 colunas
tranquilamente. A questão é, como determinar a largura e o comprimento
da tela?

Como o Merlin dimensiona as telas geradas? Ele mesmo determina a
posição dos controles?

Diogo

Marcelo Mrack

unread,
Oct 5, 2007, 3:53:02 AM10/5/07
to treelaye...@googlegroups.com
Primeiro ponto, no Merlin, as configuracoes podem ser feitas (1) por anotacoes, (2) por algoritmos plugaveis de posicionamento - que deve ser o seu caso ou (3) passando um template de tela (um outro arquivo *.class* feito num netbeans da vida, ou no caso da web, um html/xhtml), onde o merlin substitui os controles gerados, colocando-os nas posicoes do template passado.

No caso (2), entao como os algortimos "built-in" dele funcionam mais ou menos assim...

O mais simples, que tem hoje implementado, é o típico grid, de linhas e colunas. Nele, os labels podem ser posicionado nos quatro pontos cardeais do controle, conforme a anotacao atachada ou o padrao da configuracao, que o algoritmo deve obedecer. O distanciamento dos labels, bem como seus alinhamentos sao padroes, ou podem ser reconfigurados via anotacao, idem.

Quanto aos controles efetivamente.

a) A *ordem* deles (considerando isso como "de cima para baixo e da esquerda para a direita") é baseada em heuristicas, que dizem que os primeiros campos sao os mais imporantes, como um campo "nome", enquanto um campo "observacoes" seria o ultimo. Essas heuristicas são calculdas por outros algoritmos que nao vem ao caso aqui, mas para voce eu eu acho que voce esta simplesmente seguindo a ordem de declaracao dos fields na classe...

b) O *tamanho* e * redimensionamento* deles vai depender de outras heuristicas. Por exemplo, um campo "String nome" será (baseado em uma heuristica) mapeado para um textbox de "tamanho médio proporcional horizontalmente e fixo verticalmente". E o que é isso? É um textbox que deve ocupar uma linha e ter o tamanho de, aproximadamente, 70% de uma tela. No caso do campo "String observacoes" uma outra heuristica dira que ele deve ser mapeado para um textarea de "tamanho full horizontal e fixo vertical de tamanho compativel com o conteudo esperado do campo". Em outras palavras, o redimensionamento e tamanho do campo dependera de varios fatores, principalmente do "volume de informacao esperada para para esse campo". Dicas para ter esse volume de informacao podem ser extraidas das (tipicas) anotacoes de persistencia que voce tera no field, como um @Length, @Nullablel, etc.

c) Tem a questao do *agrupamento* de controles. Vou usar parte do teu exemplo pra responder. Voce disse "10 controles de 200px"..., bem, imaginamos que sejam 10 comboxes esses controles. Nesse caso, uma heuristica pode verificar que esses 10 controles "possuem um conteudo muito proximo". Assim, o algoritmo de layout usa essa heuristica para criar uma agrupamento desses 10 controles, de forma que, quando esse agrupamento estiver retraido (imagine um _div_ que "abre e fecha" com esses controles dentro dele) o tamanho final da sua tela nao precisa ter todo um tamanho de "10 x 200px" , mas sim scrolls (no div ou na tela quando o div aberto) para mostrar esses controles quando necessarios.

d) Quanto as *colunas* e *linhas*. De fato, distribuir controles em formatos de Grid é a solucao mais simples e, por isso é o padrao nessa versao inicial do Merlin. Para voce ter uma ideia, vai anexo uma tela bem simples gerada pelo merlin com uma anotacao sobre o campo "String name" para defini-lo com tamanho fixo. Oberve que o campo "String otherDetails" é o tal do textarea full horizontal que te falei, o qual acompanha o redimensionamento da tela. No primeiro caso da tela (que se enquadra nos seus 300px) os controles sao colocados um abaixo do outro. No segunco caso, uma anotacao "disse" para os campos serem dispostos em "full distribution", o que indica o algoritmo a coloca-los lado a lado (exetuando-se o campo otherDetails - justamente por ele ser full horizontal) e o "active", pois este fora anotado para ser um campo "isolado". A ordem dos campos, nessas telas nao esta conforme seria o padrao - onde o campo "otherDetails" deveria ser o ultimo (devido algumas heuristicas) - justamente por existir uma anotacao @After("name") nesse campo, que implica que esse controle deve vir apos o controle "name".

Em suma cara, é bem maluco. A jogada, em tudo isso que te falei é que, em nenhum momento "eu disse a posicao exata do controle na tela", ou seja, eu dei posicoes relativas uns aos outros em conjunto com heuristicas e deixei os algoritmos trabalhar. Muitas telas que o merlin gera, a gente só ve o resultado quando ele gerou a tela, dai a gente ajusta - mesmo porque a gente nao consegue "visualizar as heuristicas em conjunto" para saber o resultado.

Nao sei se ajudei voce...apenas tentei explicar (muito porcamente - eu lendo o post agora) mais ou menos qual a ideia do merlin por baixo dos panos...

Att,
--
Marcelo Mrack
3Layer Tecnologia
www.3layer.com.br

Seja doador de medula óssea. Não dói. Não tira pedaço. Salva vidas.
Informe-se: www.abrale.org.br
MerlinMinimumTest-1.PNG
MerlinMinumintest-3.PNG

Marcos Barreto

unread,
Oct 5, 2007, 6:14:25 PM10/5/07
to treelaye...@googlegroups.com
Marcelo, tem como nos mostrar estes algoritimos plugáveis de posicionamento e heuristicas? para podermos implementá-las em delphi?

Estamos tentando definir como gerar GUI's diferentes para a mesma classe tb. como o merlin trata isso?

O merlin usa as heurísticas para gerar a tela na aplicação final? ou apenas durante a compilação? to perguntando isso por que o usuario final (o cliente, não o programador) enlouqueceria caso ele abrisse a mesma tela em momentos diferentes e os controles fossem posicionados em locais diferentes a cada geração. Isso sim seria uma loucura!

--
Marcos Barreto
MicroProcess Sistemas Ltda - Sócio-Diretor

Marcelo Mrack

unread,
Oct 12, 2007, 5:45:00 PM10/12/07
to treelayer-merlin
Oi,

Desculpa a demora. E por enquanto, também desculpa a resposta vaga,
pois código mesmo só posso mostrar depois que eu entregar a
dissertação....

Bem, Os algortitmos plugáveis que falo nada mais são que um "monte de
código escrito em qualquer e que pode fazer qualquer coisa em qualquer
parte do sistema". Na prática, a única exigência é a clássica
implementação de uma interface comum, que possui um método "doLayout",
que recebe como parâmetro o "root" do grafo de objetos que a tela de
cadastro está vinculada. É tarefa do algoritmo extrair as meta-
informações do grafo recebido e gerar o posicionamento e distribuição
dos controles como achar melhor. Essas meta-informações são as
anotações (JSR 175) do Java. Para .Net, uma outra empresa parceira
nossa deve estar assumindo a implementação, e daí não tenho detalhes
ainda (mas parece que o conceito é o mesmo). Aqui, Groovy e BeanShell
são uma mão na roda.

GUIs diferentes para uma mesma classe ainda não está estável e a
solução que tenho acho que pode ser melhorada. Na prática, o que faço
nesses casos é declarar interfaces "ocas" no mesmo nível da classe de
base. E usar essas interfaces no lugar das classes originais na hora
da geração. Porém, não é uma solução "bonita", por assim dizer. Outra
alternativa não descartada é usar o pattern Wrapper, onde a classe
original é empacotada noutra classe (o Wrapper). Daí, no wrapper
usando o padrão delegate, eu poderia sobreescrever somente aquilo que
o wrapper tem de diferente da classe original. Nesse caso, o wrapper
deveria ter um marcador (uma anotação), de forma que o Merlin saiba
que, ao recebê-lo, ele deve buscar as informações para geração ora da
classe/objeto empacotado e ora do wrapper. Essas abordagens contrastam
de outras soluções que vi na minha pesquisa, onde os caras usam
herança para resolver isso. Não gosto de herança para isso, pois
muitas vezes as telas podem estar operando sobre classes final, e daí
já era...

As heurísticas são feitas durante a montagem da tela, em tempo de
execução. Nada existe nada em tempo de compilação. Mas, toda a
execução pode ser prevista, ou seja, saberemos o que vai acontecer em
tempo de execução. Assim, não tem perigo de uma tela mudar a cada vez
que executa o sistema. Isso é garantido por um complexo mecanismo de
gerência de histórico (a parte mais complicada do sistema, pra dizer a
verdade) que já tem uma implementação básica, mas que deve ser
refinado muito ainda (na prática, acho que isso vai ser tema do meu
Doutorado no futuro...). É esse mecanismo que garante coisas como, se
um sistema S1 mudar alguma coisa, essa mudança possa ser propagada de
forma gerenciada para os sistemas S2, S3, S4, etc. ao longo da
cadeia...E note que isso é realimentado, pois a mudança em S2, nesse
caso implicaria novamente em mudanças em S3, S4 e assim, um ciclo
recursivo. Por isso é complexo :)

Bem, enchi de historinhas. Não sei se ajudei :)

Reply all
Reply to author
Forward
0 new messages