radialmenu — u_pbt_radialmenu #
← Referencia de componentes · Índice de la guía
Menú contextual radial: los comandos en corona alrededor del cursor, elegidos por su dirección en lugar de leídos en una lista.
▶ Verlo en vivo — Aplicación de demostración, mosaico Radial menu: la vista previa, el código que lo produce y esta página, lado a lado.
En resumen #
| Userobject | u_pbt_radialmenu |
| Clase de elementos | n_pbt_radialmenu_item (of_item(keys)) |
| Sirve para | Ofrecer un puñado de comandos frecuentes donde la mano ya está |
| Principio | Usted describe las ramas; la rueda, la forma y la navegación son cosa nuestra |
Inicio rápido #
// Una rueda montada para lo que esta bajo el cursor
uo_wheel.of_add_item(/*keys*/ "cut", /*text*/ "Cut")
uo_wheel.of_add_item(/*keys*/ "copy", /*text*/ "Copy")
uo_wheel.of_add_item(/*keys*/ "paste", /*text*/ "Paste")
uo_wheel.of_add_item(/*keys*/ "delete", /*text*/ "Delete")
// Se abre al soltar el boton derecho: ver ue_rclicked
Abrir y luego elegir #
La rueda se abre al soltar el botón derecho, y hace falta un segundo clic para elegir. No es un detalle de implementación: si se abriera al pulsar, el soltado de ese mismo clic seleccionaría de inmediato el sector caído bajo el cursor, y el usuario lanzaría un comando sin haberlo visto.
Por eso of_show() se llama desde el evento de clic derecho del control sobre el que el usuario hace el gesto (un statictext, un button, una rejilla…): en ese instante el botón ya está arriba, y el clic siguiente es realmente el que elige. El menú radial en sí no tiene superficie — por tanto ningún evento de ratón propio.
El componente en sí es invisible: no ocupa sitio en la ventana. Colóquelo donde sea, con anchura y altura cero — solo existe mientras la rueda está abierta.
La rama señalada — con el ratón o el teclado — muestra su etiqueta entera, por encima de sus vecinas: un sector conserva dos líneas como máximo (una sola a partir de nueve ramas), y eso es lo que le permite llevar una etiqueta corta sin mentir sobre lo que hace. El cubo central es la salida: hacer clic en él cierra la rueda; dentro de una sub-rueda, sube un nivel. Mientras la rueda está abierta la aplicación sigue funcionando: una rama retirada, atenuada u oculta entretanto ya no se elige (en su lugar, ue_dismissed); of_clear, of_reset, of_close y un segundo of_show cierran la rueda abierta, y también of_remove_item cuando la rueda mostraba la rama quitada — ue_dismissed se lanza en el acto, y of_is_open responde falso en cuanto vuelve la llamada.
// Se abre al soltar el boton derecho: ver ue_rclicked
uo_wheel.of_show()
Con el teclado, las flechas recorren las ramas saltando las atenuadas, Intro o Espacio elige, ← y Retroceso suben un nivel, y Escape sube un nivel en una sub-rueda — solo cierra la rueda en la raíz. Ninguna de estas teclas llega a la aplicación mientras la rueda está abierta. En lectura de derecha a izquierda, la corona gira en el otro sentido y ← y → se intercambian: → sube un nivel.
Para abrirla con el teclado — la tecla Menú, Mayús+F10 —, llame a of_show_over desde el control que tiene el foco, con ab_keyboard a verdadero: la rueda se centra en ese control, esté donde esté el ratón, y su primera rama que responde queda encendida — Intro la elige, las flechas siguen desde ahí. of_show_over(control) sin ese segundo argumento sirve también a un botón de barra de herramientas: la rueda se abre sobre él.
Las sub-ruedas #
Una dirección cuelga ramas bajo otra: export/pdf. Elegir la rama padre no elige nada: la rueda es sustituida por la de sus hijos, y el cubo pasa a ser la vuelta atrás.
¿Por qué sustituir en lugar de añadir una segunda corona? Porque un anillo exterior dividiría los sectores por dos en cada nivel. Ocho ramas ya es el máximo legible; no hay sitio para mostrar dos niveles a la vez.
El evento ue_item_selected informa de la dirección completa (export/pdf), no de la clave de la hoja sola. Dos sub-ruedas pueden por tanto nombrar sus ramas igual.
// A branch, then two entries at its address
uo_wheel.of_add_item(/*keys*/ "export", /*text*/ "Export")
uo_wheel.of_add_item(/*keys*/ "export/pdf", /*text*/ "PDF")
uo_wheel.of_add_item(/*keys*/ "export/csv", /*text*/ "CSV")
Para quitar una rama — con su sub-rueda — sin reconstruir toda la rueda: of_remove_item("export/csv"). Las demás ramas se quedan en su sitio.
Cuando hay demasiadas ramas #
Una rueda se lee por dirección, y más allá de ocho sectores las porciones dejan de distinguirse. ii_max_sectors fija ese tope (de 3 a 12, 8 por defecto).
Las ramas sobrantes no se pierden: el último lugar de la corona pasa a ser una rama que las contiene todas y que se abre como sub-rueda. Un menú que dejara caer su cola sería un menú que miente sobre lo que ofrece.
Estrechar la corona suele salir a cuenta: cuatro ramas anchas se apuntan más deprisa que ocho estrechas.
Propiedades #
| Propiedad | Tipo | Predeterminado | Función |
|---|---|---|---|
ii_max_sectors | integer | 8 | Cuántas ramas puede llevar una corona (3 a 12). Lo que sobra pasa bajo una última rama que se abre como sub-rueda. Por encima de ocho, la rueda se compacta (icono más pequeño, etiqueta en una línea) para que las etiquetas no se solapen |
is_theme_style | string | "" | Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio |
is_theme_mode | string | "" | Variante clara u oscura (constantes THEME_MODE_*); vacío = la de la aplicación, seguida en cada cambio |
il_theme_accent | long | -1 | Color de acento de este componente (-1 = acento de la aplicación, o el del tema) |
Métodos #
| Método | Función | |
|---|---|---|
of_add_item (string as_keys, string as_text) | Añade una rama en su dirección: format/strike cuelga bajo Format, que debe existir ya. Esa misma dirección vuelve en ue_item_selected cuando se elige. Devuelve 0 una vez añadida, -5 si la dirección se rechaza (padre no encontrado, dirección ya ocupada, nivel vacío como export/ o /pdf, clave que contiene ` | o empieza por __), -2` si el componente no está creado |
of_add_item (string as_keys, string as_text, string as_image, boolean ab_checked) | Lo mismo, con el icono y la marca — el icono como tercer argumento, como en todo el resto de la biblioteca. Una rama se atenúa mediante su manejador: of_item(keys).ib_enabled = false. Devuelve 0 una vez añadida, -5 si la dirección se rechaza (padre no encontrado, dirección ya ocupada, nivel vacío como export/ o /pdf, clave que contiene ` | o empieza por __), -2` si el componente no está creado |
of_clear ( ) | Vacía la rueda y libera los manejadores obtenidos con of_item (cada uno designaba una rama que ya no existe). Devuelve 0 una vez aplicado, -2 si el componente no está creado | |
of_close ( ) | Cierra la rueda del componente si está en pantalla, sin elección: ue_dismissed se lanza en el acto, como con un clic fuera — incluso para una rueda pedida un instante antes y aún no dibujada — y of_is_open responde falso en cuanto vuelve. Nada abierto, no pasa nada. Devuelve 0 una vez hecho, -2 si el componente no está creado | |
of_is_open ( ) | true mientras una rueda del componente está en pantalla — abierta, y aún no respondida por una elección o un cierre. of_show y of_close se aplican antes de volver: responde verdadero justo después de of_show, falso justo después de of_close | |
long of_show ( ) | Abre la rueda centrada en el cursor. Llámelo desde el clic derecho del control que recibe el gesto. Una rueda sin ninguna rama visible no se abre: se lanza ue_dismissed. Una rueda aún en pantalla se sustituye: lanza primero ue_dismissed. Devuelve 0 una vez solicitado, -2 si el componente no está creado | |
long of_show (long al_x, long al_y) | Lo mismo, centrada en una posición de pantalla en píxeles. Unas coordenadas negativas son un punto real, (-1, -1) incluido: una pantalla situada a la izquierda o por encima de la principal. Devuelve 0 una vez solicitado, -2 si el componente no está creado | |
long of_show_over (dragobject ado_control) | Abre la rueda centrada en un control — una imagen, un campo, un botón de barra de herramientas —, esté donde esté el ratón. Devuelve 0 una vez solicitado, -5 si el control no es válido, -2 si el componente no está creado | |
long of_show_over (dragobject ado_control, boolean ab_keyboard) | Igual, diciendo cómo se pidió la rueda: ab_keyboard a verdadero cuando el usuario la abrió con el teclado (tecla Menú, Mayús+F10) — su primera rama que responde queda encendida, Intro la elige. Devuelve 0 una vez solicitado, -5 si el control no es válido, -2 si el componente no está creado | |
of_item (string as_keys) | Devuelve el manejador de una rama, por su dirección, para modificarla después (etiqueta, estado, colores). Una clave sola se resuelve en la dirección completa de la única rama que la lleva: of_item("csv") y of_item("import/csv") devuelven entonces el mismo manejador. Ambigua, o sin ninguna rama que la lleve, devuelve un manejador que no cambia nada en lugar de la rama equivocada. of_key() del manejador devuelve la clave del último nivel | |
of_remove_item (string as_keys) | Quita una rama y su sub-rueda; las demás se quedan. Una clave suelta se resuelve como lo hace of_item. La rueda en pantalla solo se cierra (ue_dismissed) si mostraba esa rama: quitar una oculta la deja abierta. Devuelve 0 una vez quitada, -5 si ninguna rama vive en esa dirección, -2 si el componente no está creado | |
of_reset ( ) | Vacía la rueda y devuelve todas las propiedades a su valor de origen. Devuelve 0 una vez aplicado, -2 si el componente no está creado |
Eventos #
| Evento | Se dispara cuando |
|---|---|
ue_item_selected (string as_keys) | El usuario ha elegido una rama. as_keys es su dirección completa (export/pdf), no la clave de la hoja sola. Un solo evento por gesto: un doble clic elige una sola vez |
ue_dismissed ( ) | La rueda se cerró sin que se eligiera ninguna rama: clic en el cubo, clic fuera de la rueda, Escape en la raíz — o por el código: of_close, of_clear, of_reset, of_remove_item de una rama que mostraba, un segundo of_show que la sustituye, un of_show que no tenía nada que mostrar. Una vez por apertura, en el acto: of_is_open ya responde falso |
Un clic en una esquina de la ventana, fuera del disco, cuenta como un clic fuera: la rueda se cierra (
ue_dismissed) y el clic pasa a la aplicación de detrás, en lugar de ser tragado por un cuadrado invisible.
Propiedades de elemento #
| Propiedad | Tipo | Predeterminado | Función |
|---|---|---|---|
is_text | string | "" | Etiqueta de la rama. Manténgala corta: un sector es una porción, no una línea, y muestra dos líneas como máximo — la rama señalada muestra su etiqueta entera. Vacía, se muestra la clave |
ib_enabled | boolean | true | A falso, la rama queda atenuada y su sector ignora todo clic. Se relee tal como lo puso: una rama atenuada por no tener ninguna subentrada visible sigue releyendo verdadero |
ib_visible | boolean | true | A falso, la rama sale de la rueda — subrueda incluida — sin ser eliminada; los sectores se cierran, y vuelve tal cual. Una rama cuyas subentradas están todas ocultas se queda en la rueda, atenuada: ya no tiene nada que abrir y no se elige como una hoja |
ib_checked | boolean | false | A verdadero, un arco fino bajo la banda marca la rama como activa |
is_image | string | "" | El icono de la rama, cambiado en su sitio — un Reproducir que se vuelve Pausa. "" lo quita. Las mismas rutas que of_add_item (mono:, tint:, archivo.dll:NOMBRE) |
is_tone | string | "" | El tono del comando: su etiqueta coloreada por el tema, claro u oscuro, en reposo — u_pbt_radialmenu.TONE_DANGER para el que destruye, TONE_WARN, TONE_SUCCESS, TONE_INFO. "" o TONE_NEUTRAL = el texto del tema; un color propio (il_text_color) prevalece |
is_group | string | "" | Un grupo de opción: las ramas de un mismo grupo bajo el mismo padre se excluyen — marcar una (ib_checked = true, o la elección del usuario, antes de ue_item_selected) desmarca las demás. "" = una rama ordinaria |
il_accent | long | -1 | Acento de esta rama: su banda cuando está señalada, y su marca (-1 = el del componente) |
il_back_color | long | -1 | Banda de esta rama en reposo (-1 = la del tema) |
il_text_color | long | -1 | Color de la etiqueta de esta rama (-1 = el del tema) |
il_back_color_hover | long | -1 | Porción de esta rama mientras está señalada (-1 = la del tema). Dada sin il_text_color_hover, recibe un texto legible encima |
il_text_color_hover | long | -1 | Color de la etiqueta de esta rama mientras está señalada (-1 = el del tema) |
Una rama no muestra ninguna información sobre herramientas: la ventana redonda no tiene sitio fuera del disco. El is_tooltip heredado por el manejador se conserva y se relee, pero nunca se muestra — es la rama señalada la que muestra su etiqueta entera.
Ejemplos #
Una rueda por contexto #
// Una rueda montada para lo que esta bajo el cursor
uo_wheel.of_clear()
uo_wheel.of_add_item(/*keys*/ "bold", /*text*/ "Bold", /*image*/ "mono:img\packimages.dll:svg/samples/bold", /*checked*/ true)
uo_wheel.of_add_item(/*keys*/ "find", /*text*/ "Find", /*image*/ "mono:img\packimages.dll:svg/samples/find", /*checked*/ false)
Reaccionar a la ruta elegida #
// Evento ue_item_selected del menu radial
// as_keys lleva la ruta completa, p. ej. "export/pdf"
choose case as_keys
case "export/pdf"
of_export_pdf()
case "delete"
of_delete_selection()
end choose
Marcar, atenuar, estrechar #
// Mark a branch as being on
uo_wheel.of_item(/*keys*/ "bold").ib_checked = true
// Grey out the one that makes no sense here
uo_wheel.of_item(/*keys*/ "paste").ib_enabled = false
// Cuatro ramas como maximo en una corona
uo_wheel.ii_max_sectors = 4
Con el teclado, y cerrada por el código #
// Tecla Menu en la rejilla: la rueda se abre centrada en ella, primera rama encendida
uo_wheel.of_show_over(/*control*/ dw_orders, /*keyboard*/ true)
// Mas tarde, desde un temporizador: la rueda se cierra sin eleccion (ue_dismissed)
if uo_wheel.of_is_open() then uo_wheel.of_close()
Un grupo de opción, un comando que destruye #
// Tres ramas exclusivas: elegir una desmarca las otras dos
uo_wheel.of_item(/*keys*/ "align/left").is_group = "align"
uo_wheel.of_item(/*keys*/ "align/center").is_group = "align"
uo_wheel.of_item(/*keys*/ "align/right").is_group = "align"
// Delete toma el tono del peligro, claro u oscuro
uo_wheel.of_item(/*keys*/ "delete").is_tone = u_pbt_radialmenu.TONE_DANGER
Buenas prácticas #
- Abra al SOLTAR el clic derecho del control, nunca al pulsar. Es lo que separa abrir de elegir, y el usuario necesita ambas cosas.
- Etiquetas cortas. Una o dos palabras. El sector está para la dirección; el texto entero solo se lee al señalar la rama.
- De cuatro a seis ramas superan a ocho. Una rueda se recuerda por la posición; cuantas menos posiciones, antes se aprenden.
- Ponga los comandos más frecuentes arriba y abajo. Son las dos direcciones que la mano alcanza sin pensar.
- Mantenga el orden estable de una apertura a otra: todo el interés de una rueda es que el gesto acabe precediendo a la lectura.
- Un menú radial no sustituye a un menú de lista. Veinte comandos raros se leen mejor en una lista; reserve la rueda para el puñado que se usa sin parar.
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.
| Miembros | Función | Detallado en |
|---|---|---|
of_count · of_keys_at · of_has | Recorrer lo que el componente contiene | 3.2 Los items |
of_reset | Poner el componente a cero | 3.6 Poner un componente a cero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atajos de teclado del componente | 3.5 Los atajos de teclado |
of_is_created · of_is_ready · of_get_last_error | Si ha nacido, si está listo, qué ha fallado | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar el render como imagen | 3.8 Exportar la representación como imagen |
of_set_redraw | Agrupar los cambios en un solo repintado | 3.10 Buenas prácticas |
of_preload_icons | Iconos mostrados sin retardo | Visualización instantánea: of_icon |
of_set_translation | Traducir una etiqueta del componente | 5.2 Adaptar una etiqueta: of_set_translation |
of_focus_webview | Dar el foco al componente | 6.4 Teclado y foco |
of_print · of_print_to_pdf | Imprimir, o escribir un PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar una propiedad por su nombre | 3.1 El motor de propiedades |
is_accessible_name · is_accessible_description | El nombre y la descripción que dice un lector de pantalla | 3.4 Propiedades y eventos opcionales |
En este lanzador invisible, of_count y of_keys_at recorren lo que usted ha añadido, ramas ocultas incluidas — no lo que la rueda dibujará. La exportación como imagen, la impresión, of_focus_webview y of_set_redraw no tienen aquí ningún efecto útil: el componente no dibuja nada propio, la rueda vive en su propia ventana.
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.