PBToolboxAI v4 ← Site

4. Temi e aspetto #

← Base comune · Sommario · Lingua e RTL →


4.1 I temi: due assi #

Un tema si compone di uno stile e di una modalità:

AsseValori
Stile (is_theme_style)fluent · metro · office · office2007 · office2003
Modalità (is_theme_mode)light · dark

In tutto dieci temi, denominati <style>-<mode>: fluent-light, fluent-dark, office2007-light, metro-dark…


4.2 Il tema predefinito dell'applicazione (consigliato) #

Imposti il tema una volta sola per tutta l'applicazione, prima dell'apertura della prima finestra. Viene iniettato in ogni componente prima del suo primo rendering: nessun lampeggio di stile chiaro su un'applicazione scura.

// Event open dell'oggetto applicazione
PBT_SetDefaultTheme("fluent-dark")
PBT_SetDefaultThemeAccent(RGB(0, 120, 212))   // facoltativo

Il cambio a caldo è possibile in qualsiasi momento: tutti i componenti già aperti cambiano tema istantaneamente.

Cambiare il tema predefinito non tocca l'accento dell'applicazione: quello impostato con PBT_SetDefaultThemeAccent resta, da un tema all'altro, finché non ne imposta un altro o -1.

// Commutazione chiaro / scuro da un pulsante dell'applicazione
PBT_SetDefaultTheme("fluent-light")
FunzioneEffetto
PBT_SetDefaultTheme (string as_name)Tema predefinito del processo, diffuso a tutti i componenti; un nome sconosciuto viene rifiutato (-5) e il tema precedente resta
PBT_GetDefaultTheme ( ) → stringTema predefinito corrente
PBT_SetDefaultThemeAccent (long al_accent)Accento dell'applicazione, seguito da tutti i componenti — compresi quelli con un tema locale, finché non ne hanno uno proprio; -1 lo toglie (ogni tema riprende il proprio accento); un colore di sistema PowerBuilder (oltre 0xFFFFFF) viene rifiutato (-5)
PBT_GetDefaultThemeAccent ( ) → longAccento dell'applicazione, -1 se nessuno è impostato
PBT_SetDefaultFont (string as_family, long al_size_px)Carattere di tutta l'applicazione; dimensione in pixel, 0 = quella del tema (vedi 4.4)

4.3 Il tema di un componente specifico #

Un componente può discostarsi dal tema dell'applicazione, asse per asse:

// Solo lo stile: la modalita resta quella dell'applicazione, e la segue
uo_editor.is_theme_style = uo_editor.THEME_STYLE_OFFICE2007

// Entrambi gli assi: un tema interamente locale
uo_editor.is_theme_mode  = uo_editor.THEME_MODE_DARK
uo_editor.il_theme_accent = RGB(200, 60, 40)     // -1 = accento dell'applicazione

// Tornare al tema dell'applicazione: entrambi gli assi vuoti
uo_editor.is_theme_style = ""
uo_editor.is_theme_mode  = ""
ProprietàTipoPredefinitoRuolo
is_theme_stylestring""Stile visivo (costanti THEME_STYLE_*). Vuoto = lo stile dell'applicazione, seguito a ogni cambio
is_theme_modestring""Variante chiara o scura (costanti THEME_MODE_*). Vuoto = la modalità dell'applicazione, seguita a ogni cambio
il_theme_accentlong-1Colore d'accento di questo componente. -1 = l'accento dell'applicazione, o quello del tema se l'applicazione non ne imposta

Un of_reset() restituisce entrambi gli assi e l'accento all'applicazione: il componente ne segue di nuovo tema e accento.

I due assi sono indipendenti: un asse lasciato vuoto segue il tema dell'applicazione a ogni suo cambio, non solo quello in vigore quando è stato impostato l'altro asse. Spazi e maiuscole non contano; un valore sconosciuto ("office2010", "sombre") viene ignorato e l'asse conserva il suo valore. Rileggere is_theme_style o is_theme_mode restituisce ciò che il componente mostra — per un asse vuoto, lo stile e la modalità dell'applicazione —, e il_theme_accent restituisce -1 finché il componente non ha un accento proprio. Anche un componente con un tema locale segue l'accento dell'applicazione finché non ne ha uno proprio.

