PBToolboxAI v3 ← Site

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 #

Userobjectu_pbt_ribbon
Item classesn_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 forReplacing a menu bar and its toolbars with a modern command interface that is readable and clearly structured
HeightIntrinsic: the ribbon always fits itself to its content, nothing to enable — see Automatic height
Demo mode limit2 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_item("accueil/presse_papier/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

uo_ruban.of_add_tab("accueil", "Home")

uo_ruban.of_add_group("accueil/presse_papier", "Clipboard")
uo_ruban.of_add_big_button("accueil/presse_papier/coller", "Paste", "mono:img\paste.svg")
uo_ruban.of_add_button("accueil/presse_papier/couper", "Cut", "mono:img\cut.svg")
uo_ruban.of_add_button("accueil/presse_papier/copier", "Copy", "mono:img\copy.svg")

uo_ruban.of_select_tab("accueil")
// ue_clicked event of uo_ruban : (string as_keys)
choose case as_key
    case "coller" ; of_coller()
    case "couper" ; of_couper()
    case "copier" ; of_copier()
end choose

Properties #

PropertyTypeDefaultPurpose
is_app_buttonstring""Label of the application button, at the top left, which opens the application menu. Empty = the label File
ib_minimizedbooleanfalsetrue collapses the ribbon down to its tab headers alone; clicking a tab unfolds it temporarily (raises ue_minimized)
ib_veto_gallerybooleantrueAsk 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_stylestringfluentVisual style of the component (THEME_STYLE_* constants)
is_theme_modestringlightLight or dark variant (THEME_MODE_* constants)
il_theme_accentlong-1Accent color of this component (-1 = the theme accent)
is_tooltipstring""Simple tooltip shown when hovering the component
is_super_tooltip_titlestring""Title of the rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Text of the rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""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("tab"), they can be changed on the fly.

PropertyTypeDefaultPurpose
ib_visiblebooleantruefalse hides the tab without removing it — the very mechanism behind contextual tabs
is_titlestring""Title of the tab. Set by of_add_tab; writing here changes it, reading tells what the tab shows
is_keytipstring""Access letter displayed after pressing Alt ("H" for Home)

Properties of a group — n_pbt_ribbon_group #

Obtained through of_group("tab/group").

PropertyTypeDefaultPurpose
ib_visiblebooleantruefalse hides the group and all its controls
is_titlestring""Caption under the group. Set by of_add_group; writing here changes it
ib_launcherbooleanfalseDisplays 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_item("tab/group/control"). They apply to every type of control; the properties that make no sense for a given type are simply ignored.

PropertyTypeDefaultPurpose
is_labelstring""Label of the control. Accepts rich text markup
ib_enabledbooleantruefalse grays out the control and blocks its activation
ib_checkedbooleanfalsePressed state of a toggle, or checked state of a check box
ib_visiblebooleantruefalse hides the control; its neighbors close the gap
is_textstring""Text typed or selected in a drop-down
id_valuedouble0Numeric value of a spinner
il_colorlong-1Current color of a color picker
ii_visible_itemsinteger3Gallery only: number of tiles the collapsed strip shows at once. The others stay reachable through the arrows, or in the expanded grid
is_keytipstring""Access letter of the control, displayed after pressing Alt
is_tooltipstring""Simple tooltip shown when hovering the item
is_super_tooltip_titlestring""Title of the item rich tooltip (takes precedence over is_tooltip)
is_super_tooltip_textstring""Text of the item rich tooltip (rich markup accepted)
is_super_tooltip_imagestring""Image of the item rich tooltip

Properties of a menu entry — n_pbt_ribbon_menu_item #

Obtained through of_menu_item("tab/group/control/entry").

PropertyTypeDefaultPurpose
is_imagestring""Image of the menu entry. An empty string takes it away
of_is_separator ( ) → boolean——Is the entry a separator line? Read only: what an entry is was decided when it was added
of_is_header ( ) → boolean——Is the entry a non-clickable header? Read only, same reason
of_is_checkable ( ) → boolean——Does the entry carry a check mark? Read only; ib_checked says whether it is on
ib_enabledbooleantruefalse grays out the entry
ib_visiblebooleantruefalse takes the entry out of the menu at its next opening — cascade included — without removing it
ib_checkedbooleanfalseCheck mark of an entry created by of_add_menu_check

The twelve types of controls #

They are all added at a group's address — "home/clipboard" — and return 0 (-5 on an invalid argument, -2 when the component is not created); a menu or a list is then filled at the control's address.

Group methodControl obtainedEvent
of_add_big_button (string as_keys, string as_label, string as_image) → longFull-height big button, icon above the label. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_clicked
of_add_big_split (string as_keys, string as_label, string as_image) → longBig split button: the upper part acts, the arrow opens the menu. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_clicked · ue_menu_selected
of_add_big_dropdown (string as_keys, string as_label, string as_image) → longBig button with a drop-down menu. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_menu_selected
of_add_button (string as_keys, string as_label, string as_image) → longSmall button (stacked in columns of three). Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_clicked
of_add_toggle (string as_keys, string as_label, string as_image) → longSmall toggle that stays pressed. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_toggled
of_add_dropdown (string as_keys, string as_label, string as_image) → longSmall button with a drop-down menu. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_menu_selected
of_add_checkbox (string as_keys, string as_label) → longCheck box. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_toggled
of_add_separator (string as_keys) → longVertical separator between two blocks of controls. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created—
of_add_combo (string as_keys, integer ai_width_px, boolean ab_editable) → longDrop-down, editable or not. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_combo_changed
of_add_spinner (string as_keys, integer ai_width_px, double ad_min, double ad_max, double ad_step, double ad_value) → longNumeric spinner with arrows. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_value_changed
of_add_colorpicker (string as_keys, string as_label, string as_image, long al_color) → longSplit color button: clicking reapplies, the arrow opens the swatch palette. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not createdue_clicked · ue_color_changed
of_add_gallery (id, width_px, tile_width, tile_height)Scrolling strip of illustrated tilesue_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 #

MethodPurpose
of_add_tab (string as_key, string as_title)Adds a tab and returns 0 (-5 on an invalid argument, -2 when the component is not created): groups are then added at its address
of_insert_tab (string as_key, string as_title, integer ai_index)Adds a tab at the position you choose (1 = first) instead of at the end, and returns 0 (-5 on an invalid argument, -2 when the component is not created) like of_add_tab. An id already taken is refused
of_tab (string as_key)Handle of an existing tab (created on first access)
of_add_group (string as_keys, string as_title)Adds a titled group to a tab — "home/clipboard" — and returns 0 (-5 on an invalid argument, -2 when the component is not created)
of_group (string as_keys)Handle of an existing group, by its address
of_item (string as_keys)Handle of an existing control, by its address — "home/clipboard/paste"
of_select_tab (string as_key)Activates a tab — strictly equivalent to a user click (raises ue_selection_changed). Returns 0 once applied, -2 when the component is not created
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_keys)Removes a group and all its controls, by its address. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_remove_item (string as_keys)Removes a control, by its address. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_remove_tab (string as_key)Removes a tab and all its content. Returns 0 once applied, -2 when the component is not created
of_clear ( )Empties the ribbon completely: tabs, groups, controls, quick access toolbar, application menu. Returns 0 once applied, -2 when the component is not created

