# ribbon — `u_pbt_ribbon` #

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

> Ruban façon Office : onglets, groupes, douze types de contrôles riches, menu applicatif, barre d'accès rapide, onglets contextuels à bandeau et keytips.

> ▶ Le voir en vrai — Application de démonstration, tuile Ribbon : l'aperçu, le code qui le produit et cette page, côte à côte.

## En bref #

Userobject | `u_pbt_ribbon`
Classes d'items | `n_pbt_ribbon_tab` (onglet), `n_pbt_ribbon_group` (groupe), `n_pbt_ribbon_item` (contrôle), `n_pbt_ribbon_menu_item` (entrée de menu), `n_pbt_ribbon_ctx_group` (groupe d'onglets contextuels)
Sert à | Remplacer une barre de menus et ses barres d'outils par une interface de commande moderne, lisible et hiérarchisée
Hauteur | Intrinsèque : le ruban se cale toujours sur son contenu, rien à activer — voir Hauteur automatique
Limite en mode démo | 2 onglets au maximum — voir le mode démo

### La règle d'or : tout passe par le chemin #

Le ruban est une hiérarchie à quatre niveaux : onglet → groupe → contrôle → entrée de menu. Vous n'avez aucun identifiant global à gérer : chaque objet s'atteint par le chemin qui y mène, et chaque ajout se fait sur le handle du parent.

    // Lire ou piloter un controle : le chemin complet, toujours
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller").ib_enabled = false

Deux conséquences pratiques et confortables : deux groupes différents peuvent utiliser le même identifiant de contrôle sans se marcher dessus, et les événements vous livrent le chemin complet — vous savez toujours d'où vient le clic.

## Démarrage rapide #

    // event open de la fenetre
    n_pbt_ribbon_tab   lnv_onglet
    n_pbt_ribbon_group lnv_groupe

    lnv_onglet = uo_ruban.of_add_tab("accueil", "Accueil")

    lnv_groupe = lnv_onglet.of_add_group("presse_papier", "Presse-papiers")
    lnv_groupe.of_add_big_button("coller", "Coller", "mono:img\paste.svg")
    lnv_groupe.of_add_button("couper", "Couper", "mono:img\cut.svg")
    lnv_groupe.of_add_button("copier", "Copier", "mono:img\copy.svg")

    uo_ruban.of_select_tab("accueil")

    // event ue_clicked de uo_ruban : (string as_tab, string as_group, string as_id)
    choose case as_id
        case "coller" ; of_coller()
        case "couper" ; of_couper()
        case "copier" ; of_copier()
    end choose

## Propriétés #

