# tilesbox — `u_pbt_tilesbox` #

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

> Panel de mosaicos agrupados al estilo de una pantalla de inicio: cuatro tamaños de mosaico, colores, distintivos, mosaicos animados, grupos plegables y reorganización con el ratón.

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

## De un vistazo #

Userobject | `u_pbt_tilesbox`
Clases de items | `n_pbt_tilesbox_group` (grupo) → `n_pbt_tilesbox_tile` (mosaico)
Sirve para | Ofrecer una pantalla de inicio o un lanzador de funciones: mosaicos en los que se puede hacer clic, legibles desde lejos, ordenados por tema
Opciones opt-in | —

## Inicio rápido #

    // event open de la ventana
    n_pbt_tilesbox_group lnv_grp

    // of_add_group devuelve el handle del grupo: en el se enganchan sus mosaicos
    lnv_grp = uo_tuiles.of_add_group(/*group_id*/ "gestion", /*title*/ "Gestión")

    lnv_grp.of_add_tile(/*id*/ "clients",   /*label*/ "Clientes",   /*icon_file*/ "mono:img\clients.svg",   /*size*/ "medium")
    lnv_grp.of_add_tile(/*id*/ "factures",  /*label*/ "Facturas",  /*icon_file*/ "mono:img\factures.svg",  /*size*/ "medium")
    lnv_grp.of_add_tile(/*id*/ "stock",     /*label*/ "Almacén",     /*icon_file*/ "mono:img\stock.svg",     /*size*/ "small")

    // event ue_tile_clicked de uo_tuiles: (string as_group, string as_id)
    choose case as_group + "/" + as_id
        case "gestion/clients"  ; open(w_clients)
        case "gestion/factures" ; open(w_factures)
        case "gestion/stock"    ; open(w_stock)
    end choose

## El modelo: grupos y mosaicos #

El panel contiene grupos, cada uno con su título y su encabezado plegable. Los mosaicos pertenecen a un grupo: su identificador solo es único dentro de ese grupo. El acceso pasa por tanto siempre por la ruta completa, y las adiciones viven en el handle del grupo.

    // Ruta obligatoria: grupo y luego mosaico
    uo_tuiles.of_group("gestion").of_tile("factures").is_badge = "12"

Los eventos también llevan la ruta completa (`as_group` y luego `as_id`). Véase Base común · Los items.

