4. Temas e aspeto #
← Base comum · Índice · Idioma e RTL →
4.1 Os temas: dois eixos #
Um tema compõe-se de um estilo e de um modo:
| Eixo | Valores |
|---|---|
Estilo (is_theme_style) | fluent · metro · office · office2007 · office2003 |
Modo (is_theme_mode) | light · dark |
Ou seja, dez temas, designados <style>-<mode>: fluent-light, fluent-dark, office2007-light, metro-dark…
4.2 O tema predefinido da aplicação (recomendado) #
O tema deve ser definido uma única vez para toda a aplicação, antes da abertura da primeira window. É injetado em cada componente antes do respetivo primeiro desenho: nenhum flash de estilo claro numa aplicação escura.
n_pbt_utils lnv_utils // autoinstantiate : nada a criar, nada a destruir
// Evento open do objeto de aplicacao
PBT_SetDefaultTheme("fluent-dark")
PBT_SetDefaultThemeAccent(RGB(0, 120, 212)) // opcional
A alteração a quente é possível a qualquer momento: todos os componentes já abertos voltam a aplicar o tema instantaneamente.
// Alternancia claro / escuro a partir de um botao da aplicacao
PBT_SetDefaultTheme("fluent-light")
| Função | Efeito |
|---|---|
PBT_SetDefaultTheme (string as_nom) | Tema predefinido do processo (difundido a todos os componentes) |
PBT_GetDefaultTheme ( ) → string | Tema predefinido atual |
PBT_SetDefaultThemeAccent (long al_couleur) | Cor de destaque predefinida (-1 = destaque nativo do tema) |
PBT_GetDefaultThemeAccent ( ) → long | Destaque predefinido atual |
4.3 O tema de um componente específico #
Um componente pode afastar-se do tema predefinido:
uo_editeur.is_theme_style = uo_editeur.THEME_STYLE_OFFICE2007
uo_editeur.is_theme_mode = uo_editeur.THEME_MODE_DARK
uo_editeur.il_theme_accent = RGB(200, 60, 40) // -1 = destaque do tema
| Propriedade | Tipo | Predefinição | Função |
|---|---|---|---|
is_theme_style | string | fluent | Estilo visual (constantes THEME_STYLE_*) |
is_theme_mode | string | light | Variante clara ou escura (constantes THEME_MODE_*) |
il_theme_accent | long | -1 | Cor de destaque deste componente (-1 = destaque do tema) |
Um of_reset() devolve o componente ao tema predefinido do processo.
💡 O resultado mais cuidado continua a ser um único tema para toda a aplicação. O tema local deve ficar reservado para casos particulares (uma zona deliberadamente contrastada, uma pré-visualização de tema).
4.4 Recolorir um componente, um grupo ou um item #
Três alcances, as mesmas propriedades. Nada a nomear, nada a adivinhar.
// O componente inteiro
uo_ruban.il_theme_accent = RGB(0, 120, 90)
// Um grupo : tudo o que contem segue
uo_ruban.of_tab("accueil").of_group("presse-papiers").il_accent = RGB(0, 120, 90)
// Um item
uo_liste.of_item("supprimer").il_text_color = RGB(200, 70, 70)
uo_liste.of_item("supprimer").il_back_color = RGB(255, 235, 235)
// Os mesmos dois, sob o ponteiro
uo_liste.of_item("supprimer").il_back_color_hover = RGB(255, 220, 220)
// Voltar a cor do componente
uo_liste.of_item("supprimer").il_text_color = -1
| Propriedade | Onde | O que recolore |
|---|---|---|
il_theme_accent | o componente | o seu acento e tudo o que dele deriva: o texto legível por cima, o fundo da aplicação, o sublinhado de separador |
il_accent | um handle de item, grupo, separador ou barra | o que essa zona pinta com o acento, descendentes incluídos |
il_back_color · il_text_color | idem | o fundo e o texto do item |
il_back_color_hover · il_text_color_hover | idem | os mesmos dois, sob o ponteiro |
-1 repõe a cor que o componente dá, ela própria vinda do tema. A cor de um item sobrevive à reconstrução do componente: é transportada por uma regra de estilo que visa o item, e não por uma propriedade colocada no nó do momento. of_reset() limpa tudo.
il_accent só repinta o que a zona pinta com o acento — uma seleção, um sublinhado ativo, uma barra de progresso. Um componente que não o usa nada mostrará: para «esta entrada a vermelho», il_back_color e il_text_color são as ferramentas certas, lidas por todos os componentes com itens.
O tipo de letra de toda a aplicação #
PBT_SetDefaultFont("Segoe UI", 14)
Uma só chamada veste cada componente vivo e os criados depois — o tipo de letra é-lhes injetado antes do primeiro desenho. Uma família vazia ou um tamanho de 0 devolve essa metade ao tema.
4.5 O fundo do componente é comunicado ao PowerBuilder #
Cada componente pinta o seu fundo de acordo com o tema e depois notifica a respetiva cor: o userobject adota essa cor (backcolor) e aciona ue_bg_color, para que a window e os controlos PowerBuilder vizinhos fiquem em harmonia.
// evento ue_bg_color de um componente
parent.backcolor = al_color
st_titre.backcolor = al_color
É isto que permite misturar componentes PBToolboxAI e controlos PowerBuilder nativos sem demarcação visível em tema escuro.
4.6 As imagens e os ícones #
Em qualquer sítio onde um componente espera um caminho de imagem (ícone de botão, mosaico, [picture=…]…), são aceites quatro formas:
| Forma | Exemplo | Utilização |
|---|---|---|
| Ficheiro | img\logo.png | Imagem tal como está (png, jpg, gif, bmp, ico, svg, webp) |
| Recurso de DLL | img\packimages.dll:RIBBON | Imagem empacotada numa DLL de recursos |
mono: | mono:img\save.svg | Cor uniforme à cor do tema: só a forma conta |
tint: | tint:img\logo_couleur.png | Duotone: o relevo interno modula a cor do tema |
mono:utiliza-se para todos os glifos monocromáticos (ícones brancos ou pretos): são recoloridos automaticamente tanto em claro como em escuro.tint:harmoniza um ícone a cores com o tema, conservando os seus gradientes. Nunca deve ser utilizado num glifo branco (permaneceria branco).- Sem prefixo, a imagem multicolor é deixada intacta.
A forma chemin.dll:nom carrega um recurso de uma DLL de imagens (à maneira de packimages.dll), aberta apenas para leitura (LOAD_LIBRARY_AS_DATAFILE, sem execução de qualquer código). Isto evita ter de expedir centenas de ficheiros a granel.
Apresentação instantânea: of_icon #
Um pequeno glifo passado por of_icon() é incorporado no comando (sem qualquer ida e volta de carregamento): aparece logo no primeiro desenho, sem o piscar de um ícone carregado posteriormente.
n_pbt_utils lnv_utils // autoinstantiate : nada a criar, nada a destruir
lnv_bar.of_add_button("save", "Guardar", lnv_utils.of_icon("mono:img\save.svg"))
Para um lote de ícones conhecido de antemão, of_preload_icons() aquece a cache de uma só vez, no arranque: a primeira pintura deixa de esperar.
Transparente na utilização: acima de um determinado tamanho, of_icon devolve o caminho de origem (a imagem é então carregada e colocada em cache normalmente).
4.7 O texto formatado com etiquetas #
Qualquer etiqueta de qualquer componente aceita uma marcação ao estilo BBCode: título de separador, etiqueta de botão, texto de barra de estado, mensagem de toast, título de painel, texto de tooltip…
As entradas dos menus integrados seguem a mesma regra — menu de contexto de um separador, lista ··· dos separadores que já não cabem, menus de coluna de uma grelha: a etiqueta mostrada pelo menu é a do controlo, marcação incluída.
O texto é desenhado em nós de texto e em <span>: nenhuma injeção HTML é possível.
| Etiqueta | Efeito |
|---|---|
[b] [i] [u] [s] / [strike] | Negrito, itálico, sublinhado, rasurado |
[sub] [super] | Índice inferior, índice superior |
[red]…[/red] (cores nomeadas) | Cor de texto (red, green, blue, orange, teal…) |
[accent]…[/accent] | Cor de destaque do tema atual |
[color=#rrggbb] / [color=accent] | Cor de texto |
[bk=#rrggbb] / [backcolor=accent] | Cor de fundo |
[font=Consolas] | Tipo de letra |
[size=14] | Tamanho absoluto, em pontos (6 a 200) |
[size+=30] / [size-=20] | Tamanho relativo em % (20 % por predefinição) |
[picture=chemin] / [picture=chemin,larg,haut] | Imagem em linha |
[br] / [linebreak] / [br:3] | Quebra de linha (ou n quebras) |
[separator] | Filete horizontal |
[hyperlink=url]…[/hyperlink] | Zona clicável: a ligação abre sempre no navegador do utilizador, em todos os componentes. O evento ue_hyperlink(as_url) é emitido além disso, nos componentes que o expõem |
[action=id]…[/action] | Zona clicável → evento ue_action(as_key), apresentada como uma ligação |
[invisibleaction=id]…[/invisibleaction] | Zona clicável → ue_action, sem o estilo de ligação |
[bullet]…[/bullet] | Marcador: item de lista cujas linhas seguintes se alinham pela primeira em vez de voltarem sob o marcador (recuo pendente). [bullet=-] altera o marcador |
[foldarea:Título]…[/foldarea] | Bloco recolhível: cabeçalho clicável (− / +) sobre um conteúdo indentado. O título aceita etiquetas |
[foldarea-closed:Título]…[/foldarea] | O mesmo bloco, recolhido ao ser apresentado |
[[ / ]] | Escape: [[b]] apresenta [b] sem o interpretar |
uo_texte.is_text = "Bem-vindo ao [b][accent]PBToolboxAI[/accent][/b] [size-=20]v1.0[/size-=20]" &
+ "[br]Consulte a [hyperlink=https://pbtoolboxai.net]documentação[/hyperlink]."
uo_tab.of_add_page("clients", "[b]Clientes[/b] [size-=20](128)[/size-=20]", uo_clients)
uo_st.is_text = "A etiqueta [[b]] coloca a [b]negrito[/b]" // apresenta : A etiqueta [b] coloca a negrito
Apresentar um dado tal como está. Um valor vindo da sua base pode conter parênteses retos: seria interpretado. of_escape_markup(), disponível em qualquer componente, duplica-os por si — envolva o dado, nunca a marcação que escreve você mesmo.
// Um dado de negocio pode conter parenteses retos : sem escape e
// INTERPRETADO e o texto entre parenteses desaparece.
ls_libelle = "Saldo [liquido]"
uo_st.is_text = "Conta : " + ls_libelle // mostra : Conta :
uo_st.is_text = "Conta : " + lnv_utils.of_escape_markup(ls_libelle) // mostra : Conta : Saldo [liquido]
Um texto sem etiquetas não tem qualquer custo adicional (caminho rápido). As etiquetas desconhecidas são ignoradas e o respetivo conteúdo conservado. Uma [hyperlink] abre em toda a parte — rótulo, título de separador, painel da barra de estado, toast, caixa de diálogo: é a base que trata disso. O evento ue_action, esse, só é emitido pelos componentes de texto interativos (statictext); nos restantes, [action] serve apenas para formatação.
Só http, https e mailto são abertos. Um rótulo transporta muitas vezes um dado vindo da sua base: confiar ao sistema um esquema qualquer transformaria um rótulo num lançador de programas.
Um [foldarea] é um bloco: ocupa toda a largura e recolhe com um clique no seu cabeçalho, sem ida e volta ao PowerBuilder. Os blocos aninham-se e, se o componente seguir a altura do seu conteúdo (ib_auto_height), essa altura é notificada de novo a cada recolha. O título é igualmente texto com etiquetas: nada é colocado a negrito por si, [foldarea:[b]Total[/b]] trata disso.
← Base comum · Índice · Idioma e RTL →
4.8 As animações e a definição do posto #
O Windows oferece uma definição de acessibilidade — Definições > Acessibilidade > Efeitos visuais > Efeitos de animação — e os componentes respeitam-na: quando está desligada, nenhum fotograma-chave e nenhuma transição são reproduzidos. O gráfico chega ao seu lugar, não vai até lá.
É o comportamento certo por omissão, e não se discute: quem pediu menos movimento ao seu sistema queria isso mesmo. ib_animated = true não muda nada.
Uma aplicação pode ainda assim insistir:
// Declarar uma vez : Function long PBT_SetAnimationPolicy (long al_policy)
// Library "pbtoolboxai.dll"
PBT_SetAnimationPolicy(1) // 1 = animar sempre, 0 = respeitar o posto (omissao)
A chamada vale para todo o processo e pode ser feita a qualquer momento: os componentes vivos seguem-na de imediato, os seguintes recebem-na ao abrir.
Ponha
1só com uma razão verdadeira — um quiosque, um painel de parede, uma demonstração cujo ofício é justamente mostrar estas animações. Numa aplicação de gestão, deixe o valor por omissão.
4.9 Compor o aspeto da sua aplicação #
A biblioteca entrega dez temas e não permite que uma aplicação defina um décimo primeiro: o vocabulário de tokens é interno e assim permanece. O que oferece em vez disso são três alavancas, que se combinam — é assim que se obtêm «as nossas cores» sem escrever um tema.
// 1. A BASE: o tema entregue mais proximo do objetivo.
PBT_SetDefaultTheme("office-light")
// 2. O REALCE: UMA cor veste todos os componentes, incluindo os
// criados depois, e tudo o que o tema dele deriva.
PBT_SetDefaultThemeAccent(RGB(0, 105, 92))
// 3. O TIPO DE LETRA de toda a aplicacao, numa chamada.
PBT_SetDefaultFont("Segoe UI Semibold", 0)
Coloque estas três linhas no evento open do objeto aplicação: chegam a cada componente antes do seu primeiro desenho, portanto sem qualquer cintilação.
| Alavanca | Alcance | O que muda |
|---|---|---|
PBT_SetDefaultTheme | o processo | estilo e modo: formas, arredondamentos, espessuras, toda a paleta |
PBT_SetDefaultThemeAccent | o processo | o realce e o que o tema dele deriva — texto legível por cima, sublinhado do separador, seleção |
PBT_SetDefaultFont | o processo | família e tamanho; uma família vazia ou um tamanho 0 devolve essa metade ao tema |
il_theme_accent | um componente | o seu próprio realce, quando uma janela se deve distinguir |
il_back_color · il_text_color | um item | uma entrada precisa, a vermelho porque elimina (ver 4.4) |
O que isto não permite #
Redefinir a paleta completa — os cinzentos de superfície, as margens, o raio dos cantos — não é oferecido. Um tema é um conjunto coerente de umas sessenta valores que se respondem: abrir metade produziria combinações ilegíveis que ninguém teria verificado. Se a sua identidade exigir mais do que estas três alavancas, escreva-nos: mais um tema dentro da biblioteca é uma opção, o seu tema dentro do seu código não é.
Na aplicação de demonstração: friso Home > Aspeto > Estilo > Corporate (composed). A entrada aplica exatamente as três chamadas acima — nada reservado a nós. O código é
of_apply_corporate.