PBToolboxAI v2 ← Site

4. Thèmes et apparence #

← Socle commun · Sommaire · Langue et RTL →


4.1 Les thèmes : deux axes #

Un thème se compose d'un style et d'un mode :

AxeValeurs
Style (is_theme_style)fluent · metro · office · office2007 · office2003
Mode (is_theme_mode)light · dark

Soit dix thèmes, nommés <style>-<mode> : fluent-light, fluent-dark, office2007-light, metro-dark…


4.2 Le thème par défaut de l'application (recommandé) #

Posez le thème une fois pour toute l'application, avant l'ouverture de la première fenêtre. Il est injecté dans chaque composant avant son premier rendu : aucun flash de style clair sur une application sombre.

n_pbt_utils lnv_utils   // autoinstantiate : rien a creer, rien a detruire
// Event open de l'objet application
PBT_SetDefaultTheme("fluent-dark")
PBT_SetDefaultThemeAccent(RGB(0, 120, 212))   // optionnel

Le changement à chaud est possible à tout moment : tous les composants déjà ouverts se re-thèment instantanément.

// Bascule clair / sombre depuis un bouton de l'application
PBT_SetDefaultTheme("fluent-light")
FonctionEffet
PBT_SetDefaultTheme (string as_nom)Thème par défaut du processus (diffusé à tous les composants)
PBT_GetDefaultTheme ( ) → stringThème par défaut courant
PBT_SetDefaultThemeAccent (long al_couleur)Couleur d'accent par défaut (-1 = accent natif du thème)
PBT_GetDefaultThemeAccent ( ) → longAccent par défaut courant

4.3 Le thème d'un composant précis #

Un composant peut s'écarter du thème par défaut :

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 = accent du theme
PropriétéTypeDéfautRôle
is_theme_stylestringfluentStyle visuel (constantes THEME_STYLE_*)
is_theme_modestringlightVariante claire ou sombre (constantes THEME_MODE_*)
il_theme_accentlong-1Couleur d'accent de ce composant (-1 = accent du thème)

Un of_reset() ramène le composant au thème par défaut du processus.

💡 Le plus soigné reste un seul thème pour toute l'application. Réservez le thème local aux cas particuliers (une zone volontairement contrastée, une prévisualisation de thème).


4.4 Recolorer un composant, un groupe ou un item #

Trois portées, les mêmes propriétés. Rien à nommer, rien à deviner.

// Le composant entier
uo_ruban.il_theme_accent = RGB(0, 120, 90)

// Un groupe : tout ce qu'il contient suit
uo_ruban.of_tab("accueil").of_group("presse-papiers").il_accent = RGB(0, 120, 90)

// Un 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)

// Les memes, sous le pointeur
uo_liste.of_item("supprimer").il_back_color_hover = RGB(255, 220, 220)

// Revenir a la couleur du composant
uo_liste.of_item("supprimer").il_text_color = -1
PropriétéOùCe qu'elle recolore
il_theme_accentle composantson accent, et tout ce qui en dérive : le texte lisible dessus, le fond applicatif, le souligné d'onglet
il_accentun handle d'item, de groupe, d'onglet, de barrece que cette zone peint à l'accent, descendants compris
il_back_color · il_text_coloridemle fond et le texte de l'item
il_back_color_hover · il_text_color_hoveridemles mêmes, sous le pointeur

-1 remet la couleur que donne le composant, elle-même issue du thème. La couleur d'un item survit à la reconstruction du composant : elle est portée par une règle de style visant l'item, pas par une propriété posée sur l'élément du moment. of_reset() efface tout.

il_accent ne repeint que ce que la zone peint avec l'accent — une sélection, un souligné actif, une barre de progression. Un composant qui n'y touche pas n'en montrera rien : pour « cette entrée en rouge », il_back_color et il_text_color sont les bons outils, lus par tous les composants à items.

La police de toute l'application #

PBT_SetDefaultFont("Segoe UI", 14)

Un seul appel habille chaque composant vivant et ceux créés ensuite — la police leur est injectée avant leur premier affichage. Une famille vide ou une taille de 0 rend cette moitié au thème.


4.5 Le fond du composant remonte à PowerBuilder #

Chaque composant peint son fond selon le thème, puis notifie sa couleur : l'userobject adopte cette couleur (backcolor) et lève ue_bg_color, pour que la fenêtre et les contrôles PowerBuilder voisins s'accordent.

// event ue_bg_color d'un composant
parent.backcolor = al_color
st_titre.backcolor = al_color

C'est ce qui permet de mélanger composants PBToolboxAI et contrôles PowerBuilder natifs sans démarcation visible en thème sombre.


4.6 Les images et les icônes #

