PBToolboxAI v4 ← Site

tilesbox — u_pbt_tilesbox #

← Référence des composants · Sommaire du guide

Panneau de tuiles groupées façon écran d'accueil : quatre tailles de tuile, couleurs, pastilles, tuiles animées, groupes repliables et réorganisation à la souris.

▶ Le voir en vrai — Application de démonstration, tuile Tiles box : l'aperçu, le code qui le produit et cette page, côte à côte.


En bref #

Userobjectu_pbt_tilesbox
Classes d'itemsn_pbt_tilesbox_group (groupe) → n_pbt_tilesbox_tile (tuile)
Sert àOffrir un écran d'accueil ou un lanceur de fonctions : des tuiles cliquables, lisibles de loin, rangées par thème
Options opt-inib_reorderable : déplacer et redimensionner les tuiles à la souris

Démarrage rapide #

// event open de la fenetre

// Une tuile s ajoute a son ADRESSE : le groupe, puis son propre identifiant
uo_tiles.of_add_group(/*key*/ "office", /*title*/ "Gestion")

// Puis ses tuiles, chacune avec sa tailleuo_tiles.of_add_tile(/*keys*/ "office/clients",   /*label*/ "Clients",   /*icon_file*/ "mono:img\clients.svg",   /*size*/ "medium")
uo_tiles.of_add_tile(/*keys*/ "office/invoices",  /*text*/ "Factures",  /*image*/ "mono:img\factures.svg",  /*size*/ "medium")
uo_tiles.of_add_tile(/*keys*/ "office/stock",     /*text*/ "Stock",     /*image*/ "mono:img\stock.svg",     /*size*/ "small")
// event ue_tile_clicked de uo_tiles : (string as_keys)
choose case as_keys
    case "office/clients"  ; open(w_clients)
    case "office/invoices" ; open(w_invoices)
    case "office/stock"    ; open(w_stock)
end choose

Le modèle : groupes et tuiles #

Le panneau contient des groupes, chacun avec son titre et son entête repliable. Les tuiles appartiennent à un groupe : leur identifiant n'est unique qu'à l'intérieur de ce groupe. L'accès passe donc toujours par le chemin complet. Les ajouts, eux, vivent sur le composant : un handle ne porte que des propriétés.

// Chemin obligatoire : groupe puis tuile
uo_tiles.of_tile(/*keys*/ "office/invoices").is_badge = "12"

Les events portent eux aussi l'adresse complete (as_keys, le groupe puis la tuile). Voir Socle commun · Les items.


Propriétés #

PropriétéTypeDéfautRôle
ib_reorderablebooleanfalseAutorise l'utilisateur à réorganiser les tuiles : à la souris, ou au clavier par Ctrl+Gauche/Droite (une place dans le groupe, dans le sens de lecture) et Ctrl+Haut/Bas (vers le groupe précédent ou suivant) ; le clic droit redimensionne. Souris et clavier déclenchent le même ue_tile_moved
is_scrollstringSCROLL_HORIZONTALSens de défilement : SCROLL_VERTICAL (les tuiles passent à la ligne) ou SCROLL_HORIZONTAL (colonnes façon écran d'accueil)
ib_show_group_headersbooleantruefalse masque les entêtes de groupe. Utile quand le panneau ne contient qu'un seul groupe : il n'y a rien à nommer et l'entête ne fait que manger de la hauteur. Sans entête il n'y a plus de chevron : les groupes s'affichent toujours dépliés
ii_anim_durationinteger180Durée en millisecondes de l'animation de repli / dépli d'un groupe ; 0 = instantané
ii_tile_unitinteger0Taille de base d une tuile, en pixels : chaque format (petite, moyenne, large, grande) en est un multiple, donc une valeur rend tout le tableau plus dense ou plus aéré. 0 la rend au thème
ii_badge_sizeinteger0Hauteur des pastilles de tuile en pixels, pour toute la boîte (0 = la taille qui vient du thème). La taille de la police suit toute seule. La couleur d une pastille appartient à la tuile parce qu elle veut dire quelque chose ; sa taille, non
is_theme_stylestring""Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement
is_theme_modestring""Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement
il_theme_accentlong-1Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème)
is_tooltipstring""Info-bulle simple affichée au survol du composant
is_super_tooltip_titlestring""Titre de l'info-bulle enrichie (prend le pas sur is_tooltip)
is_super_tooltip_textstring""Texte de l'info-bulle enrichie (balisage riche accepté)
is_super_tooltip_imagestring""Image de l'info-bulle enrichie