💡 La soluzione più curata resta un unico tema per tutta l'applicazione. Riservi il tema locale ai casi particolari (un'area volutamente contrastata, un'anteprima di tema).


4.4 Ricolorare un componente, un gruppo o un elemento #

Tre portate, le stesse proprietà. Niente da nominare, niente da indovinare.

// Il componente intero
uo_ribbon.il_theme_accent = RGB(0, 120, 90)

// Un gruppo : tutto cio che contiene segue
uo_ribbon.of_group(/*keys*/ "home/clipboard").il_accent = RGB(0, 120, 90)

// Un elemento
uo_list.of_item(/*keys*/ "delete").il_text_color = RGB(200, 70, 70)
uo_list.of_item(/*keys*/ "delete").il_back_color = RGB(255, 235, 235)

// Gli stessi due, sotto il puntatore
uo_list.of_item(/*keys*/ "delete").il_back_color_hover = RGB(255, 220, 220)

// Tornare al colore del componente
uo_list.of_item(/*keys*/ "delete").il_text_color = -1
ProprietàDoveChe cosa ricolora
il_theme_accentil componenteil suo accento e tutto ciò che ne deriva: il passaggio del mouse e la pressione dei pulsanti d'accento, le selezioni e gli stati spuntati tinti, il testo leggibile sopra, lo sfondo applicativo, la sottolineatura di scheda
il_accentun handle di elemento, gruppo, scheda o barraciò che quella zona dipinge con l'accento, discendenti compresi
il_back_color · il_text_coloridemlo sfondo e il testo dell'elemento
il_back_color_hover · il_text_color_hoveridemgli stessi due, sotto il puntatore

-1 ripristina il colore che dà il componente, a sua volta preso dal tema. Il colore di un elemento sopravvive alla ricostruzione del componente: è portato da una regola di stile che mira all'elemento, non da una proprietà posata sul nodo del momento. of_reset() azzera tutto.

il_accent ridipinge soltanto ciò che la zona dipinge con l'accento — una selezione, una sottolineatura attiva, una barra di avanzamento. Un componente che non lo usa non ne mostrerà nulla: per «questa voce in rosso», il_back_color e il_text_color sono gli strumenti giusti, letti da ogni componente con elementi.

Il carattere di tutta l'applicazione #

PBT_SetDefaultFont("Segoe UI", 14)

Una sola chiamata veste ogni componente vivo e quelli creati in seguito — il carattere è iniettato prima del loro primo disegno. Una famiglia vuota o una dimensione di 0 restituisce quella metà al tema. La dimensione è in pixel.


4.5 Lo sfondo del componente viene segnalato a PowerBuilder #

Ogni componente dipinge il proprio sfondo in base al tema, poi ne notifica il colore: l'userobject adotta questo colore (backcolor) e attiva ue_bg_color, affinché la finestra e i controlli PowerBuilder adiacenti si accordino.

// event ue_bg_color di un componente
parent.backcolor = al_color
st_title.backcolor = al_color

È ciò che consente di mescolare componenti PBToolboxAI e controlli PowerBuilder nativi senza alcuna demarcazione visibile in tema scuro.


4.6 Immagini e icone #

Ovunque un componente si attenda un percorso di immagine (icona di un pulsante, riquadro, [picture=…]…), sono accettate quattro forme:

FormaEsempioUtilizzo
Fileimg\logo.pngImmagine così com'è (png, jpg, gif, bmp, ico, svg, webp)
Risorsa di DLLimg\packimages.dll:RIBBONImmagine inclusa in una DLL di risorse
mono:mono:img\save.svgTinta unita nel colore del tema: conta solo la forma
tint:tint:img\logo_couleur.pngDuotone: il rilievo interno modula il colore del tema

La forma percorso.dll:nome carica una risorsa da una DLL di immagini (in stile packimages.dll), aperta in sola lettura (LOAD_LIBRARY_AS_DATAFILE, nessun codice eseguito). Questo evita di distribuire centinaia di file sparsi.

Visualizzazione istantanea: of_icon #

