# tilesbox — `u_pbt_tilesbox` #

← Component reference · Guide contents

> Panel of grouped tiles in home-screen style: four tile sizes, colors, badges, live tiles, collapsible groups and mouse rearranging.

> ▶ See it live — Demo application, Tiles box tile: the preview, the code behind it and this page, side by side.

## At a glance #

Userobject | `u_pbt_tilesbox`
Item classes | `n_pbt_tilesbox_group` (group) → `n_pbt_tilesbox_tile` (tile)
Used for | Offering a home screen or a feature launcher: clickable tiles, readable from a distance, arranged by topic
Opt-in options | —

## Quick start #

    // window open event
    n_pbt_tilesbox_group lnv_grp

    // of_add_group returns the handle of the group : you attach its tiles to it
    lnv_grp = uo_tuiles.of_add_group(/*group_id*/ "gestion", /*title*/ "Management")

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

    // ue_tile_clicked event of 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

## The model: groups and tiles #

The panel contains groups, each with its title and its collapsible header. Tiles belong to a group: their identifier is only unique within that group. Access therefore always goes through the full path, and additions live on the group handle.

    // Mandatory path : group then tile
    uo_tuiles.of_group("gestion").of_tile("factures").is_badge = "12"

Events carry the full path as well (`as_group` then `as_id`). See Shared foundation · Items.

## Properties #