Méthodes #

MéthodeRôle
of_group (string as_key) → n_pbt_tilesbox_groupRend le handle d'un groupe (créé au premier accès). Sur un groupe qui n'existe pas, il n'écrit rien — il ne crée jamais le groupe, of_add_group le fait ; une clé qui ne peut pas nommer un groupe (vide, avec / ou ``) rend un handle inerte qui se relit vide
of_add_group (string as_key, string as_title) → longAjoute un groupe. Renvoie 0 une fois appliqué, -5 si la clé est vide, contient un / ou un `, ou est déjà prise, -2` si le composant n'est pas créé
of_add_tile (string as_keys, string as_text, string as_image, string as_size) → longAjoute une tuile à son adresse, "office/clients" : le groupe où elle atterrit, puis son propre identifiant. Renvoie 0 une fois appliqué, -5 si l'adresse n'est pas groupe/tuile, si le groupe n'a pas été ajouté par of_add_group, si la clé est déjà prise dans ce groupe (ou vide, ou contient un `), -2` si le composant n'est pas créé. Une surcharge omet l'icône et la taille
of_tile (string as_keys) → n_pbt_tilesbox_tileRend le handle d'une tuile, par son adresse (créé au premier accès). Une adresse qui n'est pas groupe/tuile rend un handle inerte : il n'écrit rien et se lit vide
of_add_live_item (string as_keys, string as_text) → longAjoute une face au bandeau animé d'une tuile, à son adresse ; à partir de deux faces, la tuile les fait défiler. La première face efface is_live_text ; of_tile(adresse).of_count() lit le nombre de faces. Renvoie 0 une fois appliqué, -5 sur un texte vide ou si aucune tuile ne vit à cette adresse, -2 si le composant n'est pas créé
of_clear_live_items (string as_keys) → longVide le bandeau animé d'une tuile : elle cesse de défiler et retrouve sa face simple. Renvoie 0 une fois appliqué, -5 si aucune tuile ne vit à cette adresse, -2 si le composant n'est pas créé
of_remove_group (string as_key)Supprime un groupe et toutes ses tuiles. Renvoie 0 une fois appliqué, -5 s'il n'existe pas de tel groupe, -2 si le composant n'est pas créé
of_insert_tile (string as_keys, string as_text, integer ai_index)Insère une tuile à une position précise dans son groupe (position comptée à partir de 1). Renvoie 0 une fois appliqué, -5 pour les mêmes refus que of_add_tile, -2 si le composant n'est pas créé
of_insert_tile (string as_keys, string as_text, string as_image, string as_size, integer ai_index)Idem, avec l’icône et la taille (small / medium / wide / large) : une tuile est une image avec un libellé dessous, et sa taille se voit dans la grille. Renvoie 0 une fois appliqué, -5 pour les mêmes refus que of_add_tile, -2 si le composant n'est pas créé
of_move_tile (string as_keys, integer ai_index)Déplace une tuile existante à une autre position de son groupe, en conservant son état. Renvoie 0 une fois appliqué, -5 si aucune tuile ne vit à cette adresse, -2 si le composant n'est pas créé
of_remove_tile (string as_keys)Supprime une seule tuile, le reste du panneau est préservé. Renvoie 0 une fois appliqué, -5 si aucune tuile ne vit à cette adresse, -2 si le composant n'est pas créé
of_clear ( )Vide le panneau (groupes et tuiles) ; les handles donnés pour eux sont libérés. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé
of_get_layout ( )Relit la disposition courante en JSON : les groupes dans leur ordre, repliés ou non, visibles ou non, et leurs tuiles dans leur ordre avec leur taille et leur visibilité. Un texte opaque : à stocker tel quel, puis à rendre par of_set_layout
of_set_layout (string as_state_json)Restaure une disposition lue avec of_get_layout ou reçue par ue_layout_changed : ordre, groupes repliés, tailles et visibilité. Une tuile se retrouve par son groupe et sa clé ; ce que la disposition ne nomme pas garde sa place. Ne lève aucun événement. Renvoie 0 une fois appliqué, -5 sur un texte vide ou qui n'est pas du JSON, -2 si le composant n'est pas créé
of_reset ( )Vide le contenu et remet les propriétés à leur défaut. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé

Sur un groupe — n_pbt_tilesbox_group #

MembreTypeDéfautRôle
is_titlestringla cléTitre affiché dans l'entête, balisage riche accepté
ib_collapsedbooleanfalseGroupe replié : ses tuiles sont masquées sous l'entête. Le poser lève ue_group_toggled quand l'état change, comme un clic sur l'entête
ib_enabledbooleantrueGroupe entier grisé et inerte : son entête ne le replie plus, ses tuiles ne répondent plus, aucune tuile n'y tombe
ib_visiblebooleantrueGroupe masqué, sans être supprimé du modèle
il_back_color · il_text_color · il_back_color_hover · il_text_color_hover · il_accentlong-1Couleurs de l'entête du groupe — fond, titre, les deux sous le pointeur, et un filet d'accent sous l'entête. Elles ne descendent pas sur les tuiles, qui gardent les leurs

Sur une tuile — n_pbt_tilesbox_tile #

MembreTypeDéfautRôle
is_titlestring""Texte affiché sur la tuile. Posé par of_add_tile ; l'écrire ici le change, le lire dit ce que la tuile affiche en ce moment
is_imagestring""Icône de la tuile (chemin disque ou resources.dll:nom). Une chaîne vide retire l'icône
is_sizestringSIZE_MEDIUMTaille : SIZE_SMALL, SIZE_MEDIUM, SIZE_WIDE, SIZE_LARGE
il_back_color · il_text_colorlong-1Fond et texte propres à la tuile, en RGB(r,v,b) (-1 = ce que donne le thème)
il_back_color_hover · il_text_color_hoverlong-1Les deux mêmes, mais sous le pointeur
is_badgestring""Pastille affichée dans l'angle de la tuile (un compteur, un état court)
il_badge_colorlong-1Fond de la pastille, en RGB PowerBuilder (-1 = la couleur qui vient du thème ; 0 est le noir)
is_live_textstring""Texte fixe superposé à la tuile ; la première face de of_add_live_item l'efface (il se relit alors vide), balisage riche accepté
ib_enabledbooleantrueTuile grisée et non cliquable
ib_visiblebooleantrueTuile masquée, sans être retirée de son groupe

Les icônes acceptent toutes les formes reconnues par la bibliothèque : chemin, mono:, tint:, ressource de DLL. Sur une grande tuile, préférez une image nette en haute définition ou un SVG.


Les quatre tailles #

TailleEncombrementUsage typique
small1 caseRaccourci secondaire ; le libellé n'est pas affiché, l'info-bulle prend le relais
medium2 × 2 casesTaille de référence : icône et libellé
wide4 × 2 casesTuile allongée, idéale pour un texte animé
large4 × 4 casesTuile vedette de l'écran

Événements #

ÉvénementDéclenché quand
ue_tile_clicked (string as_keys)Une tuile est cliquée
ue_tile_moved (string as_keys, string as_to_key, long al_index)L'utilisateur a déplacé une tuile, à la souris ou par Ctrl+flèches (of_move_tile ne lève rien) : as_keys est l'adresse de départ, as_to_key le groupe d'arrivée, al_index la nouvelle position
ue_group_toggled (string as_key, boolean ab_collapsed)Un groupe est replié ou déplié : depuis son entête, ou par son ib_collapsed posé par votre code (rien quand il est déjà dans cet état)
ue_tile_context (string as_keys)Clic droit sur une tuile
ue_tile_resized (string as_keys, string as_size)L'utilisateur a donné une autre taille à une tuile depuis son menu du clic droit (affiché seulement quand ib_reorderable vaut true) ; as_size porte la nouvelle taille
ue_layout_changed (string as_layout_json)L'utilisateur a changé l'arrangement : une tuile déplacée, une tuile redimensionnée depuis son menu, un groupe replié ou déplié depuis son entête. Porte la disposition entière, le même texte que of_get_layout. Ce que l'application change par le code ne le lève pas (le ib_collapsed d'un groupe lève seulement ue_group_toggled)
ue_ready ( )Le composant a fini de charger ; tout ce qui a été envoyé avant a été rejoué
ue_runtime_missing ( )Le runtime WebView2 est absent : le composant reste vide
ue_bg_color (long al_color)Le composant a calculé sa couleur de fond de thème ; l'userobject l'a déjà adoptée (backcolor)

Exemples #

Tailles mélangées dans un même groupe #