Filling menus and lists #

All these methods are called on the component, with the address of the control (tab/group/control) — the entry, the choice or the tile as a fourth level.

MethodPurpose
of_add_menu_item (string as_keys, string as_label, string as_image)Root entry in the menu of a drop-down or split button. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_add_menu_check (string as_keys, string as_label) · (id, label, image)Checkable entry: clicking toggles its state and reports it in ue_menu_selected. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_add_menu_header (string as_keys, string as_label)Non-clickable title line, to break up a long menu. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_add_menu_separator (string as_keys)Separator line in the menu. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_menu_item (string as_keys)Handle of a menu entry, to gray it out or check it on the fly
of_add_combo_item (string as_keys, string as_label)Adds a choice to the list of a drop-down. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_add_gallery_item (string as_keys, string as_image, string as_label)Adds a tile to a gallery. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_select_gallery_item (string as_keys)Selects a gallery tile programmatically, by its four-level address (without raising an event). Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created
of_open (string as_keys)Programmatically opens the menu, the list or the swatch palette of the control at that address; a Quick Access Toolbar button is addressed by its key alone. Returns 0 once applied, -5 on an invalid argument (empty key, wrong address), -2 when the component is not created

Application menu and quick access toolbar #

MethodPurpose
of_add_app_menu_item (string as_keys, string as_label, string as_image)Root entry of the application menu (the one opened by the is_app_button button). Returns 0 once applied, -2 when the component is not created
of_add_app_menu_separator (string as_keys)Separator line in the application menu. Returns 0 once applied, -2 when the component is not created
of_add_qat (string as_key, string as_image, string as_tooltip)Button of the quick access toolbar, above the tabs, and returns 0 (-5 on an invalid argument, -2 when the component is not created)
of_qat_item (string as_key)Handle of a quick access button, to gray it out or hide it on the fly

Contextual tabs #