Partout où un composant attend un chemin d'image (icône de bouton, tuile, [picture=…]…), quatre formes sont acceptées :

FormeExempleUsage
Fichierimg\logo.pngImage telle quelle (png, jpg, gif, bmp, ico, svg, webp)
Ressource de DLLimg\packimages.dll:RIBBONImage packagée dans une DLL de ressources
mono:mono:img\save.svgAplat à la couleur du thème : seule la forme compte
tint:tint:img\logo_couleur.pngDuotone : le relief interne module la couleur du thème

La forme chemin.dll:nom charge une ressource d'une DLL d'images (façon packimages.dll), ouverte en lecture seule (LOAD_LIBRARY_AS_DATAFILE, aucun code exécuté). Cela évite d'expédier des centaines de fichiers en vrac.

Affichage instantané : of_icon #

Un petit glyphe passé par of_icon() est incorporé dans la commande (aucun aller-retour de chargement) : il apparaît dès le premier rendu, sans le clignotement d'une icône chargée après coup.

n_pbt_utils lnv_utils   // autoinstantiate : rien a creer, rien a detruire

lnv_bar.of_add_button("save", "Enregistrer", lnv_utils.of_icon("mono:img\save.svg"))

Pour un lot d'icônes connu d'avance, of_preload_icons() réchauffe le cache en une seule fois, au démarrage : le premier affichage n'attend alors plus rien.

Transparent à l'usage : au-delà d'une certaine taille, of_icon renvoie le chemin d'origine (l'image est alors chargée puis mise en cache normalement).


4.7 Le texte riche à balises #

N'importe quel libellé de n'importe quel composant accepte un balisage façon BBCode : titre d'onglet, libellé de bouton, texte de barre d'état, message de toast, titre de panneau, texte d'info-bulle…

Les entrées des menus intégrés suivent la même règle — menu contextuel d'un onglet, liste ··· des onglets qui ne tiennent plus, menus de colonne d'une grille : le libellé qu'affiche le menu est celui du contrôle, balises comprises.

Le texte est rendu en nœuds de texte et en <span> : aucune injection HTML n'est possible.