Propriété | Type | Défaut | Rôle
--- | --- | --- | ---
`is_app_button` | string | `""` | Libellé du bouton applicatif, en haut à gauche, qui ouvre le menu applicatif. Vide = libellé `File`
`ib_minimized` | boolean | `false` | `true` replie le ruban sur ses seuls en-têtes d'onglets ; un clic sur un onglet le déroule temporairement (déclenche `ue_minimized`)
`ib_veto_gallery` | boolean | `true` | Demander avant qu'une tuile de galerie ne soit retenue (déclenche `ue_gallery_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
`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

Constante — `ACCENT_LIGHT` (`-1`) : à passer comme couleur d'un onglet ou d'un groupe contextuel pour qu'il suive l'accent du thème, éclairci, plutôt qu'une couleur figée.

### Propriétés d'un onglet — `n_pbt_ribbon_tab` #

Obtenues par `of_tab(id)`, elles se modifient à chaud.

Propriété | Type | Défaut | Rôle
--- | --- | --- | ---
`ib_visible` | boolean | `true` | `false` masque l'onglet sans le supprimer — le mécanisme même des onglets contextuels
`is_keytip` | string | `""` | Lettre d'accès rapide affichée après appui sur Alt (`"A"` pour Accueil)

### Propriétés d'un groupe — `n_pbt_ribbon_group` #

Obtenues par `of_tab(id).of_group(id)`.

Propriété | Type | Défaut | Rôle
--- | --- | --- | ---
`ib_visible` | boolean | `true` | `false` masque le groupe et tous ses contrôles
`ib_launcher` | boolean | `false` | Affiche la petite flèche en bas à droite du groupe — le lanceur de boîte de dialogue (déclenche `ue_launcher`). La flèche vit dans la barre de titre du groupe, et un groupe que le ruban a dû replier faute de place la garde au même endroit — elle voyage en plus dans le panneau qu'ouvre le groupe replié

Constantes de mode du sélecteur de couleur : `COLORMODE_PALETTE` (nuancier de pastilles, mode par défaut) et `COLORMODE_OPEN` (palette complète avec validation).

### Propriétés d'un contrôle — `n_pbt_ribbon_item` #

Obtenues par `of_tab(id).of_group(id).of_item(id)`. Elles s'appliquent à tous les types de contrôles ; les propriétés hors sujet pour un type donné sont simplement ignorées.

Propriété | Type | Défaut | Rôle
--- | --- | --- | ---
`is_label` | string | `""` | Libellé du contrôle. Accepte le balisage riche
`ib_enabled` | boolean | `true` | `false` grise le contrôle et bloque son activation
`ib_checked` | boolean | `false` | État enfoncé d'une bascule ou coché d'une case
`ib_visible` | boolean | `true` | `false` masque le contrôle ; les voisins se resserrent
`is_text` | string | `""` | Texte saisi ou sélectionné dans une zone de liste modifiable
`id_value` | double | `0` | Valeur numérique d'un compteur
`il_color` | long | `-1` | Couleur courante d'un sélecteur de couleur
`ii_visible_items` | integer | `3` | Galerie uniquement : nombre de tuiles que la bande repliée montre d'un coup. Les autres restent atteignables par les flèches, ou dans la grille dépliée
`is_keytip` | string | `""` | Lettre d'accès rapide du contrôle, affichée après appui sur Alt
`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

### Propriétés d'une entrée de menu — `n_pbt_ribbon_menu_item` #

Obtenues par `of_tab(id).of_group(id).of_item(id).of_menu_item(id)`.

Propriété | Type | Défaut | Rôle
--- | --- | --- | ---
`ib_enabled` | boolean | `true` | `false` grise l'entrée
`ib_checked` | boolean | `false` | Coche d'une entrée créée par `of_add_menu_check`

## Les douze types de contrôles #

Tous s'ajoutent sur le handle d'un groupe et renvoient le handle du contrôle créé — vous pouvez donc enchaîner l'alimentation d'un menu ou d'une liste dans la foulée.

Méthode du groupe | Contrôle obtenu | Événement
--- | --- | ---
`of_add_big_button (id, label, image)` | Gros bouton pleine hauteur, icône au-dessus du libellé | `ue_clicked`
`of_add_big_split (id, label, image)` | Gros bouton scindé : la partie haute agit, la flèche ouvre le menu | `ue_clicked` · `ue_menu_selected`
`of_add_big_dropdown (id, label, image)` | Gros bouton à menu déroulant | `ue_menu_selected`
`of_add_button (id, label, image)` | Petit bouton (empilé par colonnes de trois) | `ue_clicked`
`of_add_toggle (id, label, image)` | Petite bascule qui reste enfoncée | `ue_toggled`
`of_add_dropdown (id, label, image)` | Petit bouton à menu déroulant | `ue_menu_selected`
`of_add_checkbox (id, label)` | Case à cocher | `ue_toggled`
`of_add_separator ( )` | Séparateur vertical entre deux blocs de contrôles | —
`of_add_combo (id, largeur_px, modifiable)` | Zone de liste, éditable ou non | `ue_combo_changed`
`of_add_spinner (id, largeur_px, mini, maxi, pas, valeur)` | Compteur numérique à flèches | `ue_value_changed`
`of_add_colorpicker (id, label, image, couleur)` | Bouton de couleur scindé : le clic réapplique, la flèche ouvre le nuancier | `ue_clicked` · `ue_color_changed`
`of_add_gallery (id, largeur_px, largeur_tuile, hauteur_tuile)` | Bande de tuiles illustrées, défilante | `ue_gallery_selection_changed`