MethodPurpose
of_add_contextual_tab (string as_key, string as_title, long al_color)Standalone contextual tab: created hidden, marked with a colored edge. Pass ACCENT_LIGHT to follow the theme accent. Returns 0 once applied, -2 when the component is not created
of_add_contextual_group (string as_key, string as_title) · (id, title, al_color)Group of contextual tabs: a colored titled banner sits above its tabs. Returns 0 (-5 on an invalid argument, -2 when the component is not created)
of_ctx_group (string as_key)Retrieves the handle of an existing contextual group, by its key — its properties are set on it
of_add_contextual_tab (string as_key, string as_title, string as_group_key)Adds a tab under a contextual group: created hidden, crowned by the group's coloured banner. This is the only way — the group handle no longer adds anything. Returns 0 once applied, -2 when the component is not created
il_color (property)On a contextual group handle: recolors the banner on the fly (ACCENT_LIGHT to go back to the accent)

Shared #

MethodPurpose
of_reset ( )Empties the ribbon and returns it to its brand-new state, properties included. Returns 0 once applied, -2 when the component is not created
of_set_redraw (boolean)Groups a burst of changes into a single rendering. Returns 0 once applied, -2 when the component is not created
of_preload_icons (string as_icons[])Warms up a batch of icons at startup: a tab opened later displays its own instantly. Returns 0 once applied, -2 when the component is not created
of_save_as_png (string) · of_save_as_jpg (string)Exports the rendering as an image. Returns 0 once the image is written, -4 when writing fails, -2 when the component is not created

Events #

Every control event carries the full path: you never need an identifier that is unique across the whole application.

EventRaised when
ue_clicked (string as_keys)A button, a big button, the main part of a split button or of a color picker is clicked
ue_toggled (string as_keys, boolean ab_checked)A toggle or a check box changes state; ab_checked carries the new state
ue_menu_selected (string as_keys, boolean ab_checked)An entry of a drop-down menu is chosen. as_keys carries four levels : tab, group, owning control, then the entry chosen, ab_checked = the state of a checkable entry
ue_combo_changed (string as_keys, string as_text)A drop-down changes value, either by selection or by typing
ue_value_changed (string as_keys, double ad_value)A numeric spinner changes value
ue_color_changed (string as_keys, long al_color)A color is chosen in a color picker
ue_gallery_selection_changed (string as_from_keys, string as_keys)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_keys is the tile left
ue_gallery_selection_changing (string as_from_keys, string as_keys) → booleanCancelable, raised before the tile is picked. Raised by default; ib_veto_gallery = false removes it. as_from_keys is the current tile. Return false to keep it (a style the document cannot take yet)
ue_launcher (string as_keys)The launcher arrow of a group is clicked — open your options window
ue_selection_changed (string as_keys)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_keys)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

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(/*key*/ "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", /*key*/ "sous_pdf", "PDF document", "")
uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*key*/ "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(/*key*/ "qat_enr", /*image*/ "mono:img\save.svg", /*tooltip*/ "Save")
uo_ruban.of_add_qat("qat_annuler", "mono:img\undo.svg", "Undo")

// Home tab
uo_ruban.of_add_tab("accueil", "Home")
uo_ruban.of_tab("accueil").is_keytip = "H"

uo_ruban.of_add_group("accueil/presse_papier", "Clipboard")
uo_ruban.of_add_big_split("accueil/presse_papier/coller", "Paste", "mono:img\paste.svg")
uo_ruban.of_add_menu_item("accueil/presse_papier/coller/coller_texte", "Paste without formatting", "")
uo_ruban.of_add_menu_item("accueil/presse_papier/coller/coller_lien", "Paste as link", "")
uo_ruban.of_add_button("accueil/presse_papier/couper", "Cut", "mono:img\cut.svg")
uo_ruban.of_add_button("accueil/presse_papier/copier", "Copy", "mono:img\copy.svg")
uo_ruban.of_group("accueil/presse_papier").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_keys)
// 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_keys
    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_item("accueil/presse_papier/coller").ib_enabled = of_presse_papier_non_vide()
uo_ruban.of_item("accueil/outils/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_item("accueil/presse_papier/coller") &
        .of_menu_item("coller_lien").ib_enabled = false

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

// Without a color, the banner follows the theme accent ; RGB(...) to force it
uo_ruban.of_add_contextual_group(/*key*/ "img", /*title*/ "Picture Tools", &
                                           /*color*/ RGB(224, 32, 96))
uo_ruban.of_add_contextual_tab("format", "Format", "img")
uo_ruban.of_add_group("format/ajuster", "Adjust")
uo_ruban.of_add_big_button("format/ajuster/rogner", "Crop", "mono:img\crop.svg")
uo_ruban.of_add_button("format/ajuster/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

uo_ruban.of_add_group("accueil/police", "Font")

// Editable drop-down : we fill it through its handle
uo_ruban.of_add_combo("accueil/police/nom_police", /*width_px*/ 140, /*editable*/ true)
uo_ruban.of_add_combo_item("accueil/police/nom_police", "Segoe UI")
uo_ruban.of_add_combo_item("accueil/police/nom_police", "Arial")
uo_ruban.of_add_combo_item("accueil/police/nom_police", "Calibri")
uo_ruban.of_item("accueil/police/nom_police").is_text = "Segoe UI"

// Numeric spinner : min, max, step, initial value
uo_ruban.of_add_spinner("accueil/police/taille", /*width_px*/ 70, /*min*/ 6, /*max*/ 96, &
                          /*step*/ 1, /*value*/ 11)

// Color picker in full palette mode (with OK / Cancel)
uo_ruban.of_add_colorpicker("accueil/police/couleur", /*label*/ "Color", &
                              /*image*/ "mono:img\font-color.svg", &
                              /*color*/ RGB(0, 0, 0), &
                              /*mode*/ u_pbt_ribbon.COLORMODE_OPEN)

// Style gallery : scrolling illustrated tiles
uo_ruban.of_add_gallery("accueil/police/styles", /*width_px*/ 220, &
                                     /*tile_width*/ 64, /*tile_height*/ 48)
uo_ruban.of_add_gallery_item("accueil/police/styles/st_normal", "img\style-normal.png", "Normal")
uo_ruban.of_add_gallery_item("accueil/police/styles/st_titre",  "img\style-titre.png",  "Title")
uo_ruban.of_add_gallery_item("accueil/police/styles/st_note",   "img\style-note.png",   "Note")
uo_ruban.of_add_gallery_item("accueil/police/styles/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.
uo_ruban.of_item("accueil/police/styles").ii_visible_items = 4

uo_ruban.of_select_gallery_item("accueil/police/styles/st_normal")
// ue_value_changed event of uo_ruban : (string as_keys, double ad_value)
n_pbt_utils lnv_utils   // autoinstantiate : nothing to create, nothing to destroy
if lnv_utils.of_leaf(as_keys) = "taille" then of_appliquer_taille(ad_value)
// ue_color_changed event of uo_ruban : (string as_keys, long al_color)
n_pbt_utils lnv_utils   // autoinstantiate : nothing to create, nothing to destroy
if lnv_utils.of_leaf(as_keys) = "couleur" then of_appliquer_couleur(al_color)
// 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_from_keys, string as_keys)
// Returning FALSE keeps the current thumbnail (as_from_keys).
n_pbt_utils lnv_utils   // autoinstantiate : nothing to create, nothing to destroy
if lnv_utils.of_leaf(as_keys) = "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_group("accueil/police").ib_launcher = true
// ue_launcher event of uo_ruban : (string as_keys)
// The path identifies the group : we open the matching options window.
n_pbt_utils lnv_utils   // autoinstantiate : nothing to create, nothing to destroy
choose case lnv_utils.of_leaf(as_keys)
    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_item("accueil/presse_papier/copier").is_keytip = "C"
uo_ruban.of_item("accueil/presse_papier/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 #


lnv_item = uo_ruban.of_item("accueil/presse_papier/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 #

Inherited from the common base #

These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.

MembersRoleDetailed in
of_count · of_keys_at · of_hasWalk what the component holds3.2 Items
of_resetPut the component back to zero3.6 Resetting a component: of_reset()
of_register_shortcut · of_clear_shortcutsThe component's keyboard chords3.5 Keyboard shortcuts
of_is_created · of_is_ready · of_get_last_errorWhether it was born, whether it is ready, what failed3.7 Diagnostics
of_save_as_png · of_save_as_jpgExport the rendering as an image3.8 Exporting the rendering as an image
of_set_redrawGroup changes into a single repaint3.10 Best practices
of_preload_iconsIcons shown with no delayInstant display: of_icon
of_set_translationTranslate one of the component's labels5.2 Adapting a label: of_set_translation
of_focus_webviewGive the component the focus6.4 Keyboard and focus
of_print · of_print_to_pdfPrint, or write a PDF6.9 Printing
of_set_property · of_get_property · of_component_nameDriving a property by its name3.1 The property engine

Two helpers are not inherited: of_icon and of_escape_markup live on n_pbt_utils. Declare one — n_pbt_utils lnv_utils, nothing to create — and call them on it.


← Component reference · Guide contents