breadcrumb — u_pbt_breadcrumb #
← Référence des composants · Sommaire du guide
Fil d'Ariane : le chemin cliquable qui dit à l'utilisateur où il est, et qui le ramène d'un clic à n'importe quel niveau au-dessus.
▶ Le voir en vrai — Application de démonstration, tuile Breadcrumb : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Userobject | u_pbt_breadcrumb |
| Classe d'items | n_pbt_breadcrumb_item (of_item(adresse)) · n_pbt_breadcrumb_child (of_child(adresse)) |
| Sert à | Dire où l'on est dans une arborescence, et permettre d'en remonter |
| Principe | Vous décrivez le chemin ; le repli, le menu et la mise en page sont à nous |
Démarrage rapide #
// A chaque fois que l'utilisateur descend d'un niveau
uo_crumbs.of_add_item(/*keys*/ "home", /*text*/ "H")
uo_crumbs.of_add_item(/*keys*/ "home/clients", /*text*/ "C")
uo_crumbs.of_add_item(/*keys*/ "home/clients/dupont", /*text*/ "D")
// Le dernier ajoute devient le lieu courant - et il repond au clic
Un segment se nomme par son adresse : les clés depuis la racine, jointes par / — "home/clients/dupont". Une clé nue ne suffit plus dès qu'elle se répète à deux niveaux du même fil : le composant refuse alors de deviner, plutôt que de vous emmener ailleurs.
C'est exactement ce que ue_item_clicked vous rend, et exactement ce que of_truncate, of_item ou of_add_child reprennent : ce que vous recevez se réinjecte tel quel.
Un clic rapporte, il ne coupe pas #
Cliquer un segment ne raccourcit pas le fil. Remonter, c'est quitter un écran, et quitter un écran veut souvent dire enregistrer d'abord — ce qu'aucun clic ne peut décider. Le composant vous dit ce qui a été cliqué ; c'est vous qui coupez, par of_truncate, une fois vos contrôles passés.
C'est la même répartition des rôles que sur la stepbar, et pour la même raison. Un composant qui se déplace tout seul oblige l'application à défaire un mouvement déjà fait, au lieu de simplement choisir s'il a lieu.
Deux segments ne rapportent jamais rien : un segment désactivé, un segment caché. Le dernier — là où l'on est — répond comme les autres, jusqu'à ce que ib_last_clickable dise non.
// event ue_item_clicked : (string as_keys)
// Vos controles d'abord - c'est vous qui decidez de quitter l'ecran
if not of_can_leave() then return
uo_crumbs.of_truncate(/*keys*/ as_keys)
of_open_screen(as_keys)
Quand le chemin est trop long #
Un chemin est aussi long que les données le font, et la largeur est ce qu'elle est. is_overflow_mode dit ce qui cède.
| Constante | Ce qui se passe |
|---|---|
OVERFLOW_COLLAPSE | Le milieu se replie dans un … qui ouvre ce qu'il cache — le défaut |
OVERFLOW_SCROLL | Les libellés restent entiers, la bande glisse (la molette la fait glisser aussi) |
OVERFLOW_SHRINK | Les segments du milieu cèdent du terrain, jusqu'à une lettre et des points de suspension ; le premier et le lieu courant ne cèdent qu'en dernier. Avec de la place, rien n'est coupé |
Ni le premier segment ni le dernier ne se replient jamais. Perdre la racine, c'est perdre l'ancre où tout le monde revient ; perdre la fin, c'est perdre l'endroit où l'on est.
Un segment replié rapporte exactement comme les autres : le choisir dans le
…lève le mêmeue_item_clicked. Être caché par la largeur ne change pas ce qu'un segment veut dire.
ii_max_visible impose un plafond ferme, quelle que soit la place. Laissez-le à 0 — le défaut — pour que la largeur décide, ce qu'un fil d'Ariane devrait normalement suivre.
Le menu de fratrie #
of_add_child donne à un segment son propre menu déroulant : les autres branches de ce niveau. C'est ce qui évite de remonter à la racine pour redescendre dans le dossier d'à côté.
Le chevron qui suit le segment devient alors le bouton qui les ouvre — c'est le même que le séparateur, comme dans l'explorateur Windows : un seul chevron, un seul sens à apprendre. Choisir une branche lève ue_child_clicked, et là encore le fil ne bouge pas de lui-même. Au clavier, Flèche bas sur un segment ouvre ses branches, et sur le … ce qu'il cache.
// Two branches under Clients : its chevron lists them
uo_crumbs.of_add_child(/*keys*/ "home/clients/durand", /*text*/ "D")
uo_crumbs.of_add_child(/*keys*/ "home/clients/martin", /*text*/ "M")
Les branches à la demande #
Poser toutes les branches à l'avance ne tient pas sur un arbre profond, ni sur une base de données. L'explorateur Windows ne lit un dossier que quand on ouvre son chevron ; le fil fait pareil : marquez un segment avec ib_has_children, son chevron s'affiche aussitôt, et l'ouvrir lève ue_children_needed. Vous posez les branches dans cet événement, et le menu s'ouvre à son retour avec ce que le segment porte à cet instant. Un gros dossier ne pose pas de problème : ajouter 30 000 branches ne relit rien, et dans le menu ouvert, taper les premières lettres (« Win ») saute à la première branche qui commence ainsi, comme dans l'explorateur.
// Le segment promet : le chevron s'affiche, rien n'est lu
uo_crumbs.of_item(/*keys*/ "home/clients").ib_has_children = true
// Dans ue_children_needed(as_keys) : lu maintenant, puis le menu s'ouvre
uo_crumbs.of_clear_children(/*keys*/ as_keys)
uo_crumbs.of_add_child(/*keys*/ as_keys + "/durand", /*text*/ "Durand SARL")
Saisir le chemin #
Avec ib_editable, la partie vide de la barre se comporte comme la barre d'adresse de l'explorateur Windows : un clic (ou F2, ou of_edit) change le fil en champ de texte qui porte l'adresse affichée — les clés jointes par /, ce que of_path rend. Entrée lève ue_path_entered avec le texte tel que tapé ; Échap annule. Le fil ne bouge pas de lui-même, pour la même raison qu'un clic ne le raccourcit pas : seule votre application sait ce que les mots veulent dire. ii_edit_skip laisse les premiers segments hors du champ — la racine qui nomme la machine — et les remet devant ce qui a été tapé au moment du rapport.
Propriétés #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_separator | string | chevron | Le glyphe entre les segments (constantes SEPARATOR_*). Il se retourne tout seul dans une langue qui s'écrit de droite à gauche : choisissez un sens, pas une direction. Un séparateur qui ouvre des branches garde le glyphe choisi : c'est le survol et le curseur qui disent qu'il s'ouvre |
is_overflow_mode | string | collapse | Ce qui cède quand le chemin ne tient plus (constantes OVERFLOW_*). En scroll, la bande suit le lieu courant |
ii_max_visible | integer | 0 | Plafond ferme du nombre de segments affichés, le … non compté. 0 laisse décider la largeur |
ib_last_clickable | boolean | true | Le dernier segment — là où l'on est — répond-il au clic ? Vrai par défaut : un fil sert aussi à recharger ce qu'on regarde, et ce que le clic fait est l'affaire de votre application. Mettez-le à faux quand votre fil ne fait que naviguer |
ib_editable | boolean | false | Le chemin peut-il être saisi ? Vrai : un clic sur la partie vide de la barre (ou F2, ou of_edit) change le fil en champ de texte qui porte l'adresse du lieu courant (ce que rend of_path) ; Entrée lève ue_path_entered, quitter le champ après l'avoir modifié aussi, Échap annule. Un champ quitté sans changement ne dit rien ; cliquer un autre contrôle de l'application valide le texte, passer à une autre application garde la saisie. Le fil ne bouge jamais de lui-même |
ib_allow_drop | boolean | false | Opt-in : accepte les fichiers déposés depuis l'Explorateur Windows sur un segment. Le segment sous le curseur s'allume pendant le glissement, et ue_drop_files le nomme avec les chemins complets |
ii_edit_skip | integer | 0 | Nombre de segments de tête laissés hors du champ de saisie — une racine qui nomme la machine ne se tape pas. Ils sont remis devant ce qui a été tapé au moment du rapport : l'adresse reste complète |
is_theme_style | string | "" | Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement |
is_theme_mode | string | "" | Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement |
il_theme_accent | long | -1 | Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui 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 |
Méthodes #
| Méthode | Rôle | |
|---|---|---|
of_add_item (string as_keys, string as_text) | Ajoute un segment à la fin : il devient le lieu courant. as_keys est une clé nue ou une adresse ; une adresse n'est acceptée que si elle atterrit là où elle le dit — ses niveaux au-dessus du dernier doivent être l'adresse du dernier segment. Renvoie 0 une fois appliqué, -5 sur une clé vide, une clé qui contient ` | ou une adresse qui atterrirait ailleurs, -2` si le composant n'est pas créé |
of_add_item (string as_keys, string as_text, string as_image) | Même chose, avec l'icône affichée avant le libellé — troisième argument, comme partout ailleurs dans la bibliothèque. Un libellé vide donne un segment à icône seule (la maison de la racine). Renvoie 0 une fois appliqué, -5 sur une clé vide, une clé qui contient ` | ou une adresse qui atterrirait ailleurs, -2` si le composant n'est pas créé |
of_insert_item (string as_keys, string as_text, integer ai_index) | Insère à la position choisie (première position = 1). Une surcharge prend aussi l'icône. Une adresse n'est acceptée que si ses niveaux au-dessus du dernier sont l'adresse du segment qu'elle suit. Les segments qui suivent descendent d'un niveau : leurs adresses changent, leurs poignées sont libérées, leurs couleurs et infobulles les suivent. Renvoie 0 une fois appliqué, -5 sur une clé vide, une clé qui contient ` | ou une adresse qui atterrirait ailleurs, -2` si le composant n'est pas créé |
of_remove_item (string as_keys) | Retire un segment, par son adresse ; les autres gardent leur état. Ceux qui le suivaient remontent d'un niveau : les poignées du segment retiré et de tout ce qui le suivait sont libérées. Renvoie 0 une fois appliqué, -5 si l'adresse ne désigne aucun segment (inconnue, ou clé nue répétée), -2 si le composant n'est pas créé | |
of_truncate (string as_keys) | Supprime tout ce qui suit ce segment, qui devient le lieu courant. C'est le geste pour lequel un fil d'Ariane existe ; une adresse inconnue ou une clé nue répétée ne change rien et renvoie -5. Les poignées des segments supprimés sont libérées. Renvoie 0 une fois appliqué, -5 si l'adresse ne désigne aucun segment, -2 si le composant n'est pas créé | |
of_clear ( ) | Vide le fil ; les poignées données pour ses segments et ses branches sont libérées. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé | |
of_add_child (string as_keys, string as_text) | Ajoute une branche sœur à l'adresse donnée : le segment au-dessus gagne un chevron qui les ouvre. Une surcharge prend aussi l'icône. Renvoie 0 une fois appliqué, -5 si le segment au-dessus n'existe pas, si la clé de la branche est déjà prise sous lui ou contient ` | , -2` si le composant n'est pas créé |
of_add_children (string as_keys, string as_child_keys[], string as_texts[]) | Ajoute toute une rangée de branches sœurs sous le segment as_keys, en un seul appel : chaque texte de as_texts (et chaque image, dans la surcharge qui prend aussi une liste d'images) va avec la clé de même rang dans as_child_keys ; un texte absent montre la clé. Les mêmes branches qu'une boucle de of_add_child, sans un aller-retour chacune : un dossier de 30 000 sous-dossiers ouvre son menu aussitôt. Renvoie 0 une fois appliqué (une liste vide n'ajoute rien), -5 si l'adresse ne désigne aucun segment, ou si une clé est vide, contient / ou ` | , est déjà prise sous le segment ou revient deux fois dans la liste — rien n'est ajouté alors, -2` si le composant n'est pas créé |
of_clear_children (string as_keys) | Retire les branches sœurs d'un segment, et leurs poignées ; son séparateur redevient un simple trait. Renvoie 0 une fois appliqué, -5 si l'adresse ne désigne aucun segment, -2 si le composant n'est pas créé | |
of_remove_child (string as_keys) | Retire une branche sœur, par sa propre adresse, et sa poignée ; la dernière partie, le chevron redevient un simple trait. Renvoie 0 une fois appliqué, -5 si le segment ou la branche n'existe pas, -2 si le composant n'est pas créé | |
of_child (string as_keys) | La poignée d'une branche sœur — l'adresse que of_add_child a prise — pour la renommer, la griser ou la cacher. Le menu est un popup natif : il dessine texte, image, grisé et masqué, rien d'autre — l'infobulle et les couleurs héritées d'une poignée y sont ignorées. Une adresse à un seul niveau n'a pas de segment au-dessus : sa poignée est inerte | |
of_path ( ) | Où l'on est, sous forme d'adresse : les clés de tous les segments jusqu'au dernier visible, séparées par /. Un segment masqué y reste — il fait partie de l'adresse — et le plafond de la version de démonstration ne la coupe jamais : of_truncate(of_path()) tombe toujours juste. Lu en direct : une application qui reconstruirait cette chaîne à la main finirait par ne plus dire la même chose que le fil | |
of_edit ( ) | Ouvre le champ de saisie du chemin — le même qu'un clic sur la partie vide de la barre — depuis une entrée de menu ou un bouton à vous. Demande ib_editable. Renvoie 0 une fois appliqué, -4 si ib_editable est faux (rien ne s'ouvre), -2 si le composant n'est pas créé | |
of_item (string as_keys) | La poignée d'un segment, pour le renommer, le griser ou le cacher plus tard. Elle vit autant que son segment : of_clear, of_remove_item et of_truncate libèrent les poignées des segments qu'ils retirent | |
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éé |
Événements #
| Événement | Déclenché quand |
|---|---|
ue_item_clicked (string as_keys) | Un segment a été cliqué — dans le fil, ou dans le … qui le cache. Le fil ne se raccourcit pas : appelez of_truncate quand vos contrôles sont passés |
ue_item_rclicked (string as_keys) | Clic droit sur un segment — un menu contextuel à vous, en général. as_keys est son adresse complète, comme dans ue_item_clicked |
ue_child_clicked (string as_keys) | Une branche sœur a été choisie dans le menu d'un segment ; as_keys est l'adresse de la branche, prête à repartir dans of_add_item |
ue_children_needed (string as_keys) | Le chevron d'un segment marqué ib_has_children s'ouvre : posez ses branches maintenant (of_add_child), le menu s'ouvre au retour de l'événement, avec ce que le segment porte à cet instant. Demandé à chaque ouverture : videz et reposez quand les branches ont pu changer, ne faites rien quand ce qui est là tient toujours |
ue_path_entered (string as_path) | L'utilisateur a saisi un chemin dans la barre (ib_editable) et pressé Entrée — ou quitté le champ après l'avoir modifié ; as_path est le texte tel que tapé, les ii_edit_skip premiers segments remis devant. Cliquer un autre contrôle de l'application compte comme quitter le champ. Échap, un champ inchangé ou une autre application passée au premier plan ne rapportent rien. Le fil ne bouge pas de lui-même : vérifiez les mots, puis reconstruisez-le avec of_clear et of_add_item si vous êtes d'accord |
ue_drop_files (string as_keys, string as_files[]) | Des fichiers ont été déposés depuis l'Explorateur sur un segment (ib_allow_drop) : as_keys est l'adresse du segment sous le curseur, vide si le dépôt est tombé à côté du fil ; as_files les chemins complets |
ue_drag_enter ( ) · ue_drag_leave ( ) | Un glissement de fichiers depuis l'Explorateur est entré dans le composant, ou en est sorti sans déposer — un dépôt lève ue_drop_files seul |
ue_auto_height (long al_height) | La barre annonce la hauteur qu'il lui faut — une rangée, décidée par la police et le thème ; l'userobject est déjà redimensionné, repositionnez ce qui se trouve dessous |
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) |
Le fil ne navigue pas. Il dit où l'on est et rapporte ce qu'on lui demande ; c'est votre application qui ouvre l'écran — la même action, lancée depuis un menu ou depuis le fil, passe donc par le même code.
Propriétés d'item #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_text | string | "" | Le libellé du segment, modifiable sans reconstruire le fil (balisage riche accepté : un libellé venu des DONNÉES — un nom de dossier — passe d'abord par of_escape_markup de n_pbt_utils, sinon [b]Brouillons s'afficherait en gras sans ses crochets) |
is_image | string | "" | L'icône affichée avant le libellé (préfixes mono: et tint: acceptés) |
ib_enabled | boolean | true | Un segment désactivé est grisé et ne rapporte rien : le niveau existe dans le chemin, mais on ne peut pas y remonter (droits, fiche en cours de saisie). Son chevron n'ouvre rien non plus, et un glissement de fichiers ne l'allume pas |
ib_visible | boolean | true | Un segment caché quitte le fil, séparateur compris — utile pour un niveau technique que l'utilisateur n'a pas à voir. Il est conservé : le remontrer ne demande aucune reconstruction |
ib_has_children | boolean | false | Marqué : il y a quelque chose sous ce segment. Son chevron s'affiche sans rien derrière, et l'ouvrir lève ue_children_needed, où les branches sont lues à cet instant. Un segment dont les branches ont été posées par of_add_child n'a pas besoin du marqueur |
Propriétés d'un enfant #
Obtenue par of_child(adresse). Le menu est un popup natif : une propriété changée pendant qu'il est ouvert se voit à l'ouverture suivante.
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_text | string | "" | Le libellé de la branche dans le menu |
is_image | string | "" | L'icône affichée avant le libellé |
ib_enabled | boolean | true | Une branche grisée reste dans le menu et ne peut pas être choisie — pas de droits sur cette branche |
ib_visible | boolean | true | Une branche cachée quitte le menu sans être retirée ; la dernière cachée referme le chevron |
Exemples #
Le suivre au fil de la navigation #
// Rebuild the trail in a single redraw : freeze, clear, add, insert, redraw
uo_crumbs.of_set_redraw(/*on*/ false)
uo_crumbs.of_clear()
uo_crumbs.of_add_item(/*keys*/ "home", /*text*/ "H", /*image*/ "mono:img\packimages.dll:svg/samples/folder-open")
uo_crumbs.of_insert_item(/*keys*/ "home/region", /*text*/ "R", /*index*/ 2)
uo_crumbs.of_set_redraw(/*on*/ true)
Remonter sur un clic #
// Cut the trail after Clients, then read the path that remains
uo_crumbs.of_truncate(/*keys*/ "home/clients")
ls_path = uo_crumbs.of_path()
Un niveau interdit, un niveau caché #
// Le niveau existe, mais on ne peut pas y remonter
uo_crumbs.of_item(/*keys*/ "home/clients/orders").ib_enabled = false
// Et celui-la ne regarde pas l'utilisateur : hors du fil, separateur compris
uo_crumbs.of_item(/*keys*/ "home").ib_visible = false
// Slash separator, scrolling on overflow, at most 4 segments shown, last one not clickable
uo_crumbs.is_separator = uo_crumbs.SEPARATOR_SLASH
uo_crumbs.is_overflow_mode = uo_crumbs.OVERFLOW_SCROLL
uo_crumbs.ii_max_visible = 4
uo_crumbs.ib_last_clickable = false
// Remove one segment, then the branches offered under another
uo_crumbs.of_remove_item(/*keys*/ "home/region")
uo_crumbs.of_clear_children(/*keys*/ "home/clients")
Bonnes pratiques #
- Donnez à chaque segment la clé de l'écran qu'il ouvre : votre
ue_item_clickeddevient unchoose caseque l'on lit, et le même code sert au menu. - Appelez
of_truncatedans votre gestionnaire de clic, pas avant : c'est ce qui garantit qu'un écran n'est jamais quitté sans vos contrôles. - Laissez
ii_max_visibleà0sauf si une maquette l'impose. Un fil qui suit la largeur montre toujours le maximum de ce qui tient. - Nommez les segments avec des mots que l'utilisateur reconnaît — le nom du client, pas son identifiant. Le fil est lu, pas décodé.
- N'y mettez que des niveaux où l'on peut réellement revenir. Un segment qui échoue une fois sur deux fait perdre confiance dans tout le fil ; s'il est temporairement interdit,
ib_enabledle dit sans mentir. - Un fil d'Ariane dit un lieu, pas une progression : pour « étape 2 sur 5 », c'est la stepbar qu'il faut.
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.