`of_add_colorpicker` accepte un cinquième argument `as_mode` : `COLORMODE_PALETTE` (nuancier de pastilles) ou `COLORMODE_OPEN` (palette complète avec boutons Valider et Annuler).

## Méthodes #

### Construire le ruban #

Méthode | Rôle
--- | ---
`of_add_tab (string as_id, string as_title)` | Ajoute un onglet et renvoie son handle : enchaînez les groupes dessus
`of_insert_tab (string as_id, string as_title, integer ai_index)` | Ajoute un onglet à la position que vous choisissez (`0` = en tête) au lieu de la fin, et renvoie son handle comme `of_add_tab`. Un id déjà pris est refusé
`of_tab (string as_id)` | Handle d'un onglet existant (créé au premier accès)
`of_add_group (string as_id, string as_title)` | Sur un handle d'onglet : ajoute un groupe titré et renvoie son handle
`of_group (string as_id)` | Sur un handle d'onglet : handle d'un groupe existant
`of_item (string as_id)` | Sur un handle de groupe : handle d'un contrôle existant
`of_select_tab (string as_id)` | Active un onglet — strictement équivalent à un clic utilisateur (déclenche `ue_selection_changed`)
`of_selected_key ( )` | Identifiant de l'onglet actif, `""` si aucun. Tenu à jour par `ue_selection_changed`, donc juste dès le démarrage
`of_remove_group (string as_id)` | Sur un handle d'onglet : retire un groupe et tous ses contrôles
`of_remove_item (string as_id)` | Sur un handle de groupe : retire un contrôle
`of_remove_tab (string as_id)` | Retire un onglet et tout son contenu
`of_clear ( )` | Vide entièrement le ruban : onglets, groupes, contrôles, barre d'accès rapide, menu applicatif

### Alimenter les menus et les listes #

Toutes ces méthodes s'appellent sur le handle d'un contrôle.