BaliseEffet
[b] [i] [u] [s] / [strike]Gras, italique, souligné, barré
[sub] [super]Indice, exposant
[red]…[/red] (couleurs nommées)Couleur de texte (red, green, blue, orange, teal…)
[accent]…[/accent]Couleur d'accent du thème courant
[color=#rrggbb] / [color=accent]Couleur de texte
[bk=#rrggbb] / [backcolor=accent]Couleur de fond
[font=Consolas]Police
[size=14]Taille absolue, en points (6 à 200)
[size+=30] / [size-=20]Taille relative en % (20 % par défaut)
[picture=chemin] / [picture=chemin,larg,haut]Image en ligne
[br] / [linebreak] / [br:3]Saut de ligne (ou n sauts)
[separator]Filet horizontal
[hyperlink=url]…[/hyperlink]Zone cliquable : le lien s'ouvre toujours dans le navigateur de l'utilisateur, dans tous les composants. L'event ue_hyperlink(as_url) est levé en plus, pour les composants qui l'exposent
[action=id]…[/action]Zone cliquable → event ue_action(as_key), présentée comme un lien
[invisibleaction=id]…[/invisibleaction]Zone cliquable → ue_action, sans le style lien
[bullet]…[/bullet]Puce : élément de liste dont les lignes suivantes s'alignent sur la première, et non sous le marqueur (retrait pendant). [bullet=-] change le marqueur
[foldarea:Titre]…[/foldarea]Bloc repliable : en-tête cliquable (− / +) au-dessus d'un contenu indenté. Le titre accepte les balises
[foldarea-closed:Titre]…[/foldarea]Le même bloc, replié à l'affichage
[[ / ]]Échappement : [[b]] affiche [b] sans l'interpréter
uo_texte.is_text = "Bienvenue sur [b][accent]PBToolboxAI[/accent][/b] [size-=20]v1.0[/size-=20]" &
                   + "[br]Consultez la [hyperlink=https://pbtoolboxai.net]documentation[/hyperlink]."

uo_tab.of_add_page("clients", "[b]Clients[/b] [size-=20](128)[/size-=20]", uo_clients)

uo_st.is_text = "La balise [[b]] met en [b]gras[/b]"   // affiche : La balise [b] met en gras

Afficher une donnée telle quelle. Une valeur venue de votre base peut contenir des crochets : elle serait interprétée. of_escape_markup(), disponible sur tout composant, les double pour vous — enveloppez la donnée, jamais le balisage que vous écrivez vous-même.

// Une donnee metier peut contenir des crochets : sans echappement, elle est
// INTERPRETEE et le texte entre crochets disparait.
ls_libelle = "Solde [net]"
uo_st.is_text = "Compte : " + ls_libelle                          // affiche : Compte :
uo_st.is_text = "Compte : " + lnv_utils.of_escape_markup(ls_libelle)  // affiche : Compte : Solde [net]

Un texte sans balise n'a aucun surcoût (chemin rapide). Les balises inconnues sont ignorées et leur contenu conservé. Un [hyperlink] s'ouvre partout — libellé, titre d'onglet, panneau de barre d'état, toast, boîte de dialogue : c'est le socle qui s'en charge. L'event ue_action, lui, n'est émis que par les composants de texte interactifs (statictext) ; ailleurs, [action] sert au seul formatage.

Seuls http, https et mailto sont ouverts. Un libellé transporte souvent une donnée venue de votre base : confier un schéma quelconque au système transformerait un libellé en lanceur de programmes.

Un [foldarea] est un bloc : il occupe toute la largeur et se replie d'un clic sur son en-tête, sans aller-retour avec PowerBuilder. Les blocs s'imbriquent, et lorsque le composant suit la hauteur de son contenu (ib_auto_height), cette hauteur est renotifiée à chaque repli. Le titre est lui-même du texte à balises : rien n'est mis en gras à votre place, [foldarea:[b]Total[/b]] s'en charge.


← Socle commun · Sommaire · Langue et RTL →

4.8 Les animations et le réglage du poste #

Windows offre un réglage d'accessibilité — Paramètres > Accessibilité > Effets visuels > Effets d'animation — et les composants l'honorent : quand il est désactivé, aucune image-clé et aucune transition ne joue. Le graphique arrive à sa place, il n'y va pas.

C'est le bon comportement par défaut, et il ne se discute pas : quelqu'un qui a demandé moins de mouvement à son système le pensait. ib_animated = true n'y change rien.

Une application peut malgré tout insister :

// A declarer une fois : Function long PBT_SetAnimationPolicy (long al_policy)
//                       Library "pbtoolboxai.dll"
PBT_SetAnimationPolicy(1)   // 1 = toujours animer, 0 = respecter le poste (defaut)

L'appel vaut pour tout le processus et peut se faire à n'importe quel moment : les composants vivants suivent aussitôt, les suivants la reçoivent à leur ouverture.

Ne posez 1 que si votre application a une vraie raison de passer outre — une borne, un écran mural, une démonstration dont le métier est justement de montrer ces animations. Pour une application de gestion, laissez le défaut.


4.9 Composer l'apparence de votre application #

La bibliothèque livre dix thèmes et ne permet pas à une application d'en définir un onzième : le vocabulaire de jetons est interne, et il le reste. Ce qu'elle offre à la place tient en trois leviers, qui se combinent — c'est ainsi qu'on obtient « nos couleurs » sans écrire un thème.

// 1. LA BASE : le thème livré le plus proche de la cible.
PBT_SetDefaultTheme("office-light")

// 2. L'ACCENT : UNE couleur habille tous les composants, y compris ceux
//    créés ensuite, et tout ce que le thème en dérive.
PBT_SetDefaultThemeAccent(RGB(0, 105, 92))

// 3. LA POLICE de toute l'application, en un appel.
PBT_SetDefaultFont("Segoe UI Semibold", 0)

Posez ces trois lignes dans l'event open de l'objet application : elles atteignent chaque composant avant son premier rendu, donc sans le moindre clignotement.

LevierPortéeCe qu'il change
PBT_SetDefaultThemele processusle style et le mode : formes, arrondis, épaisseurs, toute la palette
PBT_SetDefaultThemeAccentle processusl'accent, et ce que le thème en dérive — texte lisible dessus, souligné d'onglet, sélection
PBT_SetDefaultFontle processusla famille et la taille ; une famille vide ou une taille 0 rend cette moitié au thème
il_theme_accentun composantson accent à lui, quand une fenêtre doit se distinguer
il_back_color · il_text_colorun itemune entrée précise, en rouge parce qu'elle supprime (voir 4.4)

Ce que cela ne permet pas #

Redéfinir la palette complète — les gris de surface, les bordures, le rayon des arrondis — n'est pas offert. Un thème est un ensemble cohérent d'une soixantaine de valeurs qui se répondent : en ouvrir la moitié produirait des combinaisons illisibles que personne n'aurait vérifiées. Si votre charte demande davantage que ces trois leviers, écrivez-nous : un thème de plus dans la bibliothèque est une option, votre thème dans votre code n'en est pas une.

Dans l'application de démonstration : ruban Home > Apparence > Style > Corporate (composed). L'entrée applique exactement les trois appels ci-dessus — rien qui nous soit réservé. Le code est celui de of_apply_corporate.