Un piccolo glifo passato tramite of_icon() viene incorporato nel comando (nessun andirivieni di caricamento): compare fin dal primo rendering, senza lo sfarfallio di un'icona caricata in un secondo momento.

n_pbt_utils lnv_utils   // autoinstantiate : niente da creare, niente da distruggere

uo_toolbar.of_add_button(/*keys*/ "main/save", /*text*/ "Salva", /*image*/ lnv_utils.of_icon(/*path*/ "mono:img\save.svg"), /*tooltip*/ "Salva")

Per un lotto di icone note in anticipo, of_preload_icons() scalda la cache in una sola volta, all'avvio: il primo disegno non attende più nulla.

Trasparente all'uso: oltre una certa dimensione, of_icon restituisce il percorso originale (l'immagine viene allora caricata e memorizzata nella cache normalmente).


4.7 Il testo formattato con tag #

Qualsiasi etichetta di qualsiasi componente accetta una formattazione in stile BBCode: titolo di una scheda, etichetta di un pulsante, testo della barra di stato, messaggio di toast, titolo di un pannello, testo di un tooltip…

Le voci dei menu integrati seguono la stessa regola — menu contestuale di una scheda, elenco ··· delle schede che non entrano più, menu di colonna di una griglia: l'etichetta mostrata dal menu è quella del controllo, marcatura compresa.

Il testo viene renderizzato in nodi di testo e <span>: nessuna iniezione HTML è possibile.

