# tilesbox — `u_pbt_tilesbox` #

← Referência dos componentes · Índice do guia

> Painel de mosaicos agrupados ao estilo de um ecrã inicial: quatro tamanhos de mosaico, cores, emblemas, mosaicos animados, grupos recolhíveis e reorganização com o rato.

> ▶ Ver ao vivo — Aplicação de demonstração, mosaico Tiles box: a pré-visualização, o código que o produz e esta página, lado a lado.

## Em resumo #

Userobject | `u_pbt_tilesbox`
Classes de items | `n_pbt_tilesbox_group` (grupo) → `n_pbt_tilesbox_tile` (mosaico)
Serve para | Oferecer um ecrã inicial ou um lançador de funções: mosaicos clicáveis, legíveis à distância, arrumados por tema
Opções opt-in | —

## Início rápido #

    // event open da janela
    n_pbt_tilesbox_group lnv_grp

    // of_add_group devolve o handle do grupo: e nele que se penduram os mosaicos
    lnv_grp = uo_tuiles.of_add_group(/*group_id*/ "gestion", /*title*/ "Gestão")

    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*/ "Faturas",  /*icon_file*/ "mono:img\factures.svg",  /*size*/ "medium")
    lnv_grp.of_add_tile(/*id*/ "stock",     /*label*/ "Stock",    /*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

## O modelo: grupos e mosaicos #

O painel contém grupos, cada um com o seu título e o seu cabeçalho recolhível. Os mosaicos pertencem a um grupo: o respetivo identificador só é único dentro desse grupo. O acesso passa, portanto, sempre pelo caminho completo, e as adições vivem no handle do grupo.

    // Caminho obrigatorio: grupo e depois mosaico
    uo_tuiles.of_group("gestion").of_tile("factures").is_badge = "12"

Os eventos transportam igualmente o caminho completo (`as_group` seguido de `as_id`). Ver Base comum · Os items.

## Propriedades #

Propriedade | Tipo | Predefinição | Função
--- | --- | --- | ---
`ib_reorderable` | boolean | `false` | Autoriza o utilizador a deslocar os mosaicos com o rato (aciona `ue_tile_moved`)
`is_scroll` | string | `SCROLL_VERTICAL` | Sentido de deslocamento: `SCROLL_VERTICAL` (os mosaicos mudam de linha) ou `SCROLL_HORIZONTAL` (colunas ao estilo de um ecrã inicial)
`ib_show_group_headers` | boolean | `true` | `false` oculta os cabeçalhos de grupo. Útil quando o painel contém um único grupo: não há nada a nomear e o cabeçalho apenas consome altura. Sem cabeçalho deixa de haver galão: os grupos apresentam-se sempre expandidos
`ii_anim_duration` | integer | `180` | Duração em milissegundos da animação de recolher / expandir um grupo; `0` = instantâneo
`ii_tile_unit` | integer | `0` | Tamanho base de um mosaico, em pixels: cada formato (pequeno, médio, largo, grande) é um múltiplo dele, pelo que um valor torna todo o quadro mais denso ou mais arejado. `0` devolve-o ao tema
`ii_badge_size` | integer | `0` | Altura dos emblemas dos mosaicos em píxeis, para toda a caixa (`0` = o tamanho que vem do tema). O tamanho da letra acompanha sozinho. A cor de um emblema pertence ao mosaico porque significa alguma coisa; o seu tamanho não
`is_theme_style` | string | `fluent` | Estilo visual do componente (constantes `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante clara ou escura (constantes `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Cor de destaque deste componente (`-1` = destaque do tema)
`is_tooltip` | string | `""` | Tooltip simples apresentado ao passar sobre o componente
`is_super_tooltip_title` | string | `""` | Título do tooltip enriquecido (prevalece sobre `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Texto do tooltip enriquecido (aceita marcação enriquecida)
`is_super_tooltip_image` | string | `""` | Imagem do tooltip enriquecido

## Métodos #

Método | Função
--- | ---
`of_group (string as_id)` → `n_pbt_tilesbox_group` | Devolve o handle de um grupo (criado no primeiro acesso)
`of_add_group (string as_group_id, string as_title)` → `n_pbt_tilesbox_group` | Adiciona um grupo e devolve o respetivo handle
`of_remove_group (string as_id)` | Elimina um grupo e todos os seus mosaicos
`of_insert_tile (string as_group, string as_id, string as_text, integer ai_index)` | Insere um mosaico numa posição precisa dentro do seu grupo (posição 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)` | Idem, com o ícone e o tamanho (`small` / `medium` / `wide` / `large`): um mosaico é uma imagem com uma etiqueta por baixo, e o seu tamanho vê-se na grelha
`of_move_tile (string as_group, string as_id, integer ai_index)` | Desloca um mosaico existente para outra posição do seu grupo, conservando o respetivo estado
`of_remove_tile (string as_group, string as_id)` | Elimina um único mosaico, o resto do painel é preservado
`of_clear ( )` | Esvazia o painel (grupos e mosaicos)
`of_get_layout ( )` | Relê a disposição atual em JSON: grupos, mosaicos, ordem e tamanhos. Guarde-a e devolva-a com `of_set_layout`
`of_set_layout (string as_state_json)` | Repõe uma disposição lida com `of_get_layout` ou recebida com `ue_layout_changed`
`of_reset ( )` | Esvazia o conteúdo e repõe as propriedades na respetiva predefinição

### Num grupo — `n_pbt_tilesbox_group` #

Membro | Tipo | Predefinição | Função
--- | --- | --- | ---
`is_title` | string | `""` | Título apresentado no cabeçalho, formatação com etiquetas aceite
`ib_collapsed` | boolean | `false` | Grupo recolhido: os seus mosaicos ficam ocultos sob o cabeçalho
`ib_enabled` | boolean | `true` | Grupo inteiro esbatido e inerte
`ib_visible` | boolean | `true` | Grupo oculto, sem ser eliminado do modelo
`of_tile (string as_id)` → `n_pbt_tilesbox_tile` |  |  | Devolve o handle de um mosaico deste grupo
`of_add_tile (as_id, as_label, as_icon_file, as_size)` → `n_pbt_tilesbox_tile` |  |  | Adiciona um mosaico a este grupo e devolve o respetivo handle

### Num mosaico — `n_pbt_tilesbox_tile` #

Membro | Tipo | Predefinição | Função
--- | --- | --- | ---
`is_size` | string | `SIZE_MEDIUM` | Tamanho: `SIZE_SMALL`, `SIZE_MEDIUM`, `SIZE_WIDE`, `SIZE_LARGE`
`il_back_color` · `il_text_color` | long | `-1` | Fundo e texto deste mosaico, como `RGB(r,g,b)` (`-1` = o que o tema der)
`il_back_color_hover` · `il_text_color_hover` | long | `-1` | Os mesmos dois, mas sob o ponteiro
`is_badge` | string | `""` | Emblema apresentado no canto do mosaico (um contador, um estado curto)
`il_badge_color` | long | `0` | Fundo do emblema, em RGB do PowerBuilder (`0` = a cor que vem do tema)
`is_live_text` | string | `""` | Texto sobreposto ao mosaico, formatação com etiquetas aceite
`ib_enabled` | boolean | `true` | Mosaico esbatido e não clicável
`ib_visible` | boolean | `true` | Mosaico oculto, sem ser retirado do seu grupo
`of_add_live_item (string as_text)` |  |  | Adiciona uma face à faixa animada; a partir de duas faces, o mosaico fá-las desfilar
`of_clear_live_items ( )` |  |  | Esvazia a faixa animada: o mosaico deixa de desfilar

Os ícones aceitam todas as formas reconhecidas pela biblioteca: caminho, `mono:`, `tint:`, recurso de DLL. Num mosaico grande, é preferível uma imagem nítida em alta definição ou um SVG.

## Os quatro tamanhos #

Tamanho | Espaço ocupado | Utilização típica
--- | --- | ---
`small` | 1 célula | Atalho secundário; a etiqueta não é apresentada, o tooltip assume esse papel
`medium` | 2 × 2 células | Tamanho de referência: ícone e etiqueta
`wide` | 4 × 2 células | Mosaico alongado, ideal para um texto animado
`large` | 4 × 4 células | Mosaico de destaque do ecrã

## Eventos #

Evento | Acionado quando
--- | ---
`ue_tile_clicked (string as_group, string as_id)` | Um mosaico é clicado
`ue_tile_moved (string as_group, string as_id, string as_to_group, long al_index)` | Um mosaico foi deslocado: `as_group` é o grupo de origem, `as_to_group` o grupo de destino, `al_index` a nova posição
`ue_group_toggled (string as_group, boolean ab_collapsed)` | Um grupo é recolhido ou expandido a partir do seu cabeçalho
`ue_tile_context (string as_group, string as_id)` | Clique com o botão direito num mosaico
`ue_tile_resized (string as_group, string as_id, string as_size)` | O tamanho de um mosaico mudou; `as_size` transporta o novo tamanho
`ue_layout_changed (string as_layout_json)` | A disposição mudou — o utilizador moveu ou redimensionou um mosaico. Transporta a disposição inteira, não apenas o que se moveu
`ue_ready ( )` | O componente terminou o carregamento; tudo o que foi enviado antes foi reproduzido
`ue_runtime_missing ( )` | O runtime WebView2 está ausente: o componente permanece vazio
`ue_bg_color (long al_color)` | O componente calculou a cor de fundo do respetivo tema; o userobject já a adotou (`backcolor`)

## Exemplos #

### Tamanhos misturados num mesmo grupo #

    n_pbt_tilesbox_group lnv_grp

    uo_tuiles.of_clear()
    lnv_grp = uo_tuiles.of_add_group(/*group_id*/ "accueil", /*title*/ "Início")

    lnv_grp.of_add_tile(/*id*/ "tableau", /*label*/ "Painel de controlo", /*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*/ "Ajuda",              /*icon_file*/ "mono:img\help.svg",   /*size*/ "small")

