ribbon — u_pbt_ribbon #
← Component reference · Guide contents
Office-style ribbon: tabs, groups, twelve types of rich controls, application menu, quick access toolbar, banner-headed contextual tabs and keytips.
▶ See it live — Demo application, Ribbon tile: the preview, the code behind it and this page, side by side.
At a glance #
| Userobject | u_pbt_ribbon |
| Item classes | n_pbt_ribbon_tab (tab), n_pbt_ribbon_group (group), n_pbt_ribbon_item (control), n_pbt_ribbon_menu_item (menu entry), n_pbt_ribbon_ctx_group (contextual tab group) |
| Used for | Replacing a menu bar and its toolbars with a modern command interface that is readable and clearly structured |
| Height | Intrinsic: the ribbon always fits itself to its content, nothing to enable — see Automatic height |
| Demo mode limit | 2 tabs maximum — see demo mode |
The golden rule: everything goes through the path #
The ribbon is a four-level hierarchy: tab → group → control → menu entry. There are no global identifiers for you to manage: every object is reached through the path that leads to it, and every addition is made on the parent handle.
// Read or drive a control : the full path, always
uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller").ib_enabled = false
Two practical, comfortable consequences: two different groups can use the same control identifier without clashing, and events hand you the full path — you always know where the click came from.
Quick start #
// open event of the window
n_pbt_ribbon_tab lnv_onglet
n_pbt_ribbon_group lnv_groupe
lnv_onglet = uo_ruban.of_add_tab("accueil", "Home")
lnv_groupe = lnv_onglet.of_add_group("presse_papier", "Clipboard")
lnv_groupe.of_add_big_button("coller", "Paste", "mono:img\paste.svg")
lnv_groupe.of_add_button("couper", "Cut", "mono:img\cut.svg")
lnv_groupe.of_add_button("copier", "Copy", "mono:img\copy.svg")
uo_ruban.of_select_tab("accueil")
// ue_clicked event of 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
Properties #
| Property | Type | Default | Purpose |
|---|---|---|---|
is_app_button | string | "" | Label of the application button, at the top left, which opens the application menu. Empty = the label File |
ib_minimized | boolean | false | true collapses the ribbon down to its tab headers alone; clicking a tab unfolds it temporarily (raises ue_minimized) |
ib_veto_gallery | boolean | true | Ask before a gallery tile is picked (raises ue_gallery_selection_changing, which can refuse). On by default: scripting nothing always lets the pick happen. Set it to false to drop the round trip to PowerBuilder (~35 ms) where it would show |
is_theme_style | string | fluent | Visual style of the component (THEME_STYLE_* constants) |
is_theme_mode | string | light | Light or dark variant (THEME_MODE_* constants) |
il_theme_accent | long | -1 | Accent color of this component (-1 = the theme accent) |
is_tooltip | string | "" | Simple tooltip shown when hovering the component |
is_super_tooltip_title | string | "" | Title of the rich tooltip (takes precedence over is_tooltip) |
is_super_tooltip_text | string | "" | Text of the rich tooltip (rich markup accepted) |
is_super_tooltip_image | string | "" | Image of the rich tooltip |
Constant — ACCENT_LIGHT (-1): pass it as the color of a contextual tab or group so that it follows the theme accent, lightened, instead of a fixed color.
Properties of a tab — n_pbt_ribbon_tab #
Obtained through of_tab(id), they can be changed on the fly.
| Property | Type | Default | Purpose |
|---|---|---|---|
ib_visible | boolean | true | false hides the tab without removing it — the very mechanism behind contextual tabs |
is_keytip | string | "" | Access letter displayed after pressing Alt ("H" for Home) |
Properties of a group — n_pbt_ribbon_group #
Obtained through of_tab(id).of_group(id).
| Property | Type | Default | Purpose |
|---|---|---|---|
ib_visible | boolean | true | false hides the group and all its controls |
ib_launcher | boolean | false | Displays the small arrow at the bottom right of the group — the dialog launcher (raises ue_launcher). The arrow lives in the group title bar, and a group the ribbon had to fold for lack of room keeps it in the very same place — it also travels into the panel the folded group opens. |
Color picker mode constants: COLORMODE_PALETTE (swatch palette, the default mode) and COLORMODE_OPEN (full palette with confirmation).
Properties of a control — n_pbt_ribbon_item #
Obtained through of_tab(id).of_group(id).of_item(id). They apply to every type of control; the properties that make no sense for a given type are simply ignored.
| Property | Type | Default | Purpose |
|---|---|---|---|
is_label | string | "" | Label of the control. Accepts rich text markup |
ib_enabled | boolean | true | false grays out the control and blocks its activation |
ib_checked | boolean | false | Pressed state of a toggle, or checked state of a check box |
ib_visible | boolean | true | false hides the control; its neighbors close the gap |
is_text | string | "" | Text typed or selected in a drop-down |
id_value | double | 0 | Numeric value of a spinner |
il_color | long | -1 | Current color of a color picker |
ii_visible_items | integer | 3 | Gallery only: number of tiles the collapsed strip shows at once. The others stay reachable through the arrows, or in the expanded grid |
is_keytip | string | "" | Access letter of the control, displayed after pressing Alt |
is_tooltip | string | "" | Simple tooltip shown when hovering the item |
is_super_tooltip_title | string | "" | Title of the item rich tooltip (takes precedence over is_tooltip) |
is_super_tooltip_text | string | "" | Text of the item rich tooltip (rich markup accepted) |
is_super_tooltip_image | string | "" | Image of the item rich tooltip |
Properties of a menu entry — n_pbt_ribbon_menu_item #
Obtained through of_tab(id).of_group(id).of_item(id).of_menu_item(id).
| Property | Type | Default | Purpose |
|---|---|---|---|
ib_enabled | boolean | true | false grays out the entry |
ib_checked | boolean | false | Check mark of an entry created by of_add_menu_check |
The twelve types of controls #
They are all added on a group handle and return the handle of the control they create — so you can go straight on to filling a menu or a list.
| Group method | Control obtained | Event |
|---|---|---|
of_add_big_button (id, label, image) | Full-height big button, icon above the label | ue_clicked |
of_add_big_split (id, label, image) | Big split button: the upper part acts, the arrow opens the menu | ue_clicked · ue_menu_selected |
of_add_big_dropdown (id, label, image) | Big button with a drop-down menu | ue_menu_selected |
of_add_button (id, label, image) | Small button (stacked in columns of three) | ue_clicked |
of_add_toggle (id, label, image) | Small toggle that stays pressed | ue_toggled |
of_add_dropdown (id, label, image) | Small button with a drop-down menu | ue_menu_selected |
of_add_checkbox (id, label) | Check box | ue_toggled |
of_add_separator ( ) | Vertical separator between two blocks of controls | — |
of_add_combo (id, largeur_px, modifiable) | Drop-down, editable or not | ue_combo_changed |
of_add_spinner (id, largeur_px, mini, maxi, pas, valeur) | Numeric spinner with arrows | ue_value_changed |
of_add_colorpicker (id, label, image, couleur) | Split color button: clicking reapplies, the arrow opens the swatch palette | ue_clicked · ue_color_changed |
of_add_gallery (id, width_px, tile_width, tile_height) | Scrolling strip of illustrated tiles | ue_gallery_selection_changed |
of_add_colorpicker accepts a fifth argument as_mode: COLORMODE_PALETTE (swatch palette) or COLORMODE_OPEN (full palette with OK and Cancel buttons).
Methods #
Building the ribbon #
| Method | Purpose |
|---|---|
of_add_tab (string as_id, string as_title) | Adds a tab and returns its handle: chain the groups onto it |
of_insert_tab (string as_id, string as_title, integer ai_index) | Adds a tab at the position you choose (0 = first) instead of at the end, and returns its handle like of_add_tab. An id already taken is refused |
of_tab (string as_id) | Handle of an existing tab (created on first access) |
of_add_group (string as_id, string as_title) | On a tab handle: adds a titled group and returns its handle |
of_group (string as_id) | On a tab handle: handle of an existing group |
of_item (string as_id) | On a group handle: handle of an existing control |
of_select_tab (string as_id) | Activates a tab — strictly equivalent to a user click (raises ue_selection_changed) |
of_selected_key ( ) | Identifier of the active tab, "" if none. Kept up to date by ue_selection_changed, so it is right from start-up |
of_remove_group (string as_id) | On a tab handle: removes a group and all its controls |
of_remove_item (string as_id) | On a group handle: removes a control |
of_remove_tab (string as_id) | Removes a tab and all its content |
of_clear ( ) | Empties the ribbon completely: tabs, groups, controls, quick access toolbar, application menu |
Filling menus and lists #
All these methods are called on a control handle.
| Method | Purpose |
|---|---|
of_add_menu_item (string as_id, string as_label, string as_image) | Root entry in the menu of a drop-down or split button |
of_add_menu_item (string as_parent, string as_id, string as_label, string as_image) | Cascading entry: as_parent designates an existing entry of that menu |
of_add_menu_check (string as_id, string as_label) · (id, label, image) | Checkable entry: clicking toggles its state and reports it in ue_menu_selected |
of_add_menu_header (string as_label) | Non-clickable title line, to break up a long menu |
of_add_menu_separator ( ) | Separator line in the menu |
of_menu_item (string as_id) | Handle of a menu entry, to gray it out or check it on the fly |
of_add_combo_item (string as_label) | Adds a choice to the list of a drop-down |
of_add_gallery_item (string as_id, string as_image, string as_label) | Adds a tile to a gallery |
of_select_item (string as_id) | Selects a gallery tile programmatically (without raising an event) |
of_open ( ) | Programmatically opens the menu, the list or the swatch palette of the control |
Application menu and quick access toolbar #
| Method | Purpose |
|---|---|
of_add_app_menu_item (string as_id, string as_label, string as_image) | Root entry of the application menu (the one opened by the is_app_button button) |
of_add_app_menu_item (string as_parent, string as_id, string as_label, string as_image) | Cascading entry of the application menu |
of_add_app_menu_separator (string as_id) | Separator line in the application menu |
of_add_qat (string as_id, string as_image, string as_tooltip) | Button of the quick access toolbar, above the tabs, and returns its handle |
of_qat_item (string as_id) | Handle of a quick access button, to gray it out or hide it on the fly |
Contextual tabs #
| Method | Purpose |
|---|---|
of_add_contextual_tab (string as_id, string as_title, long al_color) | Standalone contextual tab: created hidden, marked with a colored edge. Pass ACCENT_LIGHT to follow the theme accent |
of_add_contextual_group (string as_id, string as_title) · (id, title, al_color) | Group of contextual tabs: a colored titled banner sits above its tabs. Returns its handle |
of_ctx_group (string as_id) | Retrieves the handle of a contextual group that already exists — handy when you did not keep the one returned at creation |
of_add_tab (string as_id, string as_title) | On a contextual group handle: adds a tab topped by the banner, created hidden |
of_tab (string as_id) | On a contextual group handle: handle of one of its tabs |
il_color (property) | On a contextual group handle: recolors the banner on the fly (ACCENT_LIGHT to go back to the accent) |
Shared #
| Method | Purpose |
|---|---|
of_reset ( ) | Empties the ribbon and returns it to its brand-new state, properties included |
of_set_redraw (boolean) | Groups a burst of changes into a single rendering |
of_preload_icons (string as_icons[]) | Warms up a batch of icons at startup: a tab opened later displays its own instantly |
of_save_as_png (string) · of_save_as_jpg (string) | Exports the rendering as an image |
Events #
Every control event carries the full path: you never need an identifier that is unique across the whole application.
| Event | Raised when |
|---|---|
ue_clicked (string as_tab, string as_group, string as_id) | A button, a big button, the main part of a split button or of a color picker is clicked |
ue_toggled (string as_tab, string as_group, string as_id, boolean ab_checked) | A toggle or a check box changes state; ab_checked carries the new state |
ue_menu_selected (string as_tab, string as_group, string as_dropdown, string as_id, boolean ab_checked) | An entry of a drop-down menu is chosen. as_dropdown = the owning control, as_id = the entry, ab_checked = the state of a checkable entry |
ue_combo_changed (string as_tab, string as_group, string as_id, string as_text) | A drop-down changes value, either by selection or by typing |
ue_value_changed (string as_tab, string as_group, string as_id, double ad_value) | A numeric spinner changes value |
ue_color_changed (string as_tab, string as_group, string as_id, long al_color) | A color is chosen in a color picker |
ue_gallery_selection_changed (string as_tab, string as_group, string as_id, string as_from_item, string as_item) | A gallery tile has been picked. Same arguments as ue_gallery_selection_changing: the question and its outcome read the same way, and as_from_item is the tile left |
ue_gallery_selection_changing (string as_tab, string as_group, string as_id, string as_from_item, string as_item) → boolean | Cancelable, raised before the tile is picked. Raised by default; ib_veto_gallery = false removes it. as_from_item is the current tile. Return false to keep it (a style the document cannot take yet) |
ue_launcher (string as_tab, string as_group) | The launcher arrow of a group is clicked — open your options window |
ue_selection_changed (string as_id) | A tab becomes active, by a click or through of_select_tab |
ue_app_button ( ) | The application button is clicked |
ue_app_menu_selected (string as_id) | An entry of the application menu is chosen |
ue_minimized (boolean ab_minimized) | The ribbon is collapsed or expanded by the user |
ue_size_changed (long al_height, boolean ab_minimized) | The ribbon's height changed on its own: folded, unfolded, a contextual tab shown, a narrower window dropping a row. Unlike ue_auto_height — which only speaks when the component sizes itself — this one fires whether auto-height is on or off: it is pure information, for laying out what sits underneath |
ue_keytips (boolean ab_on, integer ai_level) | The keytips appear (true) or disappear (false). ai_level tells how far the navigation has gone: 1 = the tabs are lettered, 2 = the commands of the current tab are, 0 = no keytip left |
ue_auto_height (long al_height) | The ribbon reports its ideal height and has just adjusted to it — always active: a ribbon's height is intrinsic |
ue_ready ( ) | The component has finished loading; everything sent beforehand has been replayed |
ue_runtime_missing ( ) | The WebView2 runtime is missing: the component stays empty |
ue_bg_color (long al_color) | The component has computed its theme background color; the userobject has already adopted it (backcolor) |
Examples #
A complete ribbon, from the application menu to the groups #
// open event : the whole build is grouped into a single rendering
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 = "File"
// Application menu, with a cascade under "Save as"
uo_ruban.of_add_app_menu_item(/*id*/ "nouveau", /*label*/ "New", /*image*/ "mono:img\new.svg")
uo_ruban.of_add_app_menu_item("ouvrir", "Open...", "mono:img\open.svg")
uo_ruban.of_add_app_menu_item("enr_sous", "Save as", "mono:img\saveas.svg")
uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*id*/ "sous_pdf", "PDF document", "")
uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*id*/ "sous_csv", "CSV file", "")
uo_ruban.of_add_app_menu_separator("sep1")
uo_ruban.of_add_app_menu_item("quitter", "Exit", "mono:img\exit.svg")
// Quick access toolbar, above the tabs
uo_ruban.of_add_qat(/*id*/ "qat_enr", /*image*/ "mono:img\save.svg", /*tooltip*/ "Save")
uo_ruban.of_add_qat("qat_annuler", "mono:img\undo.svg", "Undo")
// Home tab
lnv_onglet = uo_ruban.of_add_tab("accueil", "Home")
lnv_onglet.is_keytip = "H"
lnv_groupe = lnv_onglet.of_add_group("presse_papier", "Clipboard")
lnv_item = lnv_groupe.of_add_big_split("coller", "Paste", "mono:img\paste.svg")
lnv_item.of_add_menu_item("coller_texte", "Paste without formatting", "")
lnv_item.of_add_menu_item("coller_lien", "Paste as link", "")
lnv_groupe.of_add_button("couper", "Cut", "mono:img\cut.svg")
lnv_groupe.of_add_button("copier", "Copy", "mono:img\copy.svg")
lnv_groupe.ib_launcher = true // options arrow at the bottom right
uo_ruban.of_set_redraw(true)
uo_ruban.of_select_tab("accueil")
A single click router #
// ue_clicked event of uo_ruban : (string as_tab, string as_group, string as_id)
// The full path arrives with the event : a single router is enough,
// and two groups can reuse the same identifier without getting in the way.
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
Driving the state of controls according to permissions #
// Always through the path : tab > group > control
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
// Gray out an entry INSIDE a drop-down menu (level 4)
uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller") &
.of_menu_item("coller_lien").ib_enabled = false
Banner-headed contextual tabs #
The Office principle: tabs that appear only when the selection warrants them, topped by a colored titled banner.
// open event : we prepare the contextual group, hidden by default
n_pbt_ribbon_ctx_group lnv_ctx
n_pbt_ribbon_tab lnv_onglet
n_pbt_ribbon_group lnv_groupe
// Without a color, the banner follows the theme accent ; RGB(...) to force it
lnv_ctx = uo_ruban.of_add_contextual_group(/*id*/ "img", /*title*/ "Picture Tools", &
/*color*/ RGB(224, 32, 96))
lnv_onglet = lnv_ctx.of_add_tab("format", "Format")
lnv_groupe = lnv_onglet.of_add_group("ajuster", "Adjust")
lnv_groupe.of_add_big_button("rogner", "Crop", "mono:img\crop.svg")
lnv_groupe.of_add_button("pivoter", "Rotate", "mono:img\rotate.svg")
// When a picture is selected : we reveal the tab and activate it
uo_ruban.of_tab("format").ib_visible = true
uo_ruban.of_select_tab("format")
// When it is deselected : we hide it, the banner goes away with it
uo_ruban.of_tab("format").ib_visible = false
Drop-down, spinner, color picker and gallery #
n_pbt_ribbon_group lnv_groupe
n_pbt_ribbon_item lnv_item
lnv_groupe = uo_ruban.of_tab("accueil").of_add_group("police", "Font")
// Editable drop-down : we fill it through its handle
lnv_item = lnv_groupe.of_add_combo(/*id*/ "nom_police", /*width_px*/ 140, /*editable*/ 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"
// Numeric spinner : min, max, step, initial value
lnv_groupe.of_add_spinner(/*id*/ "taille", /*width_px*/ 70, /*min*/ 6, /*max*/ 96, &
/*step*/ 1, /*value*/ 11)
// Color picker in full palette mode (with OK / Cancel)
lnv_groupe.of_add_colorpicker(/*id*/ "couleur", /*label*/ "Color", &
/*image*/ "mono:img\font-color.svg", &
/*color*/ RGB(0, 0, 0), &
/*mode*/ lnv_groupe.COLORMODE_OPEN)
// Style gallery : scrolling illustrated tiles
lnv_item = lnv_groupe.of_add_gallery(/*id*/ "styles", /*width_px*/ 220, &
/*tile_width*/ 64, /*tile_height*/ 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", "Title")
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")
// The collapsed strip shows 4 thumbnails at a time ; the others stay
// reachable through the arrows, or in the expanded grid.
lnv_item.ii_visible_items = 4
lnv_item.of_select_item("st_normal")
// ue_value_changed event of uo_ruban : (string as_tab, string as_group, string as_id, double ad_value)
if as_id = "taille" then of_appliquer_taille(ad_value)
// ue_color_changed event of uo_ruban : (string as_tab, string as_group, string as_id, long al_color)
if as_id = "couleur" then of_appliquer_couleur(al_color)
Refusing the choice of a gallery thumbnail #
// The question is asked by DEFAULT: nothing to enable. This line does the
// opposite, removing it where arbitration is useless.
uo_ruban.ib_veto_gallery = false
// ue_gallery_selection_changing event of uo_ruban :
// (string as_tab, string as_group, string as_id, string as_from_item, string as_item)
// Returning FALSE keeps the current thumbnail (as_from_item).
if as_item = "st_code" and not of_document_supporte_code() then
MessageBox("Style", "This document cannot take the Code style.")
return false
end if
return true
The dialog launcher #
// The small arrow at the bottom right of the group
uo_ruban.of_tab("accueil").of_group("police").ib_launcher = true
// ue_launcher event of uo_ruban : (string as_tab, string as_group)
// The path identifies the group : we open the matching options window.
choose case as_group
case "police" ; open(w_options_police)
case "presse_papier" ; open(w_options_collage)
end choose
Keytips: driving the ribbon from the keyboard #
// Alt displays the letters ; Alt then H then C triggers "copier"
uo_ruban.of_tab("accueil").is_keytip = "H"
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"
Pressing Alt wherever the focus sits in the window hands over to the ribbon: it takes the keyboard focus and raises its letters. You have nothing to wire — it is enough that at least one keytip is declared. Escape, a second Alt or picking a command return the focus to the control the user had left.
ue_keytips warns you at every state change, and gives you the current level:
// ue_keytips event of uo_ruban : (boolean ab_on, integer ai_level)
// The keyboard is driving the ribbon: clear the status bar hint, which talks
// about the mouse, and put it back when the letters drop.
if ab_on then
uo_statut.of_item("main").is_text = "Type a letter (level " + String(ai_level) + ")"
else
uo_statut.of_item("main").is_text = ""
end if
Rich tooltips on a control #
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 = "Paste (Ctrl+V)"
lnv_item.is_super_tooltip_text = "Inserts the contents of the clipboard." &
+ "[br][br][size-=15]Use the arrow to paste without formatting.[/size-=15]"
lnv_item.is_super_tooltip_image = "img\paste.png"
These four properties are exactly the same as on any other item of the library. For a one-line tooltip, is_tooltip alone is enough.
Automatic height #
The ribbon sizes itself: there is nothing to enable. It notifies you on every height change (collapsing, contextual tab, theme change) so that you can reposition whatever sits below.
// ue_auto_height event of uo_ruban : (long al_height)
// The ribbon has already resized itself : we reposition what sits below.
uo_contenu.y = uo_ruban.y + uo_ruban.height
uo_contenu.height = this.height - uo_contenu.y
Collapsing the ribbon to save space #
uo_ruban.ib_minimized = true
// ue_minimized event of uo_ruban : (boolean ab_minimized)
// We remember the user preference for the next time the window opens.
of_enregistrer_preference("ruban_replie", ab_minimized)
Starting over from an empty ribbon #
// of_reset empties tabs, groups, controls, quick access toolbar and menu
uo_ruban.of_reset()
uo_ruban.of_add_tab("accueil", "Home")
From an existing PowerBuilder menu #
A PowerBuilder application has already described its commands once: in its menu. Labels, shortcuts, images, separators, sub-menus, tooltips — it is all there. n_pbt_menu2ribbon reads that menu back through RTTI and writes the PowerScript that builds the matching ribbon.
// Once, by hand : the generator WRITES code, it does not run in production.
// Paste its result into the open event of your window.
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)
The conversion is deterministic: no AI, no network call, nothing that leaves the machine. And the generated identifiers keep the menu path (m_principal.m_fichier.m_ouvrir), so the choose case of your existing actions works as it is from ue_clicked.
The generated code is a starting point to review, not a deliverable: a menu is a list, a ribbon is a layout. Group things, choose your big buttons, drop what does not deserve to be permanently on show. Sample 9 of the ribbon page in the demo application shows a complete result.
Best practices #
- Wrap the whole build in
of_set_redraw(false)/of_set_redraw(true): a complete ribbon is then drawn in one go, without flickering. - Keep the returned handles (
n_pbt_ribbon_tab,n_pbt_ribbon_group,n_pbt_ribbon_item) in local variables for the duration of the build: the code stays short and readable. To drive a control later on, simply go back through the path. - Call
of_preload_iconsat startup: without it, the first display of a tab that has never been opened shows a brief delay before its icons appear. - An identifier only needs to be unique within its group. Take advantage of that to name your controls simply (
copier,coller) rather than with prefixes. - Reserve contextual tabs for commands that make no sense out of context: a grayed-out permanent tab is more restful than a tab that appears and disappears.
- The question is asked by default: a
ue_gallery_selection_changingleft empty always allows the pick, you have nothing to do. Switch it off withib_veto_gallery = falseif arbitration is useless to you, since every question costs a round trip to PowerBuilder. - One dialog launcher per group at most, and only if the group really has advanced options to offer.
- To rebuild an entire ribbon, prefer
of_clear()(orof_reset()) over a series ofof_remove_tabcalls: without that, reusing a tab identifier fails. - For a lighter command bar, without tabs or groups, see toolbar; for side navigation, listbar.