// Repartir d'une boite vide, avec un groupe
uo_tiles.of_clear()
uo_tiles.of_add_group(/*key*/ "home", /*title*/ "Accueil")

// Quatre tuiles, de quatre tailles
uo_tiles.of_add_tile(/*keys*/ "home/dashboard", /*text*/ "Tableau de bord", /*image*/ "mono:img\chart.svg",  /*size*/ "large")
uo_tiles.of_add_tile(/*keys*/ "home/clients", /*text*/ "Clients",         /*image*/ "mono:img\users.svg",  /*size*/ "medium")
uo_tiles.of_add_tile(/*keys*/ "home/agenda",  /*text*/ "Agenda",          /*image*/ "mono:img\cal.svg",    /*size*/ "wide")
uo_tiles.of_add_tile(/*keys*/ "home/help",    /*text*/ "Aide",            /*image*/ "mono:img\help.svg",   /*size*/ "small")

Pastille, couleur et tuile animée #

// Local variables
n_pbt_tilesbox_tile lnv_tile

// Une pastille signale un nombre d'elements en attente
uo_tiles.of_tile(/*keys*/ "home/clients").is_badge = String(ll_new_count)

// Rouge quand le retard devient critique, couleur du theme sinon (-1)
if ll_new_count > 50 then
    uo_tiles.of_tile(/*keys*/ "home/clients").il_badge_color = RGB(/*red*/ 200, /*green*/ 30, /*blue*/ 30)
else
    uo_tiles.of_tile(/*keys*/ "home/clients").il_badge_color = -1
end if

// Une couleur propre met une tuile en avant : fond, texte, et ce que
// chacun devient sous le pointeur
lnv_tile = uo_tiles.of_tile(/*keys*/ "home/dashboard")
lnv_tile.il_back_color = RGB(/*red*/ 0, /*green*/ 103, /*blue*/ 192)
lnv_tile.il_back_color_hover = RGB(/*red*/ 0, /*green*/ 80, /*blue*/ 150)
lnv_tile.il_text_color = RGB(/*red*/ 255, /*green*/ 255, /*blue*/ 255)

// Tuile ANIMEE : chaque face ajoutee defile a son tour sur la tuile. Une face
// s ajoute depuis le COMPOSANT, a l adresse de la tuile
uo_tiles.of_clear_live_items(/*keys*/ "home/agenda")
uo_tiles.of_add_live_item(/*keys*/ "home/agenda", /*text*/ "3 rendez-vous aujourd'hui")
uo_tiles.of_add_live_item(/*keys*/ "home/agenda", /*text*/ "Reunion equipe a 14h00")
uo_tiles.of_add_live_item(/*keys*/ "home/agenda", /*text*/ "2 relances en retard")

Un texte fixe plutôt qu'un défilement #

// is_live_text pose UN texte permanent sur la tuile (balisage riche accepte)
uo_tiles.of_tile(/*keys*/ "home/dashboard").is_live_text = "[b]48[/b] commandes du jour"

Groupes repliables #

// Local variables
n_pbt_tilesbox_group lnv_admin

// Un groupe et ses deux tuiles, puis une poignee sur le groupe
uo_tiles.of_add_group(/*key*/ "admin", /*title*/ "Administration")
uo_tiles.of_add_tile(/*keys*/ "admin/users",  /*text*/ "Utilisateurs", /*image*/ "mono:img\users.svg", /*size*/ "medium")
uo_tiles.of_add_tile(/*keys*/ "admin/params", /*text*/ "Parametres", /*image*/ "mono:img\gear.svg",  /*size*/ "medium")
lnv_admin = uo_tiles.of_group(/*key*/ "admin")

// Ce groupe demarre replie : l'utilisateur l'ouvre s'il en a besoin
lnv_admin.ib_collapsed = true

// Un groupe entier peut aussi etre grise selon les droits
lnv_admin.ib_enabled = (is_profile = "ADMIN")
// event ue_group_toggled de uo_tiles
if as_key = "admin" and not ab_collapsed then of_trace("Ouverture du volet administration")

Un panneau à groupe unique, sans entête #

// Un seul groupe n'a rien a nommer : son entete ne fait que manger de la hauteur.
// Sans entete, plus de chevron non plus : les tuiles restent toujours visibles.
uo_tiles.ib_show_group_headers = false
uo_tiles.of_add_group(/*key*/ "all", /*title*/ "")

Déplacer une tuile entre deux groupes #

Avec ib_reorderable = true, l'utilisateur fait glisser une tuile où il veut, y compris d'un groupe vers un autre. L'event ue_tile_moved livre les deux groupes et la nouvelle position. Au clavier, la tuile qui a le focus avance ou recule d'une place par Ctrl+Gauche/Droite (dans le sens de lecture : inversé en droite à gauche) et passe au groupe précédent ou suivant par Ctrl+Haut/Bas — même ue_tile_moved, mêmes refus (clé déjà prise, groupe désactivé ou replié). La touche Tab ne s'arrête qu'une fois par groupe : les flèches parcourent les tuiles.

// Laisser l'utilisateur reorganiser les tuiles : faux par defaut, a demander
uo_tiles.ib_reorderable = true
// event ue_tile_moved de uo_tiles
// as_keys = d'ou elle vient, as_to_key = ou elle va, al_index = position
n_pbt_utils lnv_utils   // autoinstantiate : rien a creer, rien a detruire
if lnv_utils.of_parent(/*keys*/ as_keys) <> as_to_key then
    of_trace("Tuile " + lnv_utils.of_leaf(/*keys*/ as_keys) + " deplacee de " + lnv_utils.of_parent(/*keys*/ as_keys) + " vers " + as_to_key)
end if
// event ue_layout_changed de uo_tiles : conserver la disposition choisie
is_layout_json = as_layout_json
// A l'ouverture suivante : restituer l'ecran tel que l'utilisateur l'avait range
if is_layout_json <> "" then uo_tiles.of_set_layout(/*state_json*/ is_layout_json)

Pour figer l'écran, il suffit de couper la réorganisation :

// Freeze the screen : the tiles stay where they are
uo_tiles.ib_reorderable = false

Réorganiser depuis le code #

// Placer la tuile "help" en tete de son groupe (positions comptees a partir de 1)
uo_tiles.of_move_tile(/*keys*/ "home/help", /*index*/ 1)

// Inserer une nouvelle tuile en deuxieme position
uo_tiles.of_insert_tile(/*keys*/ "home/quotes", /*text*/ "Devis", /*index*/ 2)

// Retirer une tuile sans toucher au reste
uo_tiles.of_remove_tile(/*keys*/ "home/help")

// Chaque appel rend -5 si l adresse ne nomme rien (ou, a l insertion, une cle deja prise)

Réagir au clic droit #

// event ue_tile_context de uo_tiles : (as_keys)
// Retenir la tuile visee, puis ouvrir votre propre menu contextuel
n_pbt_utils lnv_utils   // autoinstantiate : rien a creer, rien a detruire

// Une seule adresse : la decouper si les deux moities servent.
is_target_group = lnv_utils.of_parent(/*keys*/ as_keys)
is_target_tile = lnv_utils.of_leaf(/*keys*/ as_keys)
of_open_tile_menu(PointerX(), PointerY())

Bonnes pratiques #

Hérité du socle commun #

Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.

MembresRôleDétaillé dans
of_count · of_keys_at · of_hasParcourir ce que le composant contient3.2 Les items
of_resetRemettre le composant à zéro3.6 Remettre un composant à zéro : of_reset()
of_register_shortcut · of_clear_shortcutsRaccourcis clavier du composant3.5 Les raccourcis clavier
of_is_created · of_is_ready · of_get_last_errorS'il est né, s'il est prêt, ce qui a échoué3.7 Diagnostic
of_save_as_png · of_save_as_jpgExporter le rendu en image3.8 Exporter le rendu en image
of_set_redrawGrouper les modifications en un seul repaint3.10 Bonnes pratiques
of_preload_iconsIcônes affichées sans délaiAffichage instantané : of_icon
of_set_translationTraduire un libellé du composant5.2 Adapter un libellé : of_set_translation
of_focus_webviewDonner le focus au composant6.4 Clavier et focus
of_print · of_print_to_pdfImprimer, ou écrire un PDF6.9 Imprimer
of_set_property · of_get_property · of_component_namePiloter une propriété par son nom3.1 Le moteur de propriétés

Deux aides ne sont pas héritées : of_icon et of_escape_markup vivent sur n_pbt_utils. Déclarez-en une — n_pbt_utils lnv_utils, rien à créer — et appelez-les dessus.

← Référence des composants · Sommaire du guide