### Emblema, cor e mosaico animado #

    n_pbt_tilesbox_tile lnv_tuile

    // Um emblema assinala um numero de elementos em espera
    uo_tuiles.of_group("accueil").of_tile("clients").is_badge = String(ll_nouveaux)

    // Vermelho quando o atraso se torna critico, cor do tema 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

    // Uma cor propria destaca um mosaico : fundo, texto e aquilo em que cada um
    // se torna sob o ponteiro
    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 face adicionada desfila a sua vez no 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 reuniões hoje")
    lnv_tuile.of_add_live_item(/*text*/ "Reunião de equipa às 14h00")
    lnv_tuile.of_add_live_item(/*text*/ "2 lembretes em atraso")

### Um texto fixo em vez de um desfile #

    // is_live_text coloca UM texto permanente no mosaico (formatacao com etiquetas aceite)
    uo_tuiles.of_group("accueil").of_tile("tableau").is_live_text = "[b]48[/b] encomendas do dia"

### Grupos recolhíveis #

    n_pbt_tilesbox_group lnv_admin

    lnv_admin = uo_tuiles.of_add_group(/*group_id*/ "admin", /*title*/ "Administração")
    lnv_admin.of_add_tile(/*id*/ "users",  /*label*/ "Utilizadores", /*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 comeca recolhido: o utilizador abre-o se precisar
    lnv_admin.ib_collapsed = true

    // Um grupo inteiro pode tambem ser esbatido consoante os direitos
    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("Abertura do painel de administração")

### Um painel de grupo único, sem cabeçalho #

    // Um so grupo nao tem nada a nomear: o seu cabecalho apenas consome altura.
    // Sem cabecalho, tambem deixa de haver galao: os mosaicos ficam sempre visiveis.
    uo_tuiles.ib_show_group_headers = false
    uo_tuiles.of_add_group(/*group_id*/ "tout", /*title*/ "")

### Deslocar um mosaico entre dois grupos #

Com `ib_reorderable = true`, o utilizador arrasta um mosaico para onde quiser, incluindo de um grupo para outro. O evento `ue_tile_moved` fornece os dois grupos e a nova posição.

    uo_tuiles.ib_reorderable = true    // false por omissao : e preciso pedir

    // event ue_tile_moved de uo_tuiles
    // as_group = grupo de origem, as_to_group = grupo de destino, al_index = posicao
    if as_group <> as_to_group then
        of_tracer("Mosaico " + as_id + " deslocado de " + as_group + " para " + as_to_group)
    end if
    uo_tuiles.of_get_layout()    // solicitar a disposicao para a conservar

    // event ue_layout_changed de uo_tuiles: conservar a disposicao escolhida
    is_disposition = as_layout_json

    // Na abertura seguinte: repor o ecra tal como o utilizador o tinha arrumado
    if is_disposition <> "" then uo_tuiles.of_set_layout(is_disposition)

Para fixar o ecrã, basta desativar a reorganização:

    uo_tuiles.ib_reorderable = false

### Reorganizar a partir do código #

    // Colocar o mosaico "aide" no inicio do seu grupo (posicoes contadas a partir de 0)
    uo_tuiles.of_move_tile(/*group*/ "accueil", /*id*/ "aide", /*index*/ 0)

    // Inserir um novo mosaico na segunda posicao
    uo_tuiles.of_insert_tile(/*group*/ "accueil", /*id*/ "devis", /*text*/ "Orçamentos", /*index*/ 1)

    // Retirar um mosaico sem mexer no resto
    uo_tuiles.of_remove_tile(/*group*/ "accueil", /*id*/ "aide")

### Reagir ao clique com o botão direito #

    // event ue_tile_context de uo_tuiles: (as_group, as_id)
    // Reter o mosaico visado e abrir em seguida o seu proprio menu contextual
    is_groupe_vise = as_group
    is_tuile_visee = as_id
    of_ouvrir_menu_tuile(PointerX(), PointerY())

## Boas práticas #

- Um único mosaico `large` por ecrã é suficiente: é o ponto de entrada principal, o resto deve manter-se legível.
- Os mosaicos `small` não apresentam a sua etiqueta — o tooltip do item deve ser preenchido sistematicamente.
- `il_back_color` deve ser reservado aos mosaicos que precisam de sobressair: para além de duas ou três cores, o ecrã perde a sua hierarquia. E se puser um fundo claro, ponha também `il_text_color` — o texto do tema não é garantidamente legível por cima.
- É preferível `of_add_live_item` (desfile) a `is_live_text` (texto fixo) quando há várias informações a transmitir no mesmo mosaico.
- Se a reorganização for deixada ativa, a disposição deve ser conservada através de `of_get_layout` / `ue_layout_changed` e `of_set_layout` reexecutado na abertura.
- Devem utilizar-se `ib_visible` e `ib_enabled` (grupo ou mosaico) para adaptar o painel aos direitos do utilizador, em vez de o reconstruir.
- Quando falta espaço para mosaicos, é preferível a navegação lateral compacta da listbar; para as ações frequentes, a toolbar.

← Referência dos componentes · Índice do guia