Property | Type | Default | Purpose
--- | --- | --- | ---
`ib_reorderable` | boolean | `false` | Lets users move the tiles with the mouse (raises `ue_tile_moved`)
`is_scroll` | string | `SCROLL_VERTICAL` | Scrolling direction: `SCROLL_VERTICAL` (tiles wrap onto the next line) or `SCROLL_HORIZONTAL` (columns, home-screen style)
`ib_show_group_headers` | boolean | `true` | `false` hides the group headers. Handy when the panel holds only one group: there is nothing to name and the header just eats up height. Without a header there is no chevron either: the groups always show expanded
`ii_anim_duration` | integer | `180` | Duration in milliseconds of the collapse / expand animation of a group; `0` = instant
`ii_tile_unit` | integer | `0` | Base size of a tile, in pixels: every tile size (small, medium, wide, large) is a multiple of it, so one value makes the whole board denser or airier. `0` gives it back to the theme
`ii_badge_size` | integer | `0` | Tile badge height in pixels, for the whole box (`0` = the size that comes from the theme). The font size follows on its own. A badge color belongs to the tile because it carries a meaning; its size does not
`is_theme_style` | string | `fluent` | Visual style of the component (`THEME_STYLE_*` constants)
`is_theme_mode` | string | `light` | Light or dark variant (`THEME_MODE_*` constants)
`il_theme_accent` | long | `-1` | Accent color of this component (`-1` = the theme accent)
`is_tooltip` | string | `""` | Simple tooltip shown when hovering the component
`is_super_tooltip_title` | string | `""` | Title of the rich tooltip (takes precedence over `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Text of the rich tooltip (rich markup accepted)
`is_super_tooltip_image` | string | `""` | Image of the rich tooltip

## Methods #

Method | Purpose
--- | ---
`of_group (string as_id)` → `n_pbt_tilesbox_group` | Returns the handle of a group (created on first access)
`of_add_group (string as_group_id, string as_title)` → `n_pbt_tilesbox_group` | Adds a group and returns its handle
`of_remove_group (string as_id)` | Removes a group and all of its tiles
`of_insert_tile (string as_group, string as_id, string as_text, integer ai_index)` | Inserts a tile at a precise position within its group (position counted from 0)
`of_insert_tile (string as_group, string as_id, string as_text, string as_image, string as_size, integer ai_index)` | Same, with the icon and the size (`small` / `medium` / `wide` / `large`): a tile is a picture with a label under it, and its size shows in the grid
`of_move_tile (string as_group, string as_id, integer ai_index)` | Moves an existing tile to another position within its group, keeping its state
`of_remove_tile (string as_group, string as_id)` | Removes a single tile, the rest of the panel is preserved
`of_clear ( )` | Empties the panel (groups and tiles)
`of_get_layout ( )` | Reads the current arrangement back as JSON: groups, tiles, order and sizes. Store it, then hand it back with `of_set_layout`
`of_set_layout (string as_state_json)` | Restores an arrangement read with `of_get_layout` or received with `ue_layout_changed`
`of_reset ( )` | Clears the content and resets every property to its default

### On a group — `n_pbt_tilesbox_group` #

Member | Type | Default | Purpose
--- | --- | --- | ---
`is_title` | string | `""` | Title shown in the header, rich text markup accepted
`ib_collapsed` | boolean | `false` | Collapsed group: its tiles are hidden under the header
`ib_enabled` | boolean | `true` | Whole group grayed out and inert
`ib_visible` | boolean | `true` | Group hidden, without being removed from the model
`of_tile (string as_id)` → `n_pbt_tilesbox_tile` |  |  | Returns the handle of a tile of this group
`of_add_tile (as_id, as_label, as_icon_file, as_size)` → `n_pbt_tilesbox_tile` |  |  | Adds a tile to this group and returns its handle

### On a tile — `n_pbt_tilesbox_tile` #

Member | Type | Default | Purpose
--- | --- | --- | ---
`is_size` | string | `SIZE_MEDIUM` | Size: `SIZE_SMALL`, `SIZE_MEDIUM`, `SIZE_WIDE`, `SIZE_LARGE`
`il_back_color` · `il_text_color` | long | `-1` | Background and text of this tile, as `RGB(r,g,b)` (`-1` = whatever the theme gives)
`il_back_color_hover` · `il_text_color_hover` | long | `-1` | The same two, but under the pointer
`is_badge` | string | `""` | Badge shown in the corner of the tile (a counter, a short status)
`il_badge_color` | long | `0` | Badge background, as a PowerBuilder RGB value (`0` = the color that comes from the theme)
`is_live_text` | string | `""` | Text overlaid on the tile, rich text markup accepted
`ib_enabled` | boolean | `true` | Tile grayed out and not clickable
`ib_visible` | boolean | `true` | Tile hidden, without being removed from its group
`of_add_live_item (string as_text)` |  |  | Adds a face to the live banner; from two faces on, the tile cycles through them
`of_clear_live_items ( )` |  |  | Clears the live banner: the tile stops cycling

Icons accept every form recognized by the library: path, `mono:`, `tint:`, DLL resource. On a large tile, prefer a crisp high-resolution image or an SVG.

## The four sizes #

Size | Footprint | Typical use
--- | --- | ---
`small` | 1 cell | Secondary shortcut; the caption is not shown, the tooltip takes over
`medium` | 2 × 2 cells | Reference size: icon and caption
`wide` | 4 × 2 cells | Elongated tile, ideal for live text
`large` | 4 × 4 cells | Flagship tile of the screen

## Events #

Event | Raised when
--- | ---
`ue_tile_clicked (string as_group, string as_id)` | A tile is clicked
`ue_tile_moved (string as_group, string as_id, string as_to_group, long al_index)` | A tile has been moved: `as_group` is the source group, `as_to_group` the destination group, `al_index` the new position
`ue_group_toggled (string as_group, boolean ab_collapsed)` | A group is collapsed or expanded from its header
`ue_tile_context (string as_group, string as_id)` | Right-click on a tile
`ue_tile_resized (string as_group, string as_id, string as_size)` | The size of a tile has changed; `as_size` carries the new size
`ue_layout_changed (string as_layout_json)` | The arrangement changed — the user moved or resized a tile. Carries the whole layout, not just what moved
`ue_ready ( )` | The component has finished loading; everything sent beforehand has been replayed
`ue_runtime_missing ( )` | The WebView2 runtime is missing: the component stays empty
`ue_bg_color (long al_color)` | The component has computed its theme background color; the userobject has already adopted it (`backcolor`)

## Examples #

### Mixed sizes within a single group #

    n_pbt_tilesbox_group lnv_grp

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

    lnv_grp.of_add_tile(/*id*/ "tableau", /*label*/ "Dashboard", /*icon_file*/ "mono:img\chart.svg",  /*size*/ "large")
    lnv_grp.of_add_tile(/*id*/ "clients", /*label*/ "Customers",         /*icon_file*/ "mono:img\users.svg",  /*size*/ "medium")
    lnv_grp.of_add_tile(/*id*/ "agenda",  /*label*/ "Calendar",          /*icon_file*/ "mono:img\cal.svg",    /*size*/ "wide")
    lnv_grp.of_add_tile(/*id*/ "aide",    /*label*/ "Help",            /*icon_file*/ "mono:img\help.svg",   /*size*/ "small")

### Badge, color and live tile #

    n_pbt_tilesbox_tile lnv_tuile

    // A badge signals a number of pending items
    uo_tuiles.of_group("accueil").of_tile("clients").is_badge = String(ll_nouveaux)

    // Red when the backlog becomes critical, theme color otherwise (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

    // A dedicated color brings a tile forward : background, text, and what each
    // becomes under the pointer
    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)

    // LIVE tile : each face added cycles in turn on the tile
    lnv_tuile = uo_tuiles.of_group("accueil").of_tile("agenda")
    lnv_tuile.of_clear_live_items()
    lnv_tuile.of_add_live_item(/*text*/ "3 appointments today")
    lnv_tuile.of_add_live_item(/*text*/ "Team meeting at 2:00 PM")
    lnv_tuile.of_add_live_item(/*text*/ "2 overdue follow-ups")

### Fixed text rather than a cycling banner #

    // is_live_text puts ONE permanent text on the tile (rich text markup accepted)
    uo_tuiles.of_group("accueil").of_tile("tableau").is_live_text = "[b]48[/b] orders today"

### Collapsible groups #

    n_pbt_tilesbox_group lnv_admin

    lnv_admin = uo_tuiles.of_add_group(/*group_id*/ "admin", /*title*/ "Administration")
    lnv_admin.of_add_tile(/*id*/ "users",  /*label*/ "Users", /*icon_file*/ "mono:img\users.svg", /*size*/ "medium")
    lnv_admin.of_add_tile(/*id*/ "params", /*label*/ "Settings",   /*icon_file*/ "mono:img\gear.svg",  /*size*/ "medium")

    // This group starts collapsed : users open it if they need it
    lnv_admin.ib_collapsed = true

    // A whole group can also be grayed out according to permissions
    lnv_admin.ib_enabled = (is_profil = "ADMIN")

    // ue_group_toggled event of uo_tuiles
    if as_group = "admin" and not ab_collapsed then of_tracer("Administration pane opened")

### A single-group panel, without a header #

    // A single group has nothing to name : its header just eats up height.
    // Without a header there is no chevron either : the tiles always stay visible.
    uo_tuiles.ib_show_group_headers = false
    uo_tuiles.of_add_group(/*group_id*/ "tout", /*title*/ "")

### Moving a tile between two groups #

With `ib_reorderable = true`, users drag a tile wherever they want, including from one group to another. The `ue_tile_moved` event delivers both groups and the new position.

    uo_tuiles.ib_reorderable = true    // false by default : ask for it

    // ue_tile_moved event of uo_tuiles
    // as_group = source group, as_to_group = destination group, al_index = position
    if as_group <> as_to_group then
        of_tracer("Tile " + as_id + " moved from " + as_group + " to " + as_to_group)
    end if
    uo_tuiles.of_get_layout()    // request the layout in order to store it

    // ue_layout_changed event of uo_tuiles : store the chosen layout
    is_disposition = as_layout_json

    // On the next opening : restore the screen the way the user had arranged it
    if is_disposition <> "" then uo_tuiles.of_set_layout(is_disposition)

To freeze the screen, simply turn rearranging off:

    uo_tuiles.ib_reorderable = false

### Rearranging from code #

    // Put the "aide" tile at the head of its group (positions counted from 0)
    uo_tuiles.of_move_tile(/*group*/ "accueil", /*id*/ "aide", /*index*/ 0)

    // Insert a new tile in second position
    uo_tuiles.of_insert_tile(/*group*/ "accueil", /*id*/ "devis", /*text*/ "Quotes", /*index*/ 1)

    // Remove a tile without touching the rest
    uo_tuiles.of_remove_tile(/*group*/ "accueil", /*id*/ "aide")

### Reacting to a right-click #

    // ue_tile_context event of uo_tuiles : (as_group, as_id)
    // Remember the targeted tile, then open your own context menu
    is_groupe_vise = as_group
    is_tuile_visee = as_id
    of_ouvrir_menu_tuile(PointerX(), PointerY())

## Best practices #

- One `large` tile per screen is enough: it is the main entry point, the rest must stay readable.
- `small` tiles do not show their caption — always fill in the tooltip of the item.
- Reserve `il_back_color` for the tiles that must stand out: beyond two or three colors, the screen loses its hierarchy. And when you set a pale background, set `il_text_color` with it — the theme's text is not guaranteed readable on top of it.
- Prefer `of_add_live_item` (cycling) over `is_live_text` (fixed text) when you have several pieces of information to convey on the same tile.
- If you leave rearranging active, store the layout through `of_get_layout` / `ue_layout_changed` and replay `of_set_layout` on opening.
- Use `ib_visible` and `ib_enabled` (group or tile) to adapt the panel to the user's permissions, rather than rebuilding it.
- When there is not enough room for tiles, prefer the compact side navigation of listbar; for frequent actions, the toolbar.

← Component reference · Guide contents