Méthode | Rôle
--- | ---
`of_add_menu_item (string as_id, string as_label, string as_image)` | Entrée racine du menu d'un bouton déroulant ou scindé
`of_add_menu_item (string as_parent, string as_id, string as_label, string as_image)` | Entrée en cascade : `as_parent` désigne une entrée existante de ce menu
`of_add_menu_check (string as_id, string as_label)` · `(id, label, image)` | Entrée cochable : le clic bascule son état et le rapporte dans `ue_menu_selected`
`of_add_menu_header (string as_label)` | Ligne de titre non cliquable, pour découper un long menu
`of_add_menu_separator ( )` | Ligne de séparation dans le menu
`of_menu_item (string as_id)` | Handle d'une entrée de menu, pour la griser ou la cocher à chaud
`of_add_combo_item (string as_label)` | Ajoute un choix à la liste d'une zone de liste
`of_add_gallery_item (string as_id, string as_image, string as_label)` | Ajoute une tuile à une galerie
`of_select_item (string as_id)` | Sélectionne une tuile de galerie par programme (sans lever d'événement)
`of_open ( )` | Ouvre par programme le menu, la liste ou le nuancier du contrôle

### Menu applicatif et barre d'accès rapide #

Méthode | Rôle
--- | ---
`of_add_app_menu_item (string as_id, string as_label, string as_image)` | Entrée racine du menu applicatif (celui qu'ouvre le bouton `is_app_button`)
`of_add_app_menu_item (string as_parent, string as_id, string as_label, string as_image)` | Entrée en cascade du menu applicatif
`of_add_app_menu_separator (string as_id)` | Ligne de séparation dans le menu applicatif
`of_add_qat (string as_id, string as_image, string as_tooltip)` | Bouton de la barre d'accès rapide, au-dessus des onglets, et renvoie son handle
`of_qat_item (string as_id)` | Handle d'un bouton d'accès rapide, pour le griser ou le masquer à chaud

### Onglets contextuels #

Méthode | Rôle
--- | ---
`of_add_contextual_tab (string as_id, string as_title, long al_color)` | Onglet contextuel isolé : créé masqué, marqué d'un liseré coloré. Passez `ACCENT_LIGHT` pour suivre l'accent du thème
`of_add_contextual_group (string as_id, string as_title)` · `(id, title, al_color)` | Groupe d'onglets contextuels : un bandeau titré coloré coiffe ses onglets. Renvoie son handle
`of_ctx_group (string as_id)` | Retrouve le handle d'un groupe contextuel déjà créé — utile quand vous n'avez pas conservé celui renvoyé à la création
`of_add_tab (string as_id, string as_title)` | Sur un handle de groupe contextuel : ajoute un onglet coiffé par le bandeau, créé masqué
`of_tab (string as_id)` | Sur un handle de groupe contextuel : handle d'un de ses onglets
`il_color` (propriété) | Sur un handle de groupe contextuel : recolore le bandeau à chaud (`ACCENT_LIGHT` pour revenir à l'accent)

### Communes #

Méthode | Rôle
--- | ---
`of_reset ( )` | Vide le ruban et le ramène à son état neuf, propriétés comprises
`of_set_redraw (boolean)` | Regroupe une rafale de modifications en un seul rendu
`of_preload_icons (string as_icons[])` | Préchauffe un lot d'icônes au démarrage : un onglet ouvert plus tard affiche les siennes instantanément
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exporte le rendu en image

## Événements #

Tous les événements de contrôle portent le chemin complet : vous n'avez jamais besoin d'un identifiant unique dans toute l'application.

Événement | Déclenché quand
--- | ---
`ue_clicked (string as_tab, string as_group, string as_id)` | Un bouton, un gros bouton, la partie principale d'un bouton scindé ou d'un sélecteur de couleur est cliqué
`ue_toggled (string as_tab, string as_group, string as_id, boolean ab_checked)` | Une bascule ou une case à cocher change d'état ; `ab_checked` porte le nouvel état
`ue_menu_selected (string as_tab, string as_group, string as_dropdown, string as_id, boolean ab_checked)` | Une entrée de menu déroulant est choisie. `as_dropdown` = le contrôle porteur, `as_id` = l'entrée, `ab_checked` = l'état d'une entrée cochable
`ue_combo_changed (string as_tab, string as_group, string as_id, string as_text)` | Une zone de liste change de valeur, par sélection ou par saisie
`ue_value_changed (string as_tab, string as_group, string as_id, double ad_value)` | Un compteur numérique change de valeur
`ue_color_changed (string as_tab, string as_group, string as_id, long al_color)` | Une couleur est choisie dans un sélecteur de couleur
`ue_gallery_selection_changed (string as_tab, string as_group, string as_id, string as_from_item, string as_item)` | Une tuile de galerie a été retenue. Mêmes arguments que `ue_gallery_selection_changing` : la question et son issue se lisent pareil, et `as_from_item` est la tuile quittée
`ue_gallery_selection_changing (string as_tab, string as_group, string as_id, string as_from_item, string as_item)` → boolean | Annulable, posé avant que la tuile ne soit retenue. Levé par défaut ; `ib_veto_gallery = false` le supprime. `as_from_item` est la tuile courante. Renvoyez `false` pour la conserver (un style que le document ne peut pas encore prendre)
`ue_launcher (string as_tab, string as_group)` | La flèche de lanceur d'un groupe est cliquée — ouvrez votre fenêtre d'options
`ue_selection_changed (string as_id)` | Un onglet devient actif, par clic ou par `of_select_tab`
`ue_app_button ( )` | Le bouton applicatif est cliqué
`ue_app_menu_selected (string as_id)` | Une entrée du menu applicatif est choisie
`ue_minimized (boolean ab_minimized)` | Le ruban est replié ou déplié par l'utilisateur
`ue_size_changed (long al_height, boolean ab_minimized)` | La hauteur du ruban a changé d'elle-même : repli, dépli, onglet contextuel affiché, fenêtre plus étroite qui perd une rangée. Contrairement à `ue_auto_height` — qui ne parle que si le composant se redimensionne lui-même — celui-ci se déclenche que la hauteur automatique soit active ou non : c'est de l'information pure, pour replacer ce qui se trouve dessous
`ue_keytips (boolean ab_on, integer ai_level)` | Les keytips apparaissent (`true`) ou disparaissent (`false`). `ai_level` dit où en est la navigation : `1` = les onglets sont lettrés, `2` = les commandes de l'onglet courant le sont, `0` = plus aucun keytip
`ue_auto_height (long al_height)` | Le ruban annonce sa hauteur idéale et vient de s'y ajuster — toujours actif : la hauteur d'un ruban est intrinsèque
`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 #

### Un ruban complet, du menu applicatif aux groupes #

    // event open : on regroupe toute la construction en un seul rendu
    n_pbt_ribbon_tab   lnv_onglet
    n_pbt_ribbon_group lnv_groupe
    n_pbt_ribbon_item  lnv_item

    uo_ruban.of_set_redraw(false)
    uo_ruban.is_app_button = "Fichier"

    // Menu applicatif, avec une cascade sous "Enregistrer sous"
    uo_ruban.of_add_app_menu_item(/*id*/ "nouveau", /*libelle*/ "Nouveau", /*image*/ "mono:img\new.svg")
    uo_ruban.of_add_app_menu_item("ouvrir", "Ouvrir...", "mono:img\open.svg")
    uo_ruban.of_add_app_menu_item("enr_sous", "Enregistrer sous", "mono:img\saveas.svg")
    uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*id*/ "sous_pdf", "Document PDF", "")
    uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*id*/ "sous_csv", "Fichier CSV", "")
    uo_ruban.of_add_app_menu_separator("sep1")
    uo_ruban.of_add_app_menu_item("quitter", "Quitter", "mono:img\exit.svg")

    // Barre d'acces rapide, au-dessus des onglets
    uo_ruban.of_add_qat(/*id*/ "qat_enr", /*image*/ "mono:img\save.svg", /*infobulle*/ "Enregistrer")
    uo_ruban.of_add_qat("qat_annuler", "mono:img\undo.svg", "Annuler")

    // Onglet Accueil
    lnv_onglet = uo_ruban.of_add_tab("accueil", "Accueil")
    lnv_onglet.is_keytip = "A"

    lnv_groupe = lnv_onglet.of_add_group("presse_papier", "Presse-papiers")
    lnv_item = lnv_groupe.of_add_big_split("coller", "Coller", "mono:img\paste.svg")
    lnv_item.of_add_menu_item("coller_texte", "Coller sans mise en forme", "")
    lnv_item.of_add_menu_item("coller_lien", "Coller comme lien", "")
    lnv_groupe.of_add_button("couper", "Couper", "mono:img\cut.svg")
    lnv_groupe.of_add_button("copier", "Copier", "mono:img\copy.svg")
    lnv_groupe.ib_launcher = true       // fleche d'options en bas a droite

    uo_ruban.of_set_redraw(true)
    uo_ruban.of_select_tab("accueil")

### Un aiguillage de clics unique #

    // event ue_clicked de uo_ruban : (string as_tab, string as_group, string as_id)
    // Le chemin complet arrive avec l'evenement : un seul aiguillage suffit,
    // et deux groupes peuvent reutiliser le meme identifiant sans se gener.
    choose case as_group + "/" + as_id
        case "presse_papier/couper" ; of_couper()
        case "presse_papier/copier" ; of_copier()
        case "presse_papier/coller" ; of_coller()
        case "police/gras"          ; of_basculer_gras()
    end choose

### Piloter l'état des contrôles selon les droits #

    // Toujours par le chemin : onglet > groupe > controle
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller").ib_enabled = of_presse_papier_non_vide()
    uo_ruban.of_tab("accueil").of_group("outils").of_item("pinceau").ib_checked = true
    uo_ruban.of_tab("admin").ib_visible = gb_administrateur

    // Griser une entree DANS un menu deroulant (niveau 4)
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller") &
            .of_menu_item("coller_lien").ib_enabled = false

### Onglets contextuels à bandeau #

Le principe d'Office : des onglets qui n'apparaissent que lorsque la sélection les justifie, coiffés d'un bandeau titré coloré.

    // event open : on prepare le groupe contextuel, masque par defaut
    n_pbt_ribbon_ctx_group lnv_ctx
    n_pbt_ribbon_tab       lnv_onglet
    n_pbt_ribbon_group     lnv_groupe

    // Sans couleur, le bandeau suit l'accent du theme ; RGB(...) pour l'imposer
    lnv_ctx = uo_ruban.of_add_contextual_group(/*id*/ "img", /*titre*/ "Outils Image", &
                                               /*couleur*/ RGB(224, 32, 96))
    lnv_onglet = lnv_ctx.of_add_tab("format", "Format")
    lnv_groupe = lnv_onglet.of_add_group("ajuster", "Ajuster")
    lnv_groupe.of_add_big_button("rogner", "Rogner", "mono:img\crop.svg")
    lnv_groupe.of_add_button("pivoter", "Pivoter", "mono:img\rotate.svg")

    // A la selection d'une image : on revele l'onglet et on l'active
    uo_ruban.of_tab("format").ib_visible = true
    uo_ruban.of_select_tab("format")

    // A la deselection : on le masque, le bandeau disparait avec lui
    uo_ruban.of_tab("format").ib_visible = false

### Zone de liste, compteur, sélecteur de couleur et galerie #

    n_pbt_ribbon_group lnv_groupe
    n_pbt_ribbon_item  lnv_item

    lnv_groupe = uo_ruban.of_tab("accueil").of_add_group("police", "Police")

    // Zone de liste editable : on l'alimente par son handle
    lnv_item = lnv_groupe.of_add_combo(/*id*/ "nom_police", /*largeur_px*/ 140, /*modifiable*/ true)
    lnv_item.of_add_combo_item("Segoe UI")
    lnv_item.of_add_combo_item("Arial")
    lnv_item.of_add_combo_item("Calibri")
    lnv_item.is_text = "Segoe UI"

    // Compteur numerique : mini, maxi, pas, valeur initiale
    lnv_groupe.of_add_spinner(/*id*/ "taille", /*largeur_px*/ 70, /*mini*/ 6, /*maxi*/ 96, &
                              /*pas*/ 1, /*valeur*/ 11)

    // Selecteur de couleur en mode palette complete (avec Valider / Annuler)
    lnv_groupe.of_add_colorpicker(/*id*/ "couleur", /*libelle*/ "Couleur", &
                                  /*image*/ "mono:img\font-color.svg", &
                                  /*couleur*/ RGB(0, 0, 0), &
                                  /*mode*/ lnv_groupe.COLORMODE_OPEN)

    // Galerie de styles : tuiles illustrees defilantes
    lnv_item = lnv_groupe.of_add_gallery(/*id*/ "styles", /*largeur_px*/ 220, &
                                         /*largeur_tuile*/ 64, /*hauteur_tuile*/ 48)
    lnv_item.of_add_gallery_item("st_normal", "img\style-normal.png", "Normal")
    lnv_item.of_add_gallery_item("st_titre",  "img\style-titre.png",  "Titre")
    lnv_item.of_add_gallery_item("st_note",   "img\style-note.png",   "Note")
    lnv_item.of_add_gallery_item("st_code",   "img\style-code.png",   "Code")

    // La bande repliee montre 4 vignettes a la fois ; les autres restent
    // atteignables par les fleches, ou dans la grille deplie.
    lnv_item.ii_visible_items = 4

    lnv_item.of_select_item("st_normal")

    // event ue_value_changed de uo_ruban : (string as_tab, string as_group, string as_id, double ad_value)
    if as_id = "taille" then of_appliquer_taille(ad_value)

    // event ue_color_changed de uo_ruban : (string as_tab, string as_group, string as_id, long al_color)
    if as_id = "couleur" then of_appliquer_couleur(al_color)

### Refuser le choix d'une vignette de galerie #

    // La question est posee par DEFAUT : rien a activer. Cette ligne fait l'inverse,
    // elle la supprime quand l'arbitrage ne sert pas.
    uo_ruban.ib_veto_gallery = false

    // event ue_gallery_selection_changing de uo_ruban :
    //   (string as_tab, string as_group, string as_id, string as_from_item, string as_item)
    // Renvoyer FALSE conserve la vignette courante (as_from_item).
    if as_item = "st_code" and not of_document_supporte_code() then
        MessageBox("Style", "Ce document ne peut pas prendre le style Code.")
        return false
    end if
    return true

### Le lanceur de boîte de dialogue #

    // La petite fleche en bas a droite du groupe
    uo_ruban.of_tab("accueil").of_group("police").ib_launcher = true

    // event ue_launcher de uo_ruban : (string as_tab, string as_group)
    // Le chemin identifie le groupe : on ouvre la fenetre d'options correspondante.
    choose case as_group
        case "police"        ; open(w_options_police)
        case "presse_papier" ; open(w_options_collage)
    end choose

### Keytips : conduire le ruban au clavier #

    // Alt affiche les lettres ; Alt puis A puis C declenche "copier"
    uo_ruban.of_tab("accueil").is_keytip = "A"
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("copier").is_keytip = "C"
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("couper").is_keytip = "X"

Un appui sur Alt où que soit le focus dans la fenêtre donne la main au ruban : il prend le focus clavier et lève ses lettres. Vous n'avez rien à câbler — il suffit qu'au moins un keytip soit déclaré. Échap, un second Alt ou le choix d'une commande rendent le focus au contrôle que l'utilisateur avait quitté.

`ue_keytips` vous prévient à chaque changement d'état, et vous donne le niveau courant :

    // event ue_keytips de uo_ruban : (boolean ab_on, integer ai_level)
    // Le clavier pilote le ruban : effacer l'aide de la barre d'etat, qui parle
    // de la souris, et la remettre quand les lettres retombent.
    if ab_on then
        uo_statut.of_item("main").is_text = "Tapez une lettre (niveau " + String(ai_level) + ")"
    else
        uo_statut.of_item("main").is_text = ""
    end if

### Info-bulles enrichies sur un contrôle #

    n_pbt_ribbon_item lnv_item

    lnv_item = uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller")
    lnv_item.is_super_tooltip_title = "Coller (Ctrl+V)"
    lnv_item.is_super_tooltip_text  = "Insere le contenu du presse-papiers." &
                                    + "[br][br][size-=15]Utilisez la fleche pour coller sans mise en forme.[/size-=15]"
    lnv_item.is_super_tooltip_image = "img\paste.png"

Ces quatre propriétés sont exactement les mêmes que sur tout autre item de la bibliothèque. Pour une info-bulle d'une seule ligne, `is_tooltip` suffit.

### Hauteur automatique #

Le ruban se dimensionne seul : il n'y a rien à activer. Il vous prévient à chaque changement de hauteur (repli, onglet contextuel, changement de thème) pour que vous replaciez ce qui est en dessous.

    // event ue_auto_height de uo_ruban : (long al_height)
    // Le ruban s'est deja redimensionne : on replace ce qui est en dessous.
    uo_contenu.y      = uo_ruban.y + uo_ruban.height
    uo_contenu.height = this.height - uo_contenu.y

### Replier le ruban pour gagner de la place #

    uo_ruban.ib_minimized = true

    // event ue_minimized de uo_ruban : (boolean ab_minimized)
    // On memorise la preference de l'utilisateur pour la prochaine ouverture.
    of_enregistrer_preference("ruban_replie", ab_minimized)

### Repartir d'un ruban vide #

    // of_reset vide onglets, groupes, controles, barre d'acces rapide et menu
    uo_ruban.of_reset()
    uo_ruban.of_add_tab("accueil", "Accueil")

## Depuis un menu PowerBuilder existant #

Une application PowerBuilder a déjà décrit ses commandes une fois : dans son menu. Libellés, raccourcis, images, séparateurs, sous-menus, info-bulles — tout y est. `n_pbt_menu2ribbon` relit ce menu par RTTI et écrit le PowerScript qui construit le ruban correspondant.

    // Une seule fois, a la main : le generateur ECRIT du code, il ne s'execute pas
    // en production. Collez son resultat dans l'open de votre fenetre.
    n_pbt_menu2ribbon lnv_gen
    string ls_code

    lnv_gen = create n_pbt_menu2ribbon
    ls_code = lnv_gen.of_generate(/*menu*/ m_principal, /*variable*/ "uo_ruban")
    destroy lnv_gen

    ClipBoard(ls_code)

La conversion est déterministe : aucune IA, aucun appel réseau, rien qui sorte du poste. Et les identifiants générés gardent le chemin du menu (`m_principal.m_fichier.m_ouvrir`), si bien que le `choose case` de vos actions existantes fonctionne tel quel depuis `ue_clicked`.

Le code produit est un point de départ à relire, pas un livrable : un menu est une liste, un ruban est une mise en page. Regroupez, choisissez vos gros boutons, supprimez ce qui n'a pas sa place en permanence. L'exemple 9 de la page ruban de l'application de démonstration montre un résultat complet.

## Bonnes pratiques #

- Encadrez toute la construction par `of_set_redraw(false)` / `of_set_redraw(true)` : un ruban complet se dessine alors en une seule fois, sans scintillement.
- Conservez les handles renvoyés (`n_pbt_ribbon_tab`, `n_pbt_ribbon_group`, `n_pbt_ribbon_item`) dans des variables locales le temps de la construction : le code reste court et lisible. Pour piloter un contrôle plus tard, repassez simplement par le chemin.
- Appelez `of_preload_icons` au démarrage : sans cela, le premier affichage d'un onglet jamais ouvert montre un court délai avant ses icônes.
- Un identifiant n'a besoin d'être unique que dans son groupe. Profitez-en pour nommer vos contrôles simplement (`copier`, `coller`) plutôt qu'avec des préfixes.
- Réservez les onglets contextuels aux commandes qui n'ont aucun sens hors contexte : un onglet permanent grisé est plus reposant qu'un onglet qui apparaît et disparaît.
- La question est posée par défaut : un `ue_gallery_selection_changing` laissé vide autorise toujours le choix, vous n'avez rien à faire. Coupez-la avec `ib_veto_gallery = false` si l'arbitrage ne vous sert pas, car chaque question coûte un aller-retour vers PowerBuilder.
- Un seul lanceur de boîte de dialogue par groupe, et seulement si le groupe a réellement des options avancées à offrir.
- Pour reconstruire un ruban entier, préférez `of_clear()` (ou `of_reset()`) à une série de `of_remove_tab` : sans cela, réutiliser un identifiant d'onglet échoue.
- Pour une barre de commandes plus légère, sans onglets ni groupes, voyez toolbar ; pour une navigation latérale, listbar.

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