PBToolboxAI v1 ← Site

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 #

Userobjectu_pbt_listbar
Classes d'itemsn_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-inib_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
n_pbt_listbar_section lnv_section

lnv_section = uo_nav.of_add_header(/*id*/ "nav", /*titre*/ "Navigation")
lnv_section.of_add_item(/*id*/ "accueil",   /*libelle*/ "Accueil",   /*icone*/ "mono:img\home.svg")
lnv_section.of_add_item(/*id*/ "documents", /*libelle*/ "Documents", /*icone*/ "mono:img\doc.svg")
lnv_section.of_add_item(/*id*/ "recherche", /*libelle*/ "Recherche", /*icone*/ "mono:img\find.svg")

uo_nav.of_add_header(/*id*/ "config", /*titre*/ "Parametres") &
      .of_add_item(/*id*/ "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_section, string as_from_id,
//                                       string as_section, string as_id)
choose case as_section + "/" + as_id
    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_section, as_from_id, as_section, as_id).


Propriétés #

PropriétéTypeDéfautRôle
ib_collapsedbooleanfalsetrue replie la barre en rail d'icônes : les libellés disparaissent, les icônes restent cliquables
ib_auto_widthbooleanfalseOpt-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_reorderablebooleanfalseOpt-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_selectionbooleantrueDemander 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_stylestringfluentStyle visuel du composant (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)
is_tooltipstring""Info-bulle simple affichée au survol du composant
is_super_tooltip_titlestring""Titre de l'info-bulle enrichie (prend le pas sur is_tooltip)
is_super_tooltip_textstring""Texte de l'info-bulle enrichie (balisage riche accepté)
is_super_tooltip_imagestring""Image de l'info-bulle enrichie

Propriétés d'une section — n_pbt_listbar_section #

PropriétéTypeDéfautRôle
is_titlestring""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_collapsedbooleanfalseAccordé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éTypeDéfautRôle
is_textstring""Libellé de l'entrée, modifiable à chaud sans reconstruire la barre. Accepte le balisage riche
is_imagestring""Icône, modifiable à chaud (formes acceptées : chemin, mono:, tint:, ressource de DLL)
ib_enabledbooleantruefalse grise l'entrée et bloque son clic
ib_visiblebooleantruefalse masque l'entrée sans la retirer de la barre
is_tooltipstring""Info-bulle simple affichée au survol de l'item
is_super_tooltip_titlestring""Titre de l'info-bulle enrichie de l'item (prend le pas sur is_tooltip)
is_super_tooltip_textstring""Texte de l'info-bulle enrichie de l'item (balisage riche accepté)
is_super_tooltip_imagestring""Image de l'info-bulle enrichie de l'item

Méthodes #

Sur le composant #

MéthodeRôle
of_add_header (string as_id, string as_text)Ajoute une section et renvoie son handle n_pbt_listbar_section, sur lequel s'enchaînent les ajouts d'entrées
of_section (string as_id)Handle d'une section existante (créé au premier accès)
of_insert_item (string as_section, string as_id, string as_text, integer ai_index)Insère une entrée à la position ai_index dans sa section
of_insert_item (string as_section, string as_id, 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
of_move_item (string as_section, string as_id, integer ai_index)Déplace une entrée existante dans sa section, en conservant son état
of_remove_item (string as_section, string as_id)Retire une entrée désignée par son couple section / identifiant
of_clear ( )Vide la barre : toutes les sections et toutes les entrées
of_select_item (string as_section, string as_id)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
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
of_clear_selection ( )Ne laisse aucune entrée sélectionnée. Annoncé comme n'importe quel autre déplacement
of_selected_key ( )Identifiant de l'entrée sélectionnée, "" si aucune. Toujours l'entrée courante : un clic et of_select_item repassent tous deux par ue_selection_changed
of_selected_section ( )Section qui porte l'entrée sélectionnée — un identifiant d'entrée n'est unique que dans sa section, c'est donc le couple qui désigne la sélection. "" si aucune
of_reset ( )Vide la barre puis ramène le composant à son état neuf
of_set_redraw (boolean)Regroupe une rafale de modifications en un seul rendu
of_save_as_png (string) · of_save_as_jpg (string)Exporte le rendu en image

Sur une section — n_pbt_listbar_section #

MéthodeRôle
of_add_item (string as_id, string as_label, string as_icon_file)Ajoute une entrée normale à cette section et renvoie son handle
of_item (string as_id)Handle d'une entrée de cette section (créé au premier accès)

Événements #

ÉvénementDéclenché quand
ue_selection_changed (string as_from_section, string as_from_id, string as_section, string as_id)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_section, boolean ab_collapsed)L'utilisateur plie ou déplie une section par son en-tête
ue_item_reordered (string as_section, string as_id, 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. 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_section, string as_from_id, string as_section, string as_id) → booleanAnnulable, 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 #

n_pbt_listbar_section lnv_dossiers, lnv_outils

uo_nav.of_set_redraw(false)

lnv_dossiers = uo_nav.of_add_header("dossiers", "Dossiers")
lnv_dossiers.of_add_item("recents",  "Recents",  "mono:img\clock.svg")
lnv_dossiers.of_add_item("clients",  "Clients",  "mono:img\user.svg")
lnv_dossiers.of_add_item("archives", "Archives", "mono:img\box.svg")

lnv_outils = uo_nav.of_add_header("outils", "Outils")
lnv_outils.of_add_item("import", "Importer", "mono:img\import.svg")
lnv_outils.of_add_item("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_section, boolean ab_collapsed)
of_enregistrer_preference("section_" + as_section, String(ab_collapsed))

Réagir à la navigation #

// event ue_selection_changed de uo_nav : (string as_from_section, string as_from_id,
//                                       string as_section, string as_id)
// La section fait partie de la cle : deux sections peuvent avoir une entree "liste".
choose case as_section
    case "dossiers" ; of_ouvrir_dossier(as_id)
    case "outils"   ; of_lancer_outil(as_id)
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_section, string as_from_id, string as_section, string as_id)
// Renvoyer FALSE garde l'utilisateur sur l'entree qu'il quitte.
if of_saisie_en_cours(as_from_section, as_from_id) 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 #


← Référence des composants · Sommaire du guide