PBToolboxAI v4 ← Site

listbar — u_pbt_listbar #

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

Barra de navegación lateral: secciones plegables en acordeón que contienen entradas con icono, con banda de acento sobre la entrada actual y plegado en riel de iconos.

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


De un vistazo #

Userobjectu_pbt_listbar
Clases de itemsn_pbt_listbar_section (sección) → n_pbt_listbar_item (entrada)
Sirve paraSustituir un menú lateral improvisado a base de botones por una navegación estructurada, con tema y plegable
Opciones opt-inib_auto_width, ib_reorderable

Es el único componente de la biblioteca que publica ib_auto_width: su anchura natural sí tiene sentido, ya que el riel plegado es bastante más estrecho que la barra desplegada. Además, el caso habitual ya está cubierto sin activar nada — ib_collapsed = true estrecha la barra hasta el riel, y le devuelve su anchura al desplegarla.


Inicio rápido #

// evento open de la ventana

// Una seccion y luego sus entradas : cada entrada se direcciona por seccion/entrada
uo_nav.of_add_section(/*key*/ "nav", /*text*/ "Navigation")
uo_nav.of_add_item(/*keys*/ "nav/home",   /*text*/ "Home",      /*image*/ "mono:img\home.svg")
uo_nav.of_add_item(/*keys*/ "nav/docs",   /*text*/ "Documents", /*image*/ "mono:img\doc.svg")
uo_nav.of_add_item(/*keys*/ "nav/search", /*text*/ "Search",    /*image*/ "mono:img\find.svg")

// Una segunda seccion, con una sola entrada
uo_nav.of_add_section(/*key*/ "settings", /*text*/ "Settings")
uo_nav.of_add_item(/*keys*/ "settings/prefs", /*text*/ "Preferences", /*image*/ "mono:img\gear.svg")

// La seleccion se pone en la ENTRADA, por su direccion : la seccion y luego la entrada
uo_nav.of_select_item(/*keys*/ "nav/home")

// of_select_item dispara ue_selection_changed, como un clic : la primera pagina se abre alli
// evento ue_selection_changed de uo_nav : (string as_from_keys, string as_keys)
choose case as_keys
    case "nav/home"       ; of_open_home()
    case "nav/docs"       ; of_open_documents()
    case "settings/prefs" ; of_open_preferences()
end choose

Dos niveles, una dirección #

Un identificador de entrada solo es único dentro de su sección: una entrada se designa por lo tanto por su dirección, la sección y luego la entrada unidas por / — "nav/docs". Es el componente quien la recibe (of_item, of_select_item, of_remove_item…); una sección se designa solo por su clave (of_section("nav")). Ver Jerarquías.

// Una seccion por su clave, una entrada por su direccion
uo_nav.of_section(/*key*/ "nav").is_title = "Navigation"
uo_nav.of_item(/*keys*/ "nav/docs").is_text = "Documents"

Los eventos también llevan la ruta completa, y con ella la entrada abandonada: ue_selection_changed(as_from_keys, as_keys).


Propiedades #

PropiedadTipoPredeterminadoFunción
ib_collapsedbooleanfalsetrue pliega la barra en un riel de iconos: los títulos de sección y las etiquetas dejan paso a un filete entre secciones, y todas las entradas siguen visibles, incluso las de una sección plegada (el plegado vuelve al salir del riel). Una entrada sin icono muestra su inicial, y cada entrada dice su etiqueta al pasar el ratón
ib_auto_widthbooleanfalseOpt-in: lo mismo para la anchura, incluida la desplegada (la barra se ajusta a la etiqueta más larga). El plegado en riel, por su parte, ya se estrecha por sí solo; ue_auto_width lo acompaña en ambos casos
ib_reorderablebooleanfalseOpt-in: el usuario puede desplazar una entrada con el ratón. El desplazamiento permanece dentro de su sección — un identificador de entrada solo es único allí, así que cruzar arriesgaría dos claves idénticas (activa ue_item_reordered)
ib_veto_selectionbooleanfalseOpt-in: preguntar antes de que la selección se mueva — un gesto del usuario y of_select_item / of_clear_selection (dispara ue_selection_changing, que puede rechazar; una orden rechazada devuelve -4). Desactivado por defecto, como todo evento cancelable de la biblioteca: ponga true cuando necesite poder rechazar (datos sin guardar). Cada pregunta de un gesto cuesta un viaje de ida y vuelta a PowerBuilder (~35 ms)
is_theme_stylestring""Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio
is_theme_modestring""Variante clara u oscura (constantes THEME_MODE_*); vacío = la de la aplicación, seguida en cada cambio
il_theme_accentlong-1Color de acento de este componente (-1 = acento de la aplicación, o el del tema)
is_tooltipstring""Tooltip simple mostrado al pasar el ratón por el componente
is_super_tooltip_titlestring""Título del tooltip enriquecido (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto del tooltip enriquecido (se acepta el marcado enriquecido)
is_super_tooltip_imagestring""Imagen del tooltip enriquecido

Propiedades de una sección — n_pbt_listbar_section #

PropiedadTipoPredeterminadoFunción
is_titlestring""Título de la sección. Acepta el texto enriquecido con etiquetas. Un título vacío no muestra ninguna fila de encabezado: la sección se convierte en una simple agrupación invisible; un espacio la separa de la sección de arriba (una línea fina en el riel), y ya no se pliega — nadie podría volver a abrirla
ib_collapsedbooleanfalseAcordeón: true pliega las entradas de esta sección. El encabezado permanece visible y su galón gira; ue_section_toggled sigue, como con un clic en el encabezado
ib_pinnedbooleanfalsetrue fija la sección abajo de la barra (Configuración, Ayuda): un pie que permanece visible mientras el resto de la barra se desplaza, empujado abajo cuando sobra espacio, y abajo del riel también. Varias secciones fijadas se apilan en su orden. Solo cambia el dibujo: la disposición (of_get_layout) conserva el orden de las secciones, y la flecha Abajo pasa de la última entrada de arriba a la primera del pie
is_imagestring""Icono delante del título de la sección (formas aceptadas: ruta, mono:, tint:, recurso de DLL). Una cadena vacía lo quita
il_accentlong-1Acento de esta sección, es decir de su título y de nada más: sus entradas conservan el suyo (-1 = el del componente)
il_back_colorlong-1Fondo del título de la sección, en RGB(r,g,b) (-1 = el del componente)
il_text_colorlong-1Color del texto del título de la sección (-1 = el del componente)
il_back_color_hoverlong-1Fondo del título bajo el puntero (-1 = el del componente)
il_text_color_hoverlong-1Color del texto del título bajo el puntero (-1 = el del componente)

Propiedades de una entrada — n_pbt_listbar_item #

PropiedadTipoPredeterminadoFunción
is_textstring""Etiqueta de la entrada, modificable en caliente sin reconstruir la barra. Acepta el texto enriquecido con etiquetas
is_imagestring""Icono, modificable en caliente (formas aceptadas: ruta, mono:, tint:, recurso de DLL)
ib_enabledbooleantruefalse atenúa la entrada: se queda en su sitio y ya no responde a nada — ni clic, ni Intro, ni clic derecho, y las flechas la saltan
ib_visiblebooleantruefalse oculta la entrada sin retirarla de la barra. Una entrada oculta no puede convertirse en la selección (of_select_item devuelve -5); ocultar la que está seleccionada la mantiene seleccionada, y volver a mostrarla la devuelve tal cual
is_badgestring""Insignia de contador al final de la entrada ("12" sin leer), con los colores de insignia del tema; en el riel, sobre la esquina del icono. Cualquier texto corto, marcado aceptado. Una cadena vacía la quita
of_is_selected ( ) → boolean——¿Es esta entrada la seleccionada? Solo lectura, y a propósito: la selección es un estado de toda la barra, no un indicador por entrada. Para ponerla, of_select_item en el componente
is_tooltipstring""Tooltip simple mostrado al pasar el ratón por el item
is_super_tooltip_titlestring""Título del tooltip enriquecido del item (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto del tooltip enriquecido del item (se acepta el marcado enriquecido)
is_super_tooltip_imagestring""Imagen del tooltip enriquecido del item
il_accentlong-1Acento de esta entrada: la barra que la marca cuando está seleccionada lo toma (-1 = el del componente). Para «esta entrada en rojo», il_back_color / il_text_color
il_back_colorlong-1Fondo propio de la entrada, en RGB(r,g,b) (-1 = lo que da el tema)
il_text_colorlong-1Color del texto de la entrada (-1 = lo que da el tema)
il_back_color_hoverlong-1Fondo de la entrada bajo el puntero (-1 = lo que da el tema)
il_text_color_hoverlong-1Color del texto de la entrada bajo el puntero (-1 = lo que da el tema)

Métodos #

En el componente #

MétodoFunción
of_add_section (string as_key, string as_text)Añade una sección al final de la barra. Un texto vacío no dibuja ninguna línea de título. El handle viene de of_section("nav") cuando quiere poner una propiedad. Devuelve 0 una vez aplicado, -5 si la clave está vacía, ya ocupada o contiene / o `, -2` si el componente no está creado
of_insert_section (string as_key, string as_text, integer ai_index)Añade una sección en la posición elegida (primera posición = 1) en lugar de al final. El índice cuenta secciones, no filas. Un nombre ya ocupado se rechaza: dos secciones con el mismo nombre harían ambigua la dirección de cada una de sus entradas. Devuelve 0 una vez aplicado, -5 si la clave está vacía, ya ocupada o contiene / o `, -2` si el componente no está creado
of_move_section (string as_key, integer ai_index)Mueve una sección a la posición ai_index, con sus entradas. Mover solo el encabezado dejaría caer sus entradas en la sección que queda por encima de ellas. Devuelve 0 una vez aplicado, -5 para una sección que esta barra nunca añadió, -2 si el componente no está creado
of_remove_section (string as_key)Quita una sección y todo lo que contiene. Vaciarla conservando sus entradas las dejaría huérfanas: llevarían un identificador de sección que ya no nombra nada. Si la selección estaba en ella, ue_selection_changed anuncia que ya no hay. Devuelve 0 una vez aplicado, -5 para una sección que esta barra nunca añadió, -2 si el componente no está creado
of_section (string as_key)Handle de una sección, por su clave: su título, icono, plegado y colores se ponen a través de él (creado en el primer acceso). Una entrada se alcanza en cambio desde el componente, por su dirección (of_item)
of_add_item (string as_keys, string as_text, string as_image)Añade una entrada en su dirección, "nav/home": la sección donde aterriza y luego su propio identificador. Una sobrecarga omite el icono. Devuelve 0 una vez añadida, -5 si la sección no fue añadida por esta barra, si la dirección ya está ocupada o si la clave contiene `, -2` si el componente no está creado
of_item (string as_keys)Handle de una entrada, por su dirección (creado en el primer acceso)
of_insert_item (string as_keys, string as_text, integer ai_index)Inserta una entrada en la posición ai_index dentro de su sección (primera posición = 1). Devuelve 0 una vez añadida, -5 si la sección no fue añadida por esta barra, si la dirección ya está ocupada o si la clave contiene `, -2` si el componente no está creado
of_insert_item (string as_keys, string as_text, string as_image, integer ai_index)Igual, con el icono de la entrada: of_add_item acepta uno, así que insertar también debe poder. Devuelve 0 una vez añadida, -5 si la sección no fue añadida por esta barra, si la dirección ya está ocupada o si la clave contiene `, -2` si el componente no está creado
of_move_item (string as_keys, integer ai_index)Mueve una entrada existente dentro de su sección, conservando su estado. Devuelve 0 una vez aplicado, -5 para una dirección que esta barra nunca añadió, -2 si el componente no está creado
of_remove_item (string as_keys)Quita una entrada, designada por su dirección. Si era la selección, ue_selection_changed anuncia que ya no hay. Devuelve 0 una vez aplicado, -5 para una dirección que esta barra nunca añadió, -2 si el componente no está creado
of_clear ( )Vacía la barra: todas las secciones y todas las entradas. Si había una entrada seleccionada, ue_selection_changed anuncia que ya no hay (dirección vacía); ue_layout_changed no se dispara, usted está reconstruyendo. Devuelve 0 una vez aplicado, -2 si el componente no está creado
of_select_item (string as_keys)Selecciona una entrada, como un clic en ella: con ib_veto_selection activo, primero se pregunta ue_selection_changing; después sigue ue_selection_changed, como para un clic (justo después de su script, desde la cola de eventos), y of_selected_key() leído justo después ya devuelve la nueva dirección. Entrada ya seleccionada: no se pregunta ni se dispara nada. Devuelve 0 una vez seleccionada (o si ya lo estaba), -4 si su ue_selection_changing lo rechazó (nada se mueve), -5 para una dirección que esta barra nunca añadió, una entrada oculta o una entrada que el límite de la demo no dibuja, -2 si el componente no está creado
of_get_layout ( )Vuelve a leer la disposición actual en JSON: las secciones en orden, cada una con sus entradas en orden y su estado plegado. Guárdela (archivo, base de datos, registro) y devuélvala con of_set_layout en el siguiente arranque. El mismo par lleva los mismos nombres en todos los componentes reorganizables
of_set_layout (string as_layout_json)Restaura una disposición leída con of_get_layout o recibida con ue_layout_changed. Lo que la disposición no nombra conserva su lugar al final: una disposición de ayer no debe hacer desaparecer lo añadido desde entonces. Aplicarla no genera ningún event — usted la ha proporcionado. Devuelve 0 una vez aplicado, -5 para un texto vacío o que no es un objeto JSON (un archivo truncado): no se envía nada; el plegado de una sección ausente se ignora, -2 si el componente no está creado
of_clear_selection ( )No deja ninguna entrada seleccionada, como cualquier movimiento: con ib_veto_selection activo, primero se pregunta ue_selection_changing, y después sigue ue_selection_changed con una dirección vacía. Nada seleccionado ya: no se pregunta ni se dispara nada. Devuelve 0 una vez aplicado, -4 si su ue_selection_changing lo rechazó (la entrada sigue seleccionada), -2 si el componente no está creado
of_selected_key ( )Dirección de la entrada seleccionada — "nav/docs", "" si no hay ninguna. Es exactamente lo que le entrega ue_selection_changed: una comparación es una comparación, no un reensamblaje. Siempre la entrada actual, leída en el componente: tras un clic, y justo después de of_select_item también
of_reset ( )Vacía la barra y luego devuelve el componente a su estado nuevo. Si había una entrada seleccionada, ue_selection_changed se dispara con una dirección vacía; ue_layout_changed no se dispara. Devuelve 0 una vez aplicado, -2 si el componente no está creado
of_set_redraw (boolean)Agrupa una ráfaga de modificaciones en una única representación. Devuelve 0 una vez aplicado, -2 si el componente no está creado
of_save_as_png (string) · of_save_as_jpg (string)Exporta la representación como imagen. Devuelve 0 una vez escrita la imagen, -4 si la escritura falla, -2 si el componente no está creado

En una sección — n_pbt_listbar_section #

MétodoFunción
of_count ( )Número de entradas de la sección, ocultas incluidas
of_keys_at (long al_index)Dirección de la entrada en la posición al_index (desde 1) — "nav/docs", lista para pasarla tal cual a of_item
of_has (string as_key)¿Contiene la sección esta entrada?

Eventos #

EventoSe activa cuando
ue_selection_changed (string as_from_keys, string as_keys)La selección se ha movido: el usuario eligió una entrada (clic, Intro, Espacio), su código la movió (of_select_item, of_clear_selection — una orden también lo dispara, como SelectItem dispara SelectionChanged), o la entrada seleccionada se fue (of_remove_item, of_remove_section, of_clear, of_reset — as_keys queda entonces vacío). Mismos argumentos que ue_selection_changing: la pregunta y su resultado se leen igual, y el par as_from_* designa la entrada abandonada (vacío si no hay ninguna)
ue_section_toggled (string as_key, boolean ab_collapsed)El usuario pliega o despliega una sección: clic en su título, Intro en el título, o las flechas Izquierda / Derecha (invertidas de derecha a izquierda), o su código que pone ib_collapsed de una sección
ue_item_reordered (string as_keys, integer ai_index)El usuario ha terminado de arrastrar una entrada. ai_index es su nuevo rango dentro de su sección, a partir de 1, como of_move_item. Conserve ese orden para devolver al usuario su barra tal como la dejó
ue_layout_changed (string as_layout_json)La disposición que hay que guardar ha cambiado: una entrada o una sección se movió, una sección se plegó o desplegó, algo se retiró — por el usuario o por su código. Lleva la disposición entera, no solo lo que se movió: guardarla es una asignación. Las adiciones, el riel, of_set_layout, of_clear y of_reset no lo disparan: son construcción, no disposición
ue_item_rclicked (string as_keys)El usuario hizo clic derecho en una entrada: su dirección, "nav/docs". Un evento por clic derecho, y la entrada no se selecciona. Abra allí su propio menú, en el puntero: m_menu.PopMenu(PointerX(), PointerY()). Una entrada atenuada no dispara nada
ue_selection_changing (string as_from_keys, string as_keys) → booleanCancelable, planteado antes de que la selección se mueva — un gesto del usuario, of_select_item u of_clear_selection —, y solo cuando ib_veto_selection = true (desactivado por defecto). Devuelva false para quedarse donde está: nada se mueve, y la orden de su código devuelve -4
ue_auto_width (long al_width)El componente ha recalculado su anchura ideal — requiere ib_auto_width = true
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 #

Menú lateral completo #

// Toda la barra en un solo renderizado
uo_nav.of_set_redraw(/*on*/ false)

// Primera seccion y sus tres entradas
uo_nav.of_add_section(/*key*/ "folders", /*text*/ "Folders")
uo_nav.of_add_item(/*keys*/ "folders/recent",    /*text*/ "Recent",    /*image*/ "mono:img\clock.svg")
uo_nav.of_add_item(/*keys*/ "folders/customers", /*text*/ "Customers", /*image*/ "mono:img\user.svg")
uo_nav.of_add_item(/*keys*/ "folders/archives",  /*text*/ "Archives",  /*image*/ "mono:img\box.svg")

// Segunda seccion y sus dos entradas
uo_nav.of_add_section(/*key*/ "tools", /*text*/ "Tools")
uo_nav.of_add_item(/*keys*/ "tools/import", /*text*/ "Import", /*image*/ "mono:img\import.svg")
uo_nav.of_add_item(/*keys*/ "tools/export", /*text*/ "Export", /*image*/ "mono:img\export.svg")

// Un solo renderizado para todo y luego se selecciona la primera entrada
uo_nav.of_set_redraw(/*on*/ true)
uo_nav.of_select_item(/*keys*/ "folders/recent")

Riel plegable que libera espacio #

// Plegar en riel de iconos : la barra se estrecha por si misma (y recupera su
// anchura cuando usted la despliega).
uo_nav.ib_collapsed = true
// evento ue_auto_width de uo_nav : (long al_width)
// La barra acaba de adoptar su ancho ideal : realinear lo que queda a su derecha.
uo_content.x     = uo_nav.x + al_width
uo_content.width = parent.width - uo_content.x

Acordeón: plegar una sección #

// Plegar la seccion de archivos, poco usada
uo_nav.of_section(/*key*/ "folders").ib_collapsed = true
// evento ue_section_toggled de uo_nav : (string as_key, boolean ab_collapsed)
// Recordar el plegado elegido por el usuario
of_save_preference("section_" + as_key, String(ab_collapsed))

Configuración y Ayuda fijadas abajo #

Una sección sin título, fijada: ninguna fila de encabezado, dos entradas que permanecen al pie de la barra incluso cuando la navegación, más larga que la ventana, se desplaza. Un clic ahí selecciona como en cualquier otro sitio: ue_selection_changed recibe foot/settings.

// Una seccion SIN titulo (ninguna fila de encabezado), fijada abajo de la barra :
// permanece visible mientras las entradas de encima se desplazan
uo_nav.of_add_section(/*key*/ "foot", /*text*/ "")
uo_nav.of_add_item(/*keys*/ "foot/settings", /*text*/ "Settings", /*image*/ "mono:img\\gear.svg")
uo_nav.of_add_item(/*keys*/ "foot/help",     /*text*/ "Help",     /*image*/ "mono:img\\help.svg")
uo_nav.of_section(/*key*/ "foot").ib_pinned = true

Reaccionar a la navegación #

// evento ue_selection_changed de uo_nav : (string as_from_keys, string as_keys)
// La direccion lleva los dos niveles : dos secciones pueden tener una entrada "list".
// Local variables
n_pbt_utils lnv_utils   // autoinstantiate : nada que crear, nada que destruir
string ls_keys[]

// Divide la direccion : [1] = la seccion, [2] = la entrada
if lnv_utils.of_split_path(/*keys*/ as_keys, /*out*/ ls_keys) < 2 then return
choose case ls_keys[1]
    case "folders" ; of_open_folder(ls_keys[2])
    case "tools"   ; of_run_tool(ls_keys[2])
end choose

Rechazar un cambio de selección #

// La pregunta esta desactivada por DEFECTO : activarla para poder rechazar un cambio
uo_nav.ib_veto_selection = true
// evento ue_selection_changing de uo_nav :
//   (string as_from_keys, string as_keys)
// Devolver FALSE deja al usuario en la entrada que abandona.
if of_has_unsaved_changes(as_from_keys) then
    MessageBox("Entrada", "Termine la ficha actual antes de navegar.")
    return false
end if
return true

Actualizar una entrada en caliente #

// Local variables
n_pbt_listbar_item lnv_entry

// La entrada se designa por su direccion : la seccion y luego la entrada
lnv_entry = uo_nav.of_item(/*keys*/ "folders/recent")
lnv_entry.is_text  = "Recent (12)"
lnv_entry.is_image = "mono:img\clock_full.svg"
// Atenuar u ocultar segun los permisos, sin reconstruir la barra
uo_nav.of_item(/*keys*/ "tools/import").ib_enabled = of_is_allowed("import")
uo_nav.of_item(/*keys*/ "tools/export").ib_visible = gb_expert_mode

Selección controlada desde el código #

// Poner la seleccion en otro lugar : la banda de acento sigue, y
// ue_selection_changed sale como para un clic
uo_nav.of_select_item(/*keys*/ "folders/customers")

// O borrarla por completo
uo_nav.of_clear_selection()

Reconstruir la barra #

// of_clear vacia secciones y entradas ; of_reset restaura ademas los valores por defecto
uo_nav.of_clear()
of_build_menu_for_profile()

Buenas prácticas #

Heredado de la base común #

Estos miembros existen en todos los componentes visuales — no son propios de este. Se detallan una sola vez, en los capítulos transversales; esta tabla solo dice dónde leerlos.

MiembrosFunciónDetallado en
of_count · of_keys_at · of_hasRecorrer lo que el componente contiene3.2 Los items
of_resetPoner el componente a cero3.6 Poner un componente a cero: of_reset()
of_register_shortcut · of_clear_shortcutsAtajos de teclado del componente3.5 Los atajos de teclado
of_is_created · of_is_ready · of_get_last_errorSi ha nacido, si está listo, qué ha fallado3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar el render como imagen3.8 Exportar la representación como imagen
of_set_redrawAgrupar los cambios en un solo repintado3.10 Buenas prácticas
of_preload_iconsIconos mostrados sin retardoVisualización instantánea: of_icon
of_set_translationTraducir una etiqueta del componente5.2 Adaptar una etiqueta: of_set_translation
of_focus_webviewDar el foco al componente6.4 Teclado y foco
of_print · of_print_to_pdfImprimir, o escribir un PDF6.9 Imprimir
of_set_property · of_get_property · of_component_nameControlar una propiedad por su nombre3.1 El motor de propiedades

Dos ayudas no se heredan: of_icon y of_escape_markup viven en n_pbt_utils. Declare uno — n_pbt_utils lnv_utils, nada que crear — y llámelas sobre él.

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