## Propiedades #

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`ib_reorderable` | boolean | `false` | Permite al usuario mover los mosaicos con el ratón (activa `ue_tile_moved`)
`is_scroll` | string | `SCROLL_VERTICAL` | Sentido de desplazamiento: `SCROLL_VERTICAL` (los mosaicos pasan a la línea siguiente) o `SCROLL_HORIZONTAL` (columnas al estilo de una pantalla de inicio)
`ib_show_group_headers` | boolean | `true` | `false` oculta los encabezados de grupo. Resulta útil cuando el panel contiene un solo grupo: no hay nada que nombrar y el encabezado se limita a consumir altura. Sin encabezado ya no hay galón: los grupos se muestran siempre desplegados
`ii_anim_duration` | integer | `180` | Duración en milisegundos de la animación de plegado / desplegado de un grupo; `0` = instantánea
`ii_tile_unit` | integer | `0` | Tamaño base de un mosaico, en píxeles: cada formato (pequeño, mediano, ancho, grande) es un múltiplo suyo, de modo que un valor hace todo el tablero más denso o más aireado. `0` lo devuelve al tema
`ii_badge_size` | integer | `0` | Altura de los distintivos de mosaico en píxeles, para toda la caja (`0` = el tamaño que viene del tema). El tamaño de la fuente se ajusta solo. El color de un distintivo pertenece al mosaico porque significa algo; su tamaño no
`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

## Métodos #

Método | Función
--- | ---
`of_group (string as_id)` → `n_pbt_tilesbox_group` | Devuelve el handle de un grupo (creado en el primer acceso)
`of_add_group (string as_group_id, string as_title)` → `n_pbt_tilesbox_group` | Añade un grupo y devuelve su handle
`of_remove_group (string as_id)` | Elimina un grupo y todos sus mosaicos
`of_insert_tile (string as_group, string as_id, string as_text, integer ai_index)` | Inserta un mosaico en una posición precisa dentro de su grupo (posición contada a partir de 0)
`of_insert_tile (string as_group, string as_id, string as_text, string as_image, string as_size, integer ai_index)` | Ídem, con el icono y el tamaño (`small` / `medium` / `wide` / `large`): un mosaico es una imagen con una etiqueta debajo, y su tamaño se ve en la cuadrícula
`of_move_tile (string as_group, string as_id, integer ai_index)` | Mueve un mosaico existente a otra posición de su grupo, conservando su estado
`of_remove_tile (string as_group, string as_id)` | Elimina un solo mosaico, el resto del panel se conserva
`of_clear ( )` | Vacía el panel (grupos y mosaicos)
`of_get_layout ( )` | Vuelve a leer la disposición actual en JSON: grupos, mosaicos, orden y tamaños. Guárdela y devuélvala con `of_set_layout`
`of_set_layout (string as_state_json)` | Restaura una disposición leída con `of_get_layout` o recibida con `ue_layout_changed`
`of_reset ( )` | Vacía el contenido y devuelve las propiedades a sus valores predeterminados

### En un grupo — `n_pbt_tilesbox_group` #

Miembro | Tipo | Predeterminado | Función
--- | --- | --- | ---
`is_title` | string | `""` | Título mostrado en el encabezado, se acepta texto enriquecido con etiquetas
`ib_collapsed` | boolean | `false` | Grupo plegado: sus mosaicos quedan ocultos bajo el encabezado
`ib_enabled` | boolean | `true` | Grupo entero atenuado e inerte
`ib_visible` | boolean | `true` | Grupo oculto, sin eliminarlo del modelo
`of_tile (string as_id)` → `n_pbt_tilesbox_tile` |  |  | Devuelve el handle de un mosaico de este grupo
`of_add_tile (as_id, as_label, as_icon_file, as_size)` → `n_pbt_tilesbox_tile` |  |  | Añade un mosaico a este grupo y devuelve su handle

### En un mosaico — `n_pbt_tilesbox_tile` #

Miembro | Tipo | Predeterminado | Función
--- | --- | --- | ---
`is_size` | string | `SIZE_MEDIUM` | Tamaño: `SIZE_SMALL`, `SIZE_MEDIUM`, `SIZE_WIDE`, `SIZE_LARGE`
`il_back_color` · `il_text_color` | long | `-1` | Fondo y texto de este mosaico, como `RGB(r,g,b)` (`-1` = lo que da el tema)
`il_back_color_hover` · `il_text_color_hover` | long | `-1` | Los dos mismos, pero bajo el puntero
`is_badge` | string | `""` | Distintivo mostrado en la esquina del mosaico (un contador, un estado breve)
`il_badge_color` | long | `0` | Fondo del distintivo, en RGB de PowerBuilder (`0` = el color que viene del tema)
`is_live_text` | string | `""` | Texto superpuesto al mosaico, se acepta texto enriquecido con etiquetas
`ib_enabled` | boolean | `true` | Mosaico atenuado y no clicable
`ib_visible` | boolean | `true` | Mosaico oculto, sin retirarlo de su grupo
`of_add_live_item (string as_text)` |  |  | Añade una cara a la banda animada; a partir de dos caras, el mosaico las hace desfilar
`of_clear_live_items ( )` |  |  | Vacía la banda animada: el mosaico deja de desfilar

Los iconos aceptan todas las formas reconocidas por la biblioteca: ruta, `mono:`, `tint:`, recurso de DLL. En un mosaico grande, es preferible una imagen nítida en alta definición o un SVG.

## Los cuatro tamaños #

Tamaño | Espacio ocupado | Uso habitual
--- | --- | ---
`small` | 1 casilla | Acceso directo secundario; la etiqueta no se muestra, el tooltip toma el relevo
`medium` | 2 × 2 casillas | Tamaño de referencia: icono y etiqueta
`wide` | 4 × 2 casillas | Mosaico alargado, ideal para un texto animado
`large` | 4 × 4 casillas | Mosaico protagonista de la pantalla

## Eventos #

Evento | Se activa cuando
--- | ---
`ue_tile_clicked (string as_group, string as_id)` | Se hace clic en un mosaico
`ue_tile_moved (string as_group, string as_id, string as_to_group, long al_index)` | Se ha movido un mosaico: `as_group` es el grupo de origen, `as_to_group` el grupo de destino, `al_index` la nueva posición
`ue_group_toggled (string as_group, boolean ab_collapsed)` | Un grupo se pliega o se despliega desde su encabezado
`ue_tile_context (string as_group, string as_id)` | Clic derecho en un mosaico
`ue_tile_resized (string as_group, string as_id, string as_size)` | El tamaño de un mosaico ha cambiado; `as_size` lleva el nuevo tamaño
`ue_layout_changed (string as_layout_json)` | La disposición ha cambiado — el usuario ha movido o redimensionado un mosaico. Lleva la disposición entera, no solo lo que se movió
`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 #