TagEffetto
[b] [i] [u] [s] / [strike]Grassetto, corsivo, sottolineato, barrato
[sub] [super]Pedice, apice
[red]…[/red] (colori denominati)Colore del testo (red, green, blue, orange, teal…)
[accent]…[/accent]Colore d'accento del tema corrente
[color=#rrggbb] / [color=accent]Colore del testo
[bk=#rrggbb] / [backcolor=accent]Colore di sfondo
[font=Consolas]Carattere
[size=14]Dimensione assoluta, in punti (da 6 a 200)
[size+=30] / [size-=20]Dimensione relativa in % (20 % per impostazione predefinita)
[picture=percorso] / [picture=percorso,largh,alt]Immagine in linea. Accetta anche ciò che restituisce of_icon() (un data URI); le dimensioni si leggono alla fine del valore. Un percorso di rete vi è rifiutato (vedi sotto)
[symbol=nome]Simbolo integrato, monocromatico, disegnato nel colore del testo che lo circonda (segue il tema, il passaggio del mouse, un [accent]) — nessun file da distribuire: clock, location, person, people, calendar, repeat, lock, bell, phone, mail, video, note, tag, link, check, star, info, warning. Un nome sconosciuto si visualizza così com'è
[br] / [linebreak] / [br:3]Interruzione di riga (o n interruzioni)
[gap=N]Interruzione di riga seguita da uno spazio di N % di riga: [gap=100] vale [br][br], [gap=50] mezza riga vuota
[separator]Filetto orizzontale
[hyperlink=url]…[/hyperlink]Area cliccabile: il collegamento si apre sempre nel browser dell'utente, in tutti i componenti. L'event ue_hyperlink(as_url) viene sollevato in più, per i componenti che lo espongono
[action=id]…[/action]Area cliccabile → event ue_action(as_key), presentata come un collegamento
[invisibleaction=id]…[/invisibleaction]Area cliccabile → ue_action, senza lo stile del collegamento
[bullet]…[/bullet]Punto elenco: voce di elenco le cui righe successive si allineano alla prima invece di tornare sotto il marcatore (rientro sporgente). [bullet=-] cambia il marcatore
[foldarea:Titolo]…[/foldarea]Blocco comprimibile: intestazione cliccabile (− / +) sopra un contenuto rientrato. Il titolo accetta i tag
[foldarea-closed:Titolo]…[/foldarea]Lo stesso blocco, compresso alla visualizzazione
[[ / ]]Escape: [[b]] visualizza [b] senza interpretarlo
uo_text.is_text = "Benvenuto in [b][accent]PBToolboxAI[/accent][/b] [size-=20]v1.0[/size-=20]" &
                   + "[br]Consulti la [hyperlink=https://pbtoolboxai.net]documentazione[/hyperlink]."

uo_tab.of_add_page(/*key*/ "clients", /*title*/ "[b]Clienti[/b] [size-=20](128)[/size-=20]", /*page*/ uo_clients)

uo_st.is_text = "Il tag [[b]] mette in [b]grassetto[/b]"   // visualizza: Il tag [b] mette in grassetto

Mostrare un dato tale e quale. Un valore che viene dalla sua base può contenere un tag noto — [b], [red], [picture=…]: verrebbe interpretato (una parola sconosciuta fra parentesi quadre si mostra così com'è scritta). of_escape_markup(), funzione di n_pbt_utils, le raddoppia al posto suo — avvolga il dato, mai la marcatura che scrive lei stesso.

n_pbt_utils lnv_utils   // autoinstantiate : niente da creare, niente da distruggere
// Un dato applicativo puo contenere un tag NOTO : senza escape viene
// INTERPRETATO -- il [b] sparisce e il seguito passa in grassetto.
ls_label = "Sconto [b]VIP"
uo_st.is_text = "Cliente : " + ls_label                          // mostra : Cliente : Sconto VIP (VIP in grassetto)
uo_st.is_text = "Cliente : " + lnv_utils.of_escape_markup(/*text*/ ls_label)  // mostra : Cliente : Sconto [b]VIP

Un testo privo di tag non comporta alcun sovraccosto (percorso rapido). Un tag sconosciuto si mostra così com'è scritto (Saldo [netto] resta Saldo [netto]). Un tag di chiusura chiude solo il proprio tag, e un tag di chiusura senza apertura viene ignorato. Un [hyperlink] si apre ovunque — etichetta, titolo di scheda, pannello della barra di stato, toast, finestra di dialogo: se ne occupa il nucleo. L'event ue_action, invece, viene emesso solo dai componenti di testo interattivi (statictext); altrove, [action] serve unicamente alla formattazione.

Vengono aperti solo http, https e mailto, qualunque sia la loro scrittura maiuscola o minuscola (anche HTTPS://). Un'etichetta trasporta spesso un dato che viene dalla Sua base: affidare al sistema uno schema qualunque trasformerebbe un'etichetta in un lanciatore di programmi. Per la stessa ragione, un'immagine della marcatura non va mai a cercare una condivisione di rete ([picture=\\server\condivisione\x.png] è rifiutata): un commento non protetto farebbe altrimenti aprire una sessione di rete verso una macchina qualunque al solo visualizzarlo. Un'immagine di rete in un testo passa per of_icon(), che la incorpora; is_picture e le icone dei componenti mantengono l'accesso alla rete.

Un [foldarea] è un blocco: occupa tutta la larghezza e si comprime con un clic sulla sua intestazione, senza alcun passaggio da PowerBuilder. I blocchi si annidano e, se il componente segue l'altezza del proprio contenuto (ib_auto_height), tale altezza viene notificata di nuovo a ogni compressione. Anche il titolo è testo con tag: nulla viene messo in grassetto al posto vostro, ci pensa [foldarea:[b]Total[/b]].


← Base comune · Sommario · Lingua e RTL →

4.8 Le animazioni e l'impostazione della postazione #

Windows offre un'impostazione di accessibilità — Impostazioni > Accessibilità > Effetti visivi > Effetti di animazione — e i componenti la rispettano: quando è disattivata, nessun fotogramma chiave e nessuna transizione viene riprodotta. Il grafico è al suo posto, non ci va.

È il comportamento giusto per difetto, e non è in discussione: chi ha chiesto meno movimento al proprio sistema lo intendeva. ib_animated = true non cambia nulla.

Un'applicazione può comunque insistere:

// Da dichiarare una volta : Function long PBT_SetAnimationPolicy (long al_policy)
//                           Library "pbtoolboxai.dll"
PBT_SetAnimationPolicy(1)   // 1 = animare sempre, 0 = rispettare la postazione (difetto)

La chiamata vale per l'intero processo e può avvenire in qualsiasi momento: i componenti vivi la seguono subito, i successivi la ricevono all'apertura.

Metta 1 solo con una ragione vera — un chiosco, un pannello a muro, una dimostrazione il cui mestiere è proprio mostrare queste animazioni. In un'applicazione gestionale, lasci il difetto.


4.9 Comporre l'aspetto della vostra applicazione #

La libreria consegna dieci temi e non permette a un'applicazione di definirne un undicesimo: il vocabolario dei token è interno e tale resta. Ciò che offre invece sono tre leve, che si combinano — è così che si ottengono «i nostri colori» senza scrivere un tema.

// 1. LA BASE: il tema consegnato piu vicino all'obiettivo.
PBT_SetDefaultTheme("office-light")

// 2. L'ACCENTO: UN colore veste ogni componente, compresi quelli
//    creati in seguito, e tutto cio che il tema ne deriva.
PBT_SetDefaultThemeAccent(RGB(0, 105, 92))

// 3. IL CARATTERE dell'intera applicazione, in una chiamata.
PBT_SetDefaultFont("Segoe UI Semibold", 0)

Mettete queste tre righe nell'evento open dell'oggetto applicazione: raggiungono ogni componente prima del suo primo disegno, quindi senza alcun tremolio.

LevaPortataCiò che cambia
PBT_SetDefaultThemeil processostile e modalità: forme, arrotondamenti, spessori, l'intera tavolozza
PBT_SetDefaultThemeAccentil processol'accento e ciò che il tema ne deriva — passaggio e pressione dei pulsanti d'accento, selezione, testo leggibile sopra, sottolineatura della scheda; compresi i componenti con un tema locale, e sopravvive a un cambio di tema
PBT_SetDefaultFontil processofamiglia e dimensione; una famiglia vuota o una dimensione 0 restituisce quella metà al tema
il_theme_accentun componenteil proprio accento, quando una finestra deve distinguersi
il_back_color · il_text_coloruna voceuna voce precisa, in rosso perché elimina (vedi 4.4)

Ciò che questo non permette #

Ridefinire l'intera tavolozza — i grigi di superficie, i bordi, il raggio degli angoli — non è offerto. Un tema è un insieme coerente di una sessantina di valori che si rispondono: aprirne la metà produrrebbe combinazioni illeggibili che nessuno avrebbe verificato. Se la vostra identità richiede più di queste tre leve, scriveteci: un tema in più dentro la libreria è un'opzione, il vostro tema dentro il vostro codice no.

Nell'applicazione dimostrativa: barra multifunzione Home > Aspetto > Stile > Corporate (composed). La voce combina queste tre leve — nulla di riservato a noi — con due differenze: il tema è office-light o office-dark a seconda del pulsante chiaro/scuro della barra, e il carattere è impostato a 16 pixel. Il codice è wf_apply_style, nella finestra w_demo_home.


4.10 Il contrasto elevato di Windows #

Quando l'utente attiva un tema Contrasto elevato di Windows, il motore sostituisce i colori della pagina con quelli di sistema, qualunque sia il tema della libreria. I componenti ne tengono conto: le icone monocromatiche (mono:, tint:) prendono il colore del testo di sistema — quello del testo evidenziato su una riga selezionata —, gli anelli di focus e i segni disegnati come ombra ricevono un vero contorno, e ciò che porta un significato con il suo colore (un pallino di stato, un colore scelto dall'applicazione) lo conserva. Nulla da fare lato applicazione: né proprietà, né chiamata.


4.11 Il contenuto di terzi: browser web e visualizzatore PDF #

webbrowser e pdfviewer mostrano un contenuto che la libreria non disegna: un sito, o il visualizzatore PDF del motore. Questo contenuto non conosce i temi della libreria, ma legge la preferenza chiara o scura che il browser gli annuncia, come un sito legge quella di Windows. Questa preferenza segue il tema predefinito dell'applicazione (PBT_SetDefaultTheme) — non la modalità di Windows, non il tema locale di un componente: un'applicazione in fluent-dark mostra la versione scura di un sito che ne offre una, e il visualizzatore PDF nei suoi colori scuri. Prima che la pagina di terzi abbia disegnato, l'area prende lo sfondo del tema invece di un rettangolo bianco.