# ribbon — `u_pbt_ribbon` #

← Referencia de componentes · Índice de la guía

> Cinta de opciones estilo Office: pestañas, grupos, doce tipos de controles enriquecidos, menú de aplicación, barra de acceso rápido, pestañas contextuales con banda y keytips.

> ▶ Verlo en vivo — Aplicación de demostración, mosaico Ribbon: la vista previa, el código que lo genera y esta página, uno al lado del otro.

## De un vistazo #

Userobject | `u_pbt_ribbon`
Clases de items | `n_pbt_ribbon_tab` (pestaña), `n_pbt_ribbon_group` (grupo), `n_pbt_ribbon_item` (control), `n_pbt_ribbon_menu_item` (entrada de menú), `n_pbt_ribbon_ctx_group` (grupo de pestañas contextuales)
Sirve para | Sustituir una barra de menús y sus barras de herramientas por una interfaz de comandos moderna, legible y jerarquizada
Altura | Intrínseca: la cinta de opciones se ajusta siempre a su contenido, no hay nada que activar — véase Altura automática
Límite en modo demo | 2 pestañas como máximo — véase El modo demo

### La regla de oro: todo pasa por la ruta #

La cinta de opciones es una jerarquía de cuatro niveles: pestaña → grupo → control → entrada de menú. No hay ningún identificador global que gestionar: cada objeto se alcanza mediante la ruta que conduce hasta él y cada adición se realiza sobre el handle del elemento padre.

    // Leer o gobernar un control : siempre la ruta completa
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller").ib_enabled = false

Dos consecuencias prácticas y cómodas: dos grupos distintos pueden usar el mismo identificador de control sin estorbarse, y los eventos le entregan la ruta completa — siempre sabe de dónde procede el clic.

## Inicio rápido #

    // event open de la ventana
    n_pbt_ribbon_tab   lnv_onglet
    n_pbt_ribbon_group lnv_groupe

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

    lnv_groupe = lnv_onglet.of_add_group("presse_papier", "Portapapeles")
    lnv_groupe.of_add_big_button("coller", "Pegar", "mono:img\paste.svg")
    lnv_groupe.of_add_button("couper", "Cortar", "mono:img\cut.svg")
    lnv_groupe.of_add_button("copier", "Copiar", "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

## Propiedades #

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`is_app_button` | string | `""` | Etiqueta del botón de aplicación, arriba a la izquierda, que abre el menú de aplicación. Vacío = etiqueta `File`
`ib_minimized` | boolean | `false` | `true` repliega la cinta de opciones dejando solo los encabezados de las pestañas; un clic en una pestaña la despliega temporalmente (activa `ue_minimized`)
`ib_veto_gallery` | boolean | `true` | Preguntar antes de que se retenga un mosaico de galería (activa `ue_gallery_selection_changing`, que puede rechazarlo). Activo de forma predeterminada: no programar nada deja pasar siempre. Póngalo a `false` para suprimir la ida y vuelta hasta PowerBuilder (~35 ms) donde se notaría
`is_theme_style` | string | `fluent` | Estilo visual del componente (constantes `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante clara u oscura (constantes `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Color de acento de este componente (`-1` = acento del tema)
`is_tooltip` | string | `""` | Tooltip simple mostrado al pasar el ratón por el componente
`is_super_tooltip_title` | string | `""` | Título del tooltip enriquecido (prevalece sobre `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Texto del tooltip enriquecido (se acepta el marcado enriquecido)
`is_super_tooltip_image` | string | `""` | Imagen del tooltip enriquecido

Constante — `ACCENT_LIGHT` (`-1`): se pasa como color de una pestaña o de un grupo contextual para que siga el color de acento del tema, aclarado, en lugar de un color fijo.

### Propiedades de una pestaña — `n_pbt_ribbon_tab` #

Obtenidas mediante `of_tab(id)`, se modifican en caliente.

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`ib_visible` | boolean | `true` | `false` oculta la pestaña sin eliminarla — es el mecanismo mismo de las pestañas contextuales
`is_keytip` | string | `""` | Letra de acceso rápido que se muestra tras pulsar Alt (`"I"` para Inicio)

### Propiedades de un grupo — `n_pbt_ribbon_group` #

Obtenidas mediante `of_tab(id).of_group(id)`.

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`ib_visible` | boolean | `true` | `false` oculta el grupo y todos sus controles
`ib_launcher` | boolean | `false` | Muestra la pequeña flecha en la parte inferior derecha del grupo — el iniciador del cuadro de diálogo (activa `ue_launcher`). La flecha vive en la barra de título del grupo, y un grupo que la cinta ha tenido que plegar por falta de espacio la conserva en el mismo sitio — además viaja al panel que abre el grupo plegado.

Constantes de modo del selector de color: `COLORMODE_PALETTE` (muestrario de casillas, modo predeterminado) y `COLORMODE_OPEN` (paleta completa con confirmación).

### Propiedades de un control — `n_pbt_ribbon_item` #

Obtenidas mediante `of_tab(id).of_group(id).of_item(id)`. Se aplican a todos los tipos de controles; las propiedades que no vienen al caso para un tipo dado simplemente se ignoran.

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`is_label` | string | `""` | Etiqueta del control. Admite el texto enriquecido con etiquetas
`ib_enabled` | boolean | `true` | `false` atenúa el control y bloquea su activación
`ib_checked` | boolean | `false` | Estado pulsado de un conmutador o marcado de una casilla
`ib_visible` | boolean | `true` | `false` oculta el control; los vecinos se compactan
`is_text` | string | `""` | Texto escrito o seleccionado en un cuadro combinado
`id_value` | double | `0` | Valor numérico de un control de número
`il_color` | long | `-1` | Color actual de un selector de color
`ii_visible_items` | integer | `3` | Solo galería: número de mosaicos que la banda plegada muestra de una vez. Los demás siguen siendo accesibles mediante las flechas, o en la cuadrícula desplegada
`is_keytip` | string | `""` | Letra de acceso rápido del control, que se muestra tras pulsar Alt
`is_tooltip` | string | `""` | Tooltip simple mostrado al pasar el ratón por el item
`is_super_tooltip_title` | string | `""` | Título del tooltip enriquecido del item (prevalece sobre `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Texto del tooltip enriquecido del item (se acepta el marcado enriquecido)
`is_super_tooltip_image` | string | `""` | Imagen del tooltip enriquecido del item

### Propiedades de una entrada de menú — `n_pbt_ribbon_menu_item` #

Obtenidas mediante `of_tab(id).of_group(id).of_item(id).of_menu_item(id)`.

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`ib_enabled` | boolean | `true` | `false` atenúa la entrada
`ib_checked` | boolean | `false` | Marca de una entrada creada con `of_add_menu_check`

## Los doce tipos de controles #

Todos se añaden sobre el handle de un grupo y devuelven el handle del control creado — por lo tanto, puede encadenar acto seguido el llenado de un menú o de una lista.

Método del grupo | Control obtenido | Evento
--- | --- | ---
`of_add_big_button (id, label, image)` | Botón grande de altura completa, icono encima de la etiqueta | `ue_clicked`
`of_add_big_split (id, label, image)` | Botón grande dividido: la parte superior actúa, la flecha abre el menú | `ue_clicked` · `ue_menu_selected`
`of_add_big_dropdown (id, label, image)` | Botón grande con menú desplegable | `ue_menu_selected`
`of_add_button (id, label, image)` | Botón pequeño (apilado en columnas de tres) | `ue_clicked`
`of_add_toggle (id, label, image)` | Pequeño conmutador que permanece pulsado | `ue_toggled`
`of_add_dropdown (id, label, image)` | Botón pequeño con menú desplegable | `ue_menu_selected`
`of_add_checkbox (id, label)` | Casilla de verificación | `ue_toggled`
`of_add_separator ( )` | Separador vertical entre dos bloques de controles | —
`of_add_combo (id, largeur_px, modifiable)` | Cuadro combinado, editable o no | `ue_combo_changed`
`of_add_spinner (id, largeur_px, mini, maxi, pas, valeur)` | Control de número con flechas | `ue_value_changed`
`of_add_colorpicker (id, label, image, couleur)` | Botón de color dividido: el clic vuelve a aplicar, la flecha abre el muestrario | `ue_clicked` · `ue_color_changed`
`of_add_gallery (id, ancho_px, ancho_mosaico, alto_mosaico)` | Banda desplazable de mosaicos ilustrados | `ue_gallery_selection_changed`

`of_add_colorpicker` admite un quinto argumento `as_mode`: `COLORMODE_PALETTE` (muestrario de casillas) o `COLORMODE_OPEN` (paleta completa con los botones Aceptar y Cancelar).

## Métodos #

### Construir la cinta de opciones #

Método | Función
--- | ---
`of_add_tab (string as_id, string as_title)` | Añade una pestaña y devuelve su handle: encadene los grupos sobre él
`of_insert_tab (string as_id, string as_title, integer ai_index)` | Añade una pestaña en la posición que usted elige (`0` = la primera) en lugar de al final, y devuelve su handle como `of_add_tab`. Un id ya ocupado se rechaza
`of_tab (string as_id)` | Handle de una pestaña existente (creada en el primer acceso)
`of_add_group (string as_id, string as_title)` | Sobre un handle de pestaña: añade un grupo con título y devuelve su handle
`of_group (string as_id)` | Sobre un handle de pestaña: handle de un grupo existente
`of_item (string as_id)` | Sobre un handle de grupo: handle de un control existente
`of_select_tab (string as_id)` | Activa una pestaña — estrictamente equivalente a un clic del usuario (activa `ue_selection_changed`)
`of_selected_key ( )` | Identificador de la pestaña activa, `""` si no hay ninguna. Se mantiene al día mediante `ue_selection_changed`, por lo que es correcto desde el inicio
`of_remove_group (string as_id)` | Sobre un handle de pestaña: retira un grupo y todos sus controles
`of_remove_item (string as_id)` | Sobre un handle de grupo: retira un control
`of_remove_tab (string as_id)` | Retira una pestaña y todo su contenido
`of_clear ( )` | Vacía por completo la cinta de opciones: pestañas, grupos, controles, barra de acceso rápido, menú de aplicación

### Llenar los menús y las listas #

Todos estos métodos se invocan sobre el handle de un control.

Método | Función
--- | ---
`of_add_menu_item (string as_id, string as_label, string as_image)` | Entrada raíz del menú de un botón desplegable o dividido
`of_add_menu_item (string as_parent, string as_id, string as_label, string as_image)` | Entrada en cascada: `as_parent` designa una entrada existente de este menú
`of_add_menu_check (string as_id, string as_label)` · `(id, label, image)` | Entrada marcable: el clic invierte su estado y lo comunica en `ue_menu_selected`
`of_add_menu_header (string as_label)` | Línea de título en la que no se puede hacer clic, para dividir un menú largo
`of_add_menu_separator ( )` | Línea de separación en el menú
`of_menu_item (string as_id)` | Handle de una entrada de menú, para atenuarla o marcarla en caliente
`of_add_combo_item (string as_label)` | Añade una opción a la lista de un cuadro combinado
`of_add_gallery_item (string as_id, string as_image, string as_label)` | Añade un mosaico a una galería
`of_select_item (string as_id)` | Selecciona un mosaico de una galería por programa (sin activar ningún evento)
`of_open ( )` | Abre por programa el menú, la lista o el muestrario del control

### Menú de aplicación y barra de acceso rápido #

Método | Función
--- | ---
`of_add_app_menu_item (string as_id, string as_label, string as_image)` | Entrada raíz del menú de aplicación (el que abre el botón `is_app_button`)
`of_add_app_menu_item (string as_parent, string as_id, string as_label, string as_image)` | Entrada en cascada del menú de aplicación
`of_add_app_menu_separator (string as_id)` | Línea de separación en el menú de aplicación
`of_add_qat (string as_id, string as_image, string as_tooltip)` | Botón de la barra de acceso rápido, encima de las pestañas, y devuelve su handle
`of_qat_item (string as_id)` | Handle de un botón de acceso rápido, para atenuarlo u ocultarlo en caliente

### Pestañas contextuales #

Método | Función
--- | ---
`of_add_contextual_tab (string as_id, string as_title, long al_color)` | Pestaña contextual aislada: creada oculta, marcada con un filete de color. Pase `ACCENT_LIGHT` para seguir el color de acento del tema
`of_add_contextual_group (string as_id, string as_title)` · `(id, title, al_color)` | Grupo de pestañas contextuales: una banda con título y color corona sus pestañas. Devuelve su handle
`of_ctx_group (string as_id)` | Recupera el handle de un grupo contextual ya creado — útil cuando no ha conservado el que se devolvió en la creación
`of_add_tab (string as_id, string as_title)` | Sobre un handle de grupo contextual: añade una pestaña coronada por la banda, creada oculta
`of_tab (string as_id)` | Sobre un handle de grupo contextual: handle de una de sus pestañas
`il_color` (propiedad) | Sobre un handle de grupo contextual: vuelve a colorear la banda en caliente (`ACCENT_LIGHT` para regresar al color de acento)

### Comunes #

Método | Función
--- | ---
`of_reset ( )` | Vacía la cinta de opciones y la devuelve a su estado inicial, propiedades incluidas
`of_set_redraw (boolean)` | Agrupa una ráfaga de modificaciones en una única representación
`of_preload_icons (string as_icons[])` | Precalienta un lote de iconos al arrancar: una pestaña abierta más tarde muestra los suyos al instante
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exporta la representación como imagen

## Eventos #

Todos los eventos de control llevan consigo la ruta completa: nunca necesita un identificador único en toda la aplicación.

Evento | Se activa cuando
--- | ---
`ue_clicked (string as_tab, string as_group, string as_id)` | Se hace clic en un botón, un botón grande, la parte principal de un botón dividido o de un selector de color
`ue_toggled (string as_tab, string as_group, string as_id, boolean ab_checked)` | Un conmutador o una casilla de verificación cambia de estado; `ab_checked` lleva el nuevo estado
`ue_menu_selected (string as_tab, string as_group, string as_dropdown, string as_id, boolean ab_checked)` | Se elige una entrada de un menú desplegable. `as_dropdown` = el control que lo contiene, `as_id` = la entrada, `ab_checked` = el estado de una entrada marcable
`ue_combo_changed (string as_tab, string as_group, string as_id, string as_text)` | Un cuadro combinado cambia de valor, por selección o por escritura
`ue_value_changed (string as_tab, string as_group, string as_id, double ad_value)` | Un control de número cambia de valor
`ue_color_changed (string as_tab, string as_group, string as_id, long al_color)` | Se elige un color en un selector de color
`ue_gallery_selection_changed (string as_tab, string as_group, string as_id, string as_from_item, string as_item)` | Un mosaico de galería ha sido retenido. Mismos argumentos que `ue_gallery_selection_changing`: la pregunta y su resultado se leen igual, y `as_from_item` es el mosaico abandonado
`ue_gallery_selection_changing (string as_tab, string as_group, string as_id, string as_from_item, string as_item)` → boolean | Cancelable, se plantea antes de que se retenga el mosaico. Lanzado de forma predeterminada; `ib_veto_gallery = false` lo suprime. `as_from_item` es el mosaico actual. Devuelva `false` para conservarlo (un estilo que el documento aún no puede adoptar)
`ue_launcher (string as_tab, string as_group)` | Se hace clic en la flecha de iniciador de un grupo — abra su ventana de opciones
`ue_selection_changed (string as_id)` | Una pestaña pasa a estar activa, por clic o mediante `of_select_tab`
`ue_app_button ( )` | Se hace clic en el botón de aplicación
`ue_app_menu_selected (string as_id)` | Se elige una entrada del menú de aplicación
`ue_minimized (boolean ab_minimized)` | El usuario repliega o despliega la cinta de opciones
`ue_size_changed (long al_height, boolean ab_minimized)` | La altura de la cinta de opciones ha cambiado por sí sola: replegada, desplegada, una pestaña contextual mostrada, una ventana más estrecha que pierde una fila. A diferencia de `ue_auto_height` — que solo habla cuando el componente se dimensiona a sí mismo — este se dispara con la altura automática activada o no: es información pura, para recolocar lo que hay debajo
`ue_keytips (boolean ab_on, integer ai_level)` | Los keytips aparecen (`true`) o desaparecen (`false`). `ai_level` indica en qué punto está la navegación: `1` = las pestañas están letradas, `2` = lo están los comandos de la pestaña actual, `0` = ya no hay ningún keytip
`ue_auto_height (long al_height)` | La cinta de opciones anuncia su altura ideal y acaba de ajustarse a ella — siempre activo: la altura de una cinta de opciones es intrínseca
`ue_ready ( )` | El componente ha terminado de cargarse; todo lo enviado antes se ha reproducido
`ue_runtime_missing ( )` | El runtime WebView2 está ausente: el componente permanece vacío
`ue_bg_color (long al_color)` | El componente ha calculado el color de fondo de su tema; el userobject ya lo ha adoptado (`backcolor`)

## Ejemplos #

### Una cinta de opciones completa, del menú de aplicación a los grupos #

    // event open : se agrupa toda la construccion en una unica representacion
    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 = "Archivo"

    // Menu de aplicacion, con una cascada bajo "Guardar como"
    uo_ruban.of_add_app_menu_item(/*id*/ "nouveau", /*etiqueta*/ "Nuevo", /*imagen*/ "mono:img\new.svg")
    uo_ruban.of_add_app_menu_item("ouvrir", "Abrir...", "mono:img\open.svg")
    uo_ruban.of_add_app_menu_item("enr_sous", "Guardar como", "mono:img\saveas.svg")
    uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*id*/ "sous_pdf", "Documento PDF", "")
    uo_ruban.of_add_app_menu_item(/*parent*/ "enr_sous", /*id*/ "sous_csv", "Archivo CSV", "")
    uo_ruban.of_add_app_menu_separator("sep1")
    uo_ruban.of_add_app_menu_item("quitter", "Salir", "mono:img\exit.svg")

    // Barra de acceso rapido, encima de las pestanas
    uo_ruban.of_add_qat(/*id*/ "qat_enr", /*imagen*/ "mono:img\save.svg", /*tooltip*/ "Guardar")
    uo_ruban.of_add_qat("qat_annuler", "mono:img\undo.svg", "Deshacer")

    // Pestana Inicio
    lnv_onglet = uo_ruban.of_add_tab("accueil", "Inicio")
    lnv_onglet.is_keytip = "I"

    lnv_groupe = lnv_onglet.of_add_group("presse_papier", "Portapapeles")
    lnv_item = lnv_groupe.of_add_big_split("coller", "Pegar", "mono:img\paste.svg")
    lnv_item.of_add_menu_item("coller_texte", "Pegar sin formato", "")
    lnv_item.of_add_menu_item("coller_lien", "Pegar como vínculo", "")
    lnv_groupe.of_add_button("couper", "Cortar", "mono:img\cut.svg")
    lnv_groupe.of_add_button("copier", "Copiar", "mono:img\copy.svg")
    lnv_groupe.ib_launcher = true       // flecha de opciones abajo a la derecha

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

### Un único encaminamiento de los clics #

    // event ue_clicked de uo_ruban : (string as_tab, string as_group, string as_id)
    // La ruta completa llega con el evento : basta un solo encaminamiento,
    // y dos grupos pueden reutilizar el mismo identificador sin estorbarse.
    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

### Gobernar el estado de los controles según los permisos #

    // Siempre a traves de la ruta : pestana > grupo > 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

    // Atenuar una entrada DENTRO de un menu desplegable (nivel 4)
    uo_ruban.of_tab("accueil").of_group("presse_papier").of_item("coller") &
            .of_menu_item("coller_lien").ib_enabled = false

### Pestañas contextuales con banda #

El principio de Office: pestañas que solo aparecen cuando la selección las justifica, coronadas por una banda con título y color.

    // event open : se prepara el grupo contextual, oculto de forma predeterminada
    n_pbt_ribbon_ctx_group lnv_ctx
    n_pbt_ribbon_tab       lnv_onglet
    n_pbt_ribbon_group     lnv_groupe

    // Sin color, la banda sigue el acento del tema ; RGB(...) para imponerlo
    lnv_ctx = uo_ruban.of_add_contextual_group(/*id*/ "img", /*titulo*/ "Herramientas de imagen", &
                                               /*color*/ RGB(224, 32, 96))
    lnv_onglet = lnv_ctx.of_add_tab("format", "Formato")
    lnv_groupe = lnv_onglet.of_add_group("ajuster", "Ajustar")
    lnv_groupe.of_add_big_button("rogner", "Recortar", "mono:img\crop.svg")
    lnv_groupe.of_add_button("pivoter", "Girar", "mono:img\rotate.svg")

    // Al seleccionar una imagen : se revela la pestana y se activa
    uo_ruban.of_tab("format").ib_visible = true
    uo_ruban.of_select_tab("format")

    // Al deseleccionar : se oculta, la banda desaparece con ella
    uo_ruban.of_tab("format").ib_visible = false

### Cuadro combinado, control de número, selector de color y galería #

    n_pbt_ribbon_group lnv_groupe
    n_pbt_ribbon_item  lnv_item

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

    // Cuadro combinado editable : se llena a traves de su handle
    lnv_item = lnv_groupe.of_add_combo(/*id*/ "nom_police", /*ancho_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"

    // Control de numero : minimo, maximo, paso, valor inicial
    lnv_groupe.of_add_spinner(/*id*/ "taille", /*ancho_px*/ 70, /*minimo*/ 6, /*maximo*/ 96, &
                              /*paso*/ 1, /*valor*/ 11)

    // Selector de color en modo paleta completa (con Aceptar / Cancelar)
    lnv_groupe.of_add_colorpicker(/*id*/ "couleur", /*etiqueta*/ "Color", &
                                  /*imagen*/ "mono:img\font-color.svg", &
                                  /*color*/ RGB(0, 0, 0), &
                                  /*modo*/ lnv_groupe.COLORMODE_OPEN)

    // Galeria de estilos : mosaicos ilustrados desplazables
    lnv_item = lnv_groupe.of_add_gallery(/*id*/ "styles", /*ancho_px*/ 220, &
                                         /*ancho_mosaico*/ 64, /*alto_mosaico*/ 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",  "Título")
    lnv_item.of_add_gallery_item("st_note",   "img\style-note.png",   "Nota")
    lnv_item.of_add_gallery_item("st_code",   "img\style-code.png",   "Código")

    // La banda plegada muestra 4 miniaturas a la vez ; las demas siguen siendo
    // accesibles mediante las flechas, o en la cuadricula desplegada.
    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)

### Rechazar la elección de una miniatura de galería #

    // La pregunta se plantea de forma PREDETERMINADA: nada que activar. Esta linea
    // hace lo contrario, la suprime cuando arbitrar no sirve.
    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)
    // Devolver FALSE conserva la miniatura actual (as_from_item).
    if as_item = "st_code" and not of_document_supporte_code() then
        MessageBox("Estilo", "Este documento no puede adoptar el estilo Código.")
        return false
    end if
    return true

### El iniciador del cuadro de diálogo #

    // La pequena flecha en la parte inferior derecha del grupo
    uo_ruban.of_tab("accueil").of_group("police").ib_launcher = true

    // event ue_launcher de uo_ruban : (string as_tab, string as_group)
    // La ruta identifica el grupo : se abre la ventana de opciones correspondiente.
    choose case as_group
        case "police"        ; open(w_options_police)
        case "presse_papier" ; open(w_options_collage)
    end choose

### Keytips: gobernar la cinta de opciones con el teclado #

    // Alt muestra las letras ; Alt luego I luego C activa "copier"
    uo_ruban.of_tab("accueil").is_keytip = "I"
    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"

Una pulsación de Alt esté donde esté el foco dentro de la ventana cede el mando a la cinta de opciones: toma el foco del teclado y muestra sus letras. No tiene nada que programar, basta con que haya al menos un keytip declarado. Esc, un segundo Alt o la elección de un comando devuelven el foco al control que el usuario había abandonado.

`ue_keytips` le avisa en cada cambio de estado y le facilita el nivel actual:

    // event ue_keytips de uo_ruban : (boolean ab_on, integer ai_level)
    // El teclado gobierna la cinta: borrar la ayuda de la barra de estado, que habla
    // del raton, y restablecerla cuando las letras desaparezcan.
    if ab_on then
        uo_statut.of_item("main").is_text = "Escriba una letra (nivel " + String(ai_level) + ")"
    else
        uo_statut.of_item("main").is_text = ""
    end if

### Tooltips enriquecidos en un 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 = "Pegar (Ctrl+V)"
    lnv_item.is_super_tooltip_text  = "Inserta el contenido del portapapeles." &
                                    + "[br][br][size-=15]Use la flecha para pegar sin formato.[/size-=15]"
    lnv_item.is_super_tooltip_image = "img\paste.png"

Estas cuatro propiedades son exactamente las mismas que en cualquier otro item de la biblioteca. Para un tooltip de una sola línea basta `is_tooltip`.

### Altura automática #

La cinta de opciones se dimensiona sola: no hay nada que activar. Le avisa en cada cambio de altura (repliegue, pestaña contextual, cambio de tema) para que usted recoloque lo que hay debajo.

    // event ue_auto_height de uo_ruban : (long al_height)
    // La cinta de opciones ya se ha redimensionado : se recoloca lo que hay debajo.
    uo_contenu.y      = uo_ruban.y + uo_ruban.height
    uo_contenu.height = this.height - uo_contenu.y

### Replegar la cinta de opciones para ganar espacio #

    uo_ruban.ib_minimized = true

    // event ue_minimized de uo_ruban : (boolean ab_minimized)
    // Se memoriza la preferencia del usuario para la proxima apertura.
    of_enregistrer_preference("ruban_replie", ab_minimized)

### Partir de una cinta de opciones vacía #

    // of_reset vacia pestanas, grupos, controles, barra de acceso rapido y menu
    uo_ruban.of_reset()
    uo_ruban.of_add_tab("accueil", "Inicio")

## Desde un menú PowerBuilder existente #

Una aplicación PowerBuilder ya ha descrito sus comandos una vez: en su menú. Etiquetas, atajos, imágenes, separadores, submenús, informaciones sobre herramientas — está todo. `n_pbt_menu2ribbon` vuelve a leer ese menú mediante RTTI y escribe el PowerScript que construye la cinta correspondiente.

    // Una sola vez, a mano : el generador ESCRIBE codigo, no se ejecuta en
    // produccion. Pegue su resultado en el open de su ventana.
    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 conversión es determinista: sin IA, sin llamadas de red, nada que salga del equipo. Y los identificadores generados conservan la ruta del menú (`m_principal.m_fichier.m_ouvrir`), de modo que el `choose case` de sus acciones existentes funciona tal cual desde `ue_clicked`.

El código producido es un punto de partida que hay que revisar, no un entregable: un menú es una lista, una cinta es una maquetación. Agrupe, elija sus botones grandes, quite lo que no merece estar siempre a la vista. El ejemplo 9 de la página de la cinta en la aplicación de demostración muestra un resultado completo.

## Buenas prácticas #

- Encuadre toda la construcción entre `of_set_redraw(false)` y `of_set_redraw(true)`: una cinta de opciones completa se dibuja así de una sola vez, sin parpadeos.
- Conserve los handles devueltos (`n_pbt_ribbon_tab`, `n_pbt_ribbon_group`, `n_pbt_ribbon_item`) en variables locales durante el tiempo de la construcción: el código queda corto y legible. Para gobernar un control más tarde, vuelva a pasar simplemente por la ruta.
- Llame a `of_preload_icons` al arrancar: sin ello, la primera visualización de una pestaña nunca abierta muestra un breve retardo antes de sus iconos.
- Un identificador solo tiene que ser único dentro de su grupo. Aprovéchelo para dar a sus controles nombres sencillos (`copier`, `coller`) en lugar de recurrir a prefijos.
- Reserve las pestañas contextuales para los comandos que no tienen ningún sentido fuera de contexto: una pestaña permanente atenuada es más descansada que una pestaña que aparece y desaparece.
- La pregunta se plantea de forma predeterminada: un `ue_gallery_selection_changing` dejado vacío autoriza siempre la elección, no tiene nada que hacer. Desactívela con `ib_veto_gallery = false` si arbitrar no le sirve, porque cada pregunta cuesta una ida y vuelta hasta PowerBuilder.
- Un solo iniciador de cuadro de diálogo por grupo, y solo si el grupo tiene realmente opciones avanzadas que ofrecer.
- Para reconstruir una cinta de opciones entera, prefiera `of_clear()` (o `of_reset()`) a una serie de `of_remove_tab`: sin ello, reutilizar un identificador de pestaña falla.
- Para una barra de comandos más ligera, sin pestañas ni grupos, vea toolbar; para una navegación lateral, listbar.

← Referencia de componentes · Índice de la guía