### Tamaños mezclados en un mismo grupo #

    n_pbt_tilesbox_group lnv_grp

    uo_tuiles.of_clear()
    lnv_grp = uo_tuiles.of_add_group(/*group_id*/ "accueil", /*title*/ "Inicio")

    lnv_grp.of_add_tile(/*id*/ "tableau", /*label*/ "Cuadro de mando", /*icon_file*/ "mono:img\chart.svg",  /*size*/ "large")
    lnv_grp.of_add_tile(/*id*/ "clients", /*label*/ "Clientes",         /*icon_file*/ "mono:img\users.svg",  /*size*/ "medium")
    lnv_grp.of_add_tile(/*id*/ "agenda",  /*label*/ "Agenda",          /*icon_file*/ "mono:img\cal.svg",    /*size*/ "wide")
    lnv_grp.of_add_tile(/*id*/ "aide",    /*label*/ "Ayuda",            /*icon_file*/ "mono:img\help.svg",   /*size*/ "small")

### Distintivo, color y mosaico animado #

    n_pbt_tilesbox_tile lnv_tuile

    // Un distintivo senala un numero de elementos pendientes
    uo_tuiles.of_group("accueil").of_tile("clients").is_badge = String(ll_nouveaux)

    // Rojo cuando el retraso pasa a ser critico, color del tema en caso contrario (0)
    if ll_nouveaux > 50 then
        uo_tuiles.of_group("accueil").of_tile("clients").il_badge_color = RGB(200, 30, 30)
    else
        uo_tuiles.of_group("accueil").of_tile("clients").il_badge_color = 0
    end if

    // Un color propio destaca un mosaico : fondo, texto y lo que cada uno
    // pasa a ser bajo el puntero
    lnv_tuile = uo_tuiles.of_group("accueil").of_tile("tableau")
    lnv_tuile.il_back_color = RGB(0, 103, 192)
    lnv_tuile.il_back_color_hover = RGB(0, 80, 150)
    lnv_tuile.il_text_color = RGB(255, 255, 255)

    // Mosaico ANIMADO: cada cara anadida desfila por turno sobre el mosaico
    lnv_tuile = uo_tuiles.of_group("accueil").of_tile("agenda")
    lnv_tuile.of_clear_live_items()
    lnv_tuile.of_add_live_item(/*text*/ "3 citas hoy")
    lnv_tuile.of_add_live_item(/*text*/ "Reunión de equipo a las 14:00")
    lnv_tuile.of_add_live_item(/*text*/ "2 avisos con retraso")

### Un texto fijo en lugar de un desplazamiento #

    // is_live_text pone UN texto permanente sobre el mosaico (se acepta texto enriquecido con etiquetas)
    uo_tuiles.of_group("accueil").of_tile("tableau").is_live_text = "[b]48[/b] pedidos del día"

### Grupos plegables #

    n_pbt_tilesbox_group lnv_admin

    lnv_admin = uo_tuiles.of_add_group(/*group_id*/ "admin", /*title*/ "Administración")
    lnv_admin.of_add_tile(/*id*/ "users",  /*label*/ "Usuarios", /*icon_file*/ "mono:img\users.svg", /*size*/ "medium")
    lnv_admin.of_add_tile(/*id*/ "params", /*label*/ "Parámetros",   /*icon_file*/ "mono:img\gear.svg",  /*size*/ "medium")

    // Este grupo arranca plegado: el usuario lo abre si lo necesita
    lnv_admin.ib_collapsed = true

    // Un grupo entero tambien puede atenuarse segun los permisos
    lnv_admin.ib_enabled = (is_profil = "ADMIN")

    // event ue_group_toggled de uo_tuiles
    if as_group = "admin" and not ab_collapsed then of_tracer("Apertura del panel de administración")

### Un panel de grupo único, sin encabezado #

    // Un solo grupo no tiene nada que nombrar : su encabezado solo consume altura.
    // Sin encabezado, tampoco hay galon : los mosaicos permanecen siempre visibles.
    uo_tuiles.ib_show_group_headers = false
    uo_tuiles.of_add_group(/*group_id*/ "tout", /*title*/ "")

### Mover un mosaico entre dos grupos #

Con `ib_reorderable = true`, el usuario arrastra un mosaico a donde quiere, incluso de un grupo a otro. El evento `ue_tile_moved` entrega los dos grupos y la nueva posición.

    uo_tuiles.ib_reorderable = true    // false por defecto : hay que pedirlo

    // event ue_tile_moved de uo_tuiles
    // as_group = grupo de origen, as_to_group = grupo de destino, al_index = posicion
    if as_group <> as_to_group then
        of_tracer("Mosaico " + as_id + " movido de " + as_group + " a " + as_to_group)
    end if
    uo_tuiles.of_get_layout()    // solicitar la disposicion para conservarla

    // event ue_layout_changed de uo_tuiles: conservar la disposicion elegida
    is_disposition = as_layout_json

    // En la siguiente apertura: restituir la pantalla tal como el usuario la habia ordenado
    if is_disposition <> "" then uo_tuiles.of_set_layout(is_disposition)

Para fijar la pantalla, basta con desactivar la reorganización:

    uo_tuiles.ib_reorderable = false

### Reorganizar desde el código #

    // Colocar el mosaico "aide" al principio de su grupo (posiciones contadas a partir de 0)
    uo_tuiles.of_move_tile(/*group*/ "accueil", /*id*/ "aide", /*index*/ 0)

    // Insertar un nuevo mosaico en segunda posicion
    uo_tuiles.of_insert_tile(/*group*/ "accueil", /*id*/ "devis", /*text*/ "Presupuestos", /*index*/ 1)

    // Retirar un mosaico sin tocar el resto
    uo_tuiles.of_remove_tile(/*group*/ "accueil", /*id*/ "aide")

### Reaccionar al clic derecho #

    // event ue_tile_context de uo_tuiles: (as_group, as_id)
    // Retener el mosaico afectado y abrir despues su propio menu contextual
    is_groupe_vise = as_group
    is_tuile_visee = as_id
    of_ouvrir_menu_tuile(PointerX(), PointerY())

## Buenas prácticas #

- Basta con un mosaico `large` por pantalla: es el punto de entrada principal, el resto debe seguir siendo legible.
- Los mosaicos `small` no muestran su etiqueta — rellene sistemáticamente el tooltip del item.
- Reserve `il_back_color` para los mosaicos que deben destacar: más allá de dos o tres colores, la pantalla pierde su jerarquía. Y si pone un fondo claro, ponga también `il_text_color` — el texto del tema no está garantizado legible encima.
- Prefiera `of_add_live_item` (desplazamiento) a `is_live_text` (texto fijo) cuando tenga varias informaciones que transmitir en el mismo mosaico.
- Si deja activa la reorganización, conserve la disposición mediante `of_get_layout` / `ue_layout_changed` y vuelva a aplicar `of_set_layout` en la apertura.
- Utilice `ib_visible` e `ib_enabled` (grupo o mosaico) para adaptarlo a los permisos del usuario, en lugar de reconstruir el panel.
- Cuando falte espacio para los mosaicos, prefiera la navegación lateral compacta de listbar; para las acciones frecuentes, la toolbar.

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