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 :
| Axe | Valeurs |
|---|---|
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.
// 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")
| Fonction | Effet |
|---|---|
PBT_SetDefaultTheme (string as_nom) | Thème par défaut du processus (diffusé à tous les composants) |
PBT_GetDefaultTheme ( ) → string | Thème par défaut courant |
PBT_SetDefaultThemeAccent (long al_couleur) | Couleur d'accent par défaut (-1 = accent natif du thème) |
PBT_GetDefaultThemeAccent ( ) → long | Accent 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é | Type | Défaut | Rôle |
|---|---|---|---|
is_theme_style | string | fluent | Style visuel (constantes THEME_STYLE_*) |
is_theme_mode | string | light | Variante claire ou sombre (constantes THEME_MODE_*) |
il_theme_accent | long | -1 | Couleur 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_accent | le composant | son accent, et tout ce qui en dérive : le texte lisible dessus, le fond applicatif, le souligné d'onglet |
il_accent | un handle d'item, de groupe, d'onglet, de barre | ce que cette zone peint à l'accent, descendants compris |
il_back_color · il_text_color | idem | le fond et le texte de l'item |
il_back_color_hover · il_text_color_hover | idem | les 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 :
| Forme | Exemple | Usage |
|---|---|---|
| Fichier | img\logo.png | Image telle quelle (png, jpg, gif, bmp, ico, svg, webp) |
| Ressource de DLL | img\packimages.dll:RIBBON | Image packagée dans une DLL de ressources |
mono: | mono:img\save.svg | Aplat à la couleur du thème : seule la forme compte |
tint: | tint:img\logo_couleur.png | Duotone : le relief interne module la couleur du thème |
mono:s'utilise pour tous les glyphes monochromes (icônes blanches ou noires) : ils se recolorent automatiquement en clair comme en sombre.tint:harmonise une icône couleur avec le thème en conservant ses dégradés. À ne jamais utiliser sur un glyphe blanc (il resterait blanc).- Sans préfixe, l'image multicolore est laissée intacte.
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.
lnv_bar.of_add_button("save", "Enregistrer", uo_toolbar.of_icon("mono:img\save.svg"))
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.
| Balise | Effet |
|---|---|
[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_id), 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 : " + uo_st.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.