terça-feira, 5 de maio de 2009

Botões: Texto e ícone

Neste tópico, falarei sobre adicionar um ícone ao botão, e mostrarei as posições relativas entre ícone e texto.

Carregando o ícone

Para carregar o ícone, basta proceder conforme explicado aqui.

Na declaração da classe:
30   FXIcon *searchIcon;

Em loadIcons():
82   searchIcon = iconSource.loadScaledIconFile("icons/search.gif", 32);

Lembrando que o ícone deve ser destruído manualmente, em destroyIcons():
89   delete searchIcon;

Com isso, basta passar o ícone como terceiro argumento do construtor do botão:
new FXButton(p, "text", searchIcon, ...


Posições relativas entre ícone e texto

A relação de posição entre ícone e menu é definida em FXLabel.h. FXButton é derivado direto de FXLabel. Isso significa que todas as opções deste valem para aquele também. Significa também que toda a discussão a seguir é válida para quando adicionarmos legendas (labels) na nossa interface.

Existem cinco maneiras de posicionar um ícone em relação ao texto, e cada uma delas possui dois sinônimos. As opções são:
enum {
ICON_UNDER_TEXT = 0,
ICON_AFTER_TEXT = 0x00080000,
ICON_BEFORE_TEXT = 0x00100000,
ICON_ABOVE_TEXT = 0x00200000,
ICON_BELOW_TEXT = 0x00400000,
TEXT_OVER_ICON = ICON_UNDER_TEXT,
TEXT_AFTER_ICON = ICON_BEFORE_TEXT,
TEXT_BEFORE_ICON = ICON_AFTER_TEXT,
TEXT_ABOVE_ICON = ICON_BELOW_TEXT,
TEXT_BELOW_ICON = ICON_ABOVE_TEXT
};

Obs.: existem também opções de posicionamento de texto e ícone em relação ao widget, usando opções de justificação, mas isso fica para outro tópico.


ICON_UNDER_TEXT
TEXT_OVER_ICON

Seu valor é 0, o que indica que esta é a opção "padrão". No fim deste tópico, falarei a respeito dessa questão.

Esta opção faz com que o ícone apareça por trás do texto. Exemplo:
25   new FXButton(matrix, "ICON_UNDER_TEXT", searchIcon, NULL, 0,
26 FRAME_RAISED|FRAME_THICK|ICON_UNDER_TEXT);
27
28 new FXButton(matrix, "TEXT_OVER_ICON", searchIcon, NULL, 0,
29 FRAME_RAISED|FRAME_THICK|TEXT_OVER_ICON);



ICON_AFTER_TEXT
TEXT_BEFORE_ICON

Desenha o ícone à direita do texto. Exemplo:
32   new FXButton(matrix, "ICON_AFTER_TEXT", searchIcon, NULL, 0,
33 FRAME_RAISED|FRAME_THICK|ICON_AFTER_TEXT);
34
35 new FXButton(matrix, "TEXT_BEFORE_ICON", searchIcon, NULL, 0,
36 FRAME_RAISED|FRAME_THICK|TEXT_BEFORE_ICON);


ICON_BEFORE_TEXT
TEXT_AFTER_ICON

Desenha o ícone à esquerda do texto. Exemplo:
39   new FXButton(matrix, "ICON_BEFORE_TEXT", searchIcon, NULL, 0,
40 FRAME_RAISED|FRAME_THICK|ICON_BEFORE_TEXT);
41
42 new FXButton(matrix, "TEXT_AFTER_ICON", searchIcon, NULL, 0,
43 FRAME_RAISED|FRAME_THICK|TEXT_AFTER_ICON);


ICON_ABOVE_TEXT
TEXT_BELOW_ICON

Desenha o ícone acima do texto. Exemplo:
46   new FXButton(matrix, "ICON_ABOVE_TEXT", searchIcon, NULL, 0,
47 FRAME_RAISED|FRAME_THICK|ICON_ABOVE_TEXT);
48
49 new FXButton(matrix, "TEXT_BELOW_ICON", searchIcon, NULL, 0,
50 FRAME_RAISED|FRAME_THICK|TEXT_BELOW_ICON);


ICON_BELOW_TEXT
TEXT_ABOVE_ICON

Desenha o ícone sob o texto. Exemplo:
53   new FXButton(matrix, "ICON_BELOW_TEXT", searchIcon, NULL, 0,
54 FRAME_RAISED|FRAME_THICK|ICON_BELOW_TEXT);
55
56 new FXButton(matrix, "TEXT_ABOVE_ICON", searchIcon, NULL, 0,
57 FRAME_RAISED|FRAME_THICK|TEXT_ABOVE_ICON);


Voltando à questão do valor "padrão"

ICON_UNDER_TEXT tem valor 0, o que o torna, teoricamente, a opção padrão.

Para entender essa questão, note que as demais opções podem ser divididas entre posicionamento vertical (ICON_ABOVE_TEXT e ICON_BELOW_TEXT) e posicionamento horizontal (ICON_BEFORE_TEXT e ICON_AFTER_TEXT).

Isso significa que eu posso combinar opções de posicionameto horizontal e vertical. Porém, se eu não especificar um ou outro, a opção padrão será utilizada. Neste caso, é melhor entender a opção padrão não como o nome diz (ícone debaixo (atrás?) do texto), mas que o ícone ficará centralizado naquele eixo que não foi especificado.

Voltando aos exemplos, perceba que ICON_AFTER_TEXT e ICON_BEFORE_TEXT deixam o ícone centralizado na vertical. Da mesma forma, ICON_ABOVE_TEXT e ICON_BELOW_TEXT deixam o ícone centralizado na horizontal. Ainda, a opção ICON_UNDER_TEXT deixa o ícone centralizado em ambos os eixos.

Então por que "padrão", entre aspas? Tem algum detalhe?
Sim. Este padrão é considerado neste caso, em que se omite o posicionamento em um dos eixos. Acontece que muitos widgets FOX têm uma opção com o sufixo _NORMAL, que reúnem as opções mais comuns, e são passadas como argumento padrão para o construtor.

Assim, para o FXButton, temos BUTTON_NORMAL, definido junto com outras opções:
BUTTON_NORMAL    = (FRAME_RAISED|FRAME_THICK |
JUSTIFY_NORMAL
|ICON_BEFORE_TEXT)

Na declaração do construtor:
FXButton(FXComposite* p, ..., FXuint opts=BUTTON_NORMAL, ...

Ou seja, para um botão, o padrão é exibir o ícone à esquerda do texto. Como não foi especificado o posicionamento na vertical, fica centralizado.

Espero que essa diferença tenha ficado clara. A distinção está na questão de existir uma opção padrão (que leva o valor 0 exatamente para que não seja necessário informá-la explicitamente) e existir um argumento padrão para o construtor de um widget, que reúne as opções mais comuns, que não necessariamente são as opções padrões.

E como fica se eu combinar posicionamento vertical e horizontal?

Veja:


Deixo como exercício.

Até a próxima.

---
Código-fonte para este tutorial.

2 comentários:

Anônimo disse...

Algumas dúvidas:
Sei que o fox-toolkit é uma ferramenta para programação C e C++, mas tem como integrar o programa criado com outras tecnologias?
Se for possível, gostaria de ver um post sobre como integrar um programa C++ que usa FOX integrando com alguma outra tecnologia.

Edgar Diniz disse...

Olá,

desde já agradeço o contato.

Na verdade, como o FOX é escrito totalmente em C++, não é possível utilizá-lo em programas escritos em C.

Quanto à integração a outras tecnologias, é possível, sim. Inclusive eu já postei um tópico onde discuto uma simples integração com OpenCV, uma biblioteca de processamento de Imagens e Visão Computacional com que eu trabalho aqui na Universidade.

Pretendo discutir aqui também sobre a integração com OpenGL, e já tive trabalhos de integração com OpenSceneGraph.

Também já trabalhei em projetos envolvendo o toolkit DCMTK, que serve para manipulação de imagens médicas no padrão DICOM.

O FOX Toolkit é apenas para desenho de interface gráfica, portanto não impede o uso de outras tecnologias (excluindo, claro, outros toolkits de interface gráfica).

Quanto à utilização do FOX com outras linguagens, existem bindings para Ruby, Eiffel e Python, mas não posso oferecer suporte a elas.

Espero ter sanado sua dúvida. Sempre que precisar, não hesite em perguntar.