listbar — u_pbt_listbar #
← Référence des composants · Sommaire du guide
Barre de navigation latérale : des sections repliables en accordéon contenant des entrées à icône, avec bandeau d'accent sur l'entrée courante et repli en rail d'icônes.
▶ Le voir en vrai — Application de démonstration, tuile Listbar : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Userobject | u_pbt_listbar |
| Classes d'items | n_pbt_listbar_section (section) → n_pbt_listbar_item (entrée) |
| Sert à | Remplacer un menu latéral bricolé à coups de boutons par une navigation structurée, thémée et repliable |
| Options opt-in | ib_auto_width, ib_reorderable |
C'est le seul composant de la bibliothèque à publier ib_auto_width : sa largeur naturelle a un sens, puisque le rail replié est nettement plus étroit que la barre déployée. Le cas courant est d'ailleurs déjà couvert sans rien activer — ib_collapsed = true rétrécit la barre au rail, et lui rend sa largeur au dépliage.
Démarrage rapide #
// event open de la fenetre
uo_nav.of_add_section(/*key*/ "nav", /*titre*/ "Navigation")
uo_nav.of_add_item(/*keys*/ "nav/accueil", /*libelle*/ "Accueil", /*icone*/ "mono:img\home.svg")
uo_nav.of_add_item(/*keys*/ "nav/documents", /*libelle*/ "Documents", /*icone*/ "mono:img\doc.svg")
uo_nav.of_add_item(/*keys*/ "nav/recherche", /*libelle*/ "Recherche", /*icone*/ "mono:img\find.svg")
uo_nav.of_add_section(/*key*/ "config", /*titre*/ "Parametres")
uo_nav.of_add_item(/*keys*/ "config/preferences", /*libelle*/ "Preferences", /*icone*/ "mono:img\gear.svg")
// La selection se pose sur l'ENTREE, par son chemin complet
uo_nav.of_select_item("nav", "accueil")
// event ue_selection_changed de uo_nav : (string as_from_keys, string as_keys)
choose case as_keys
case "nav/accueil" ; of_ouvrir_accueil()
case "nav/documents" ; of_ouvrir_documents()
case "config/preferences"; of_ouvrir_preferences()
end choose
Deux niveaux, un chemin obligatoire #
Un identifiant d'entrée n'est unique que dans sa section : il n'existe donc aucun raccourci vers l'entrée. Tout accès passe par la section, ce qui rend l'écriture non ambiguë — voir Hiérarchies.
// Composant -> section -> entree -> propriete
uo_nav .of_section("nav") .of_item("docs") .is_text = "Documents"
Les events portent eux aussi le chemin complet, et l'entrée quittée avec : ue_selection_changed(as_from_keys, as_keys).
Propriétés #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
ib_collapsed | boolean | false | true replie la barre en rail d'icônes : les libellés disparaissent, les icônes restent cliquables |
ib_auto_width | boolean | false | Opt-in : idem pour la largeur, y compris dépliée (la barre se cale sur le libellé le plus long). Le repli en rail, lui, se rétrécit déjà tout seul ; ue_auto_width suit dans les deux cas |
ib_reorderable | boolean | false | Opt-in : l'utilisateur peut déplacer une entrée à la souris. Le déplacement reste dans sa section — un identifiant d'entrée n'est unique que là, donc traverser risquerait deux clés identiques (déclenche ue_item_reordered) |
ib_veto_selection | boolean | true | Demander avant que la sélection ne se déplace (déclenche ue_selection_changing, qui peut refuser). Actif par défaut : ne rien scripter laisse toujours passer. Mettez-le à false pour supprimer l'aller-retour vers PowerBuilder (~35 ms) là où il se verrait — navigation clavier, sélection déplacée en boucle |
is_theme_style | string | fluent | Style visuel du composant (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) |
is_tooltip | string | "" | Info-bulle simple affichée au survol du composant |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie |
Propriétés d'une section — n_pbt_listbar_section #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_title | string | "" | Titre de la section. Accepte le balisage riche. Un titre vide n'affiche aucune ligne d'en-tête : la section devient un simple regroupement invisible |
ib_collapsed | boolean | false | Accordéon : true replie les entrées de cette section. L'en-tête reste visible, son chevron pivote |
Propriétés d'une entrée — n_pbt_listbar_item #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_text | string | "" | Libellé de l'entrée, modifiable à chaud sans reconstruire la barre. Accepte le balisage riche |
is_image | string | "" | Icône, modifiable à chaud (formes acceptées : chemin, mono:, tint:, ressource de DLL) |
ib_enabled | boolean | true | false grise l'entrée et bloque son clic |
ib_visible | boolean | true | false masque l'entrée sans la retirer de la barre |
of_is_selected ( ) → boolean | — | — | Cette entrée est-elle la sélectionnée ? Lecture seule, et volontairement : la sélection est un état de la barre entière, pas un drapeau par entrée. Pour la poser, of_select sur le composant — qui lève toujours l'événement |
is_tooltip | string | "" | Info-bulle simple affichée au survol de l'item |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie de l'item (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie de l'item (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie de l'item |
Méthodes #
Sur le composant #
| Méthode | Rôle |
|---|---|
of_add_section (string as_key, string as_text) | Ajoute une section. Renvoie 0 (-5 sur un argument invalide, -2 si le composant n'est pas créé), comme tout geste de structure : le handle vient d'of_section("nav") quand vous voulez poser une propriété |
of_insert_section (string as_key, string as_text, integer ai_index) | Ajoute une section au rang demandé (première position = 1) plutôt qu'à la fin. L'index compte des sections, pas des lignes. Un nom déjà pris est laissé tel quel : deux sections sous un même nom rendraient ambiguë l'adresse de chacune de leurs entrées. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_move_section (string as_key, integer ai_index) | Déplace une section au rang ai_index, avec ses entrées. Déplacer l'en-tête seul larguerait ses entrées dans la section qui se retrouve au-dessus d'elles. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_remove_section (string as_key) | Retire une section et tout ce qu'elle contient. La vider en gardant ses entrées les rendrait orphelines : elles porteraient un identifiant de section qui ne nomme plus rien. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_section (string as_key) | Handle d'une section existante (créé au premier accès) |
of_add_item (string as_keys, string as_text, string as_image) | Ajoute une entrée à son adresse, "nav/accueil" : la section où elle atterrit, puis son propre identifiant. Renvoie 0 (-5 sur un argument invalide, -2 si le composant n'est pas créé) — -5 si le parent n'est pas une section, plutôt que de laisser l'entrée disparaître. Une surcharge omet l'icône |
of_item (string as_keys) | Handle d'une entrée, par son adresse (créé au premier accès) |
of_insert_item (string as_keys, string as_text, integer ai_index) | Insère une entrée à la position ai_index dans sa section. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_insert_item (string as_keys, string as_text, string as_image, integer ai_index) | Idem, avec l’icône de l’entrée : of_add_item en prend une, insérer doit pouvoir en prendre une aussi. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_move_item (string as_keys, integer ai_index) | Déplace une entrée existante dans sa section, en conservant son état. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_remove_item (string as_keys) | Retire une entrée désignée par son couple section / identifiant. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_clear ( ) | Vide la barre : toutes les sections et toutes les entrées. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_select_item (string as_keys) | Sélectionne une entrée — strictement équivalent à un clic de l'utilisateur : ue_selection_changing est posée d'abord, puis ue_selection_changed annonce le déplacement. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_get_layout ( ) | Relit la disposition courante en JSON : les sections dans l'ordre, chacune avec ses entrées dans l'ordre et son état replié. À stocker (fichier, base, registre) et à rendre par of_set_layout au démarrage suivant. La même paire porte les mêmes noms sur tous les composants réorganisables |
of_set_layout (string as_layout_json) | Restaure une disposition lue par of_get_layout ou reçue par ue_layout_changed. Ce que la disposition ne nomme pas garde sa place à la fin : une disposition d'hier ne doit pas faire disparaître ce qui a été ajouté depuis. L'appliquer ne déclenche aucun event — c'est vous qui l'avez fournie. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_clear_selection ( ) | Ne laisse aucune entrée sélectionnée. Annoncé comme n'importe quel autre déplacement. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_selected_key ( ) | Adresse de l'entrée sélectionnée — "nav/docs", "" si aucune. C'est exactement ce que ue_selection_changed vous remet : une comparaison est une comparaison, et non un recollage. Toujours l'entrée courante : un clic et of_select_item repassent tous deux par l'event |
of_reset ( ) | Vide la barre puis ramène le composant à son état neuf. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_set_redraw (boolean) | Regroupe une rafale de modifications en un seul rendu. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_save_as_png (string) · of_save_as_jpg (string) | Exporte le rendu en image. Renvoie 0 une fois l'image écrite, -4 si l'écriture échoue, -2 si le composant n'est pas créé |
Sur une section — n_pbt_listbar_section #
| Méthode | Rôle |
|---|
Événements #
| Événement | Déclenché quand |
|---|---|
ue_selection_changed (string as_from_keys, string as_keys) | La sélection a bougé — par clic ou par of_select_item. Mêmes arguments que ue_selection_changing : la question et son issue se lisent pareil, et le couple as_from_* désigne l'entrée quittée (vide si aucune) |
ue_section_toggled (string as_key, boolean ab_collapsed) | L'utilisateur plie ou déplie une section par son en-tête |
ue_item_reordered (string as_keys, integer ai_index) | L'utilisateur a fini de faire glisser une entrée. ai_index est son nouveau rang dans sa section, à partir de 1, comme of_move_item. Conservez cet ordre pour rendre à l'utilisateur sa barre telle qu'il l'a laissée |
ue_layout_changed (string as_layout_json) | L'arrangement a changé — l'utilisateur a réorganisé quelque chose, ou votre propre code l'a fait. Porte la disposition entière, pas seulement ce qui a bougé : la conserver tient en une affectation |
ue_selection_changing (string as_from_keys, string as_keys) → boolean | Annulable, posé avant que la sélection ne se déplace. Levé par défaut ; ib_veto_selection = false le supprime. Renvoyez false pour garder l'utilisateur où il est |
ue_auto_width (long al_width) | Le composant a recalculé sa largeur idéale — nécessite ib_auto_width = true |
ue_ready ( ) | Le composant a fini de charger ; tout ce qui a été envoyé avant a été rejoué |
ue_runtime_missing ( ) | Le runtime WebView2 est absent : le composant reste vide |
ue_bg_color (long al_color) | Le composant a calculé sa couleur de fond de thème ; l'userobject l'a déjà adoptée (backcolor) |
Exemples #
Menu latéral complet #
uo_nav.of_set_redraw(false)
uo_nav.of_add_section("dossiers", "Dossiers")
uo_nav.of_add_item("dossiers/recents", "Recents", "mono:img\clock.svg")
uo_nav.of_add_item("dossiers/clients", "Clients", "mono:img\user.svg")
uo_nav.of_add_item("dossiers/archives", "Archives", "mono:img\box.svg")
uo_nav.of_add_section("outils", "Outils")
uo_nav.of_add_item("outils/import", "Importer", "mono:img\import.svg")
uo_nav.of_add_item("outils/export", "Exporter", "mono:img\export.svg")
uo_nav.of_set_redraw(true)
uo_nav.of_select_item("dossiers", "recents")
Rail repliable qui libère la place #
// Replier en rail d'icones : la barre se retrecit d'elle-meme (et reprend sa
// largeur quand vous la depliez).
uo_nav.ib_collapsed = true
// event ue_auto_width de uo_nav : (long al_width)
// La barre vient d'adopter sa largeur ideale : recaler ce qui se trouve a droite.
uo_contenu.x = uo_nav.x + al_width
uo_contenu.width = parent.width - uo_contenu.x
Accordéon : replier une section #
// Replier la section des archives, rarement utilisee
uo_nav.of_section("archives").ib_collapsed = true
// event ue_section_toggled de uo_nav : (string as_keys, boolean ab_collapsed)
of_enregistrer_preference("section_" + as_keys, String(ab_collapsed))
Réagir à la navigation #
// event ue_selection_changed de uo_nav : (string as_from_keys, string as_keys)
// L'adresse porte les deux niveaux : deux sections peuvent avoir une entree "liste".
n_pbt_utils lnv_utils // autoinstantiate : rien a creer, rien a detruire
string ls_ids[]
if lnv_utils.of_split_path(as_keys, ls_ids) < 2 then return
choose case ls_ids[1]
case "dossiers" ; of_ouvrir_dossier(ls_ids[2])
case "outils" ; of_lancer_outil(ls_ids[2])
end choose
Refuser un changement de sélection #
// La question est posee par DEFAUT : rien a activer. Cette ligne fait l'inverse,
// elle la supprime quand l'arbitrage ne sert pas et que le cout se verrait.
uo_nav.ib_veto_selection = false
// event ue_selection_changing de uo_nav :
// (string as_from_keys, string as_keys)
// Renvoyer FALSE garde l'utilisateur sur l'entree qu'il quitte.
if of_saisie_en_cours(as_from_keys) then
MessageBox("Saisie", "Terminez la fiche en cours avant de naviguer.")
return false
end if
return true
Mettre une entrée à jour à chaud #
n_pbt_listbar_item lnv_entree
// Le chemin complet est obligatoire : composant -> section -> entree
lnv_entree = uo_nav.of_section("dossiers").of_item("recents")
lnv_entree.is_text = "Recents (12)"
lnv_entree.is_image = "mono:img\clock_full.svg"
// Griser ou masquer selon les droits, sans reconstruire la barre
uo_nav.of_section("outils").of_item("import").ib_enabled = of_a_le_droit("import")
uo_nav.of_section("outils").of_item("export").ib_visible = gb_mode_expert
Sélection pilotée depuis le code #
// Poser la selection ailleurs : le bandeau d'accent suit
uo_nav.of_select_item("dossiers", "clients")
// Ou l'effacer completement
uo_nav.of_clear_selection()
Reconstruire la barre #
// of_clear vide sections et entrees ; of_reset y ajoute les defauts du composant
uo_nav.of_clear()
of_construire_menu_selon_profil()
Bonnes pratiques #
- Une entrée s'ajoute par son adresse :
of_add_item("nav/accueil", ...). Le handle de section ne sert plus qu'à poser une propriété, etof_section("nav")le rend au premier accès. - Utilisez
mono:pour les icônes : elles se recolorent avec le thème, clair comme sombre, et restent lisibles une fois la barre repliée en rail. - Un titre de section vide sert de regroupement discret : les entrées sont espacées sans qu'aucune ligne d'en-tête n'apparaisse.
ib_collapsedrétrécit l'userobject au rail, mais il ne déplace pas vos autres contrôles : traitezue_auto_widthpour occuper la place libérée, sinon elle reste vide.- En mode rail, seules les icônes subsistent : renseignez une info-bulle sur chaque entrée pour que les libellés restent accessibles.
- La question est posée par défaut : un
ue_selection_changinglaissé vide autorise toujours le déplacement, vous n'avez rien à faire. Coupez-la avecib_veto_selection = falselà où le clic est répété — navigation clavier, sélection pilotée en boucle — car chaque question coûte un aller-retour vers PowerBuilder. ib_enabled = falsevaut mieux queib_visible = falsequand l'entrée redeviendra disponible : le menu ne change pas de forme sous les yeux de l'utilisateur.
Hérité du socle commun #
Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.
| Membres | Rôle | Détaillé dans |
|---|---|---|
of_count · of_keys_at · of_has | Parcourir ce que le composant contient | 3.2 Les items |
of_reset | Remettre le composant à zéro | 3.6 Remettre un composant à zéro : of_reset() |
of_register_shortcut · of_clear_shortcuts | Raccourcis clavier du composant | 3.5 Les raccourcis clavier |
of_is_created · of_is_ready · of_get_last_error | S'il est né, s'il est prêt, ce qui a échoué | 3.7 Diagnostic |
of_save_as_png · of_save_as_jpg | Exporter le rendu en image | 3.8 Exporter le rendu en image |
of_set_redraw | Grouper les modifications en un seul repaint | 3.10 Bonnes pratiques |
of_preload_icons | Icônes affichées sans délai | Affichage instantané : of_icon |
of_set_translation | Traduire un libellé du composant | 5.2 Adapter un libellé : of_set_translation |
of_focus_webview | Donner le focus au composant | 6.4 Clavier et focus |
of_print · of_print_to_pdf | Imprimer, ou écrire un PDF | 6.9 Imprimer |
of_set_property · of_get_property · of_component_name | Piloter une propriété par son nom | 3.1 Le moteur de propriétés |
Deux aides ne sont pas héritées : of_icon et of_escape_markup vivent sur n_pbt_utils. Déclarez-en une — n_pbt_utils lnv_utils, rien à créer — et appelez-les dessus.