PBToolboxAI v4 ← Site

dockcontainer — u_pbt_dockcontainer #

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

Panneaux dockables façon Visual Studio : docking par glisser-déposer, empilement en onglets, séparateurs redimensionnables, fenêtres flottantes, masquage automatique — et sauvegarde/restauration de la disposition.

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


En bref #

Userobjectu_pbt_dockcontainer
Classe d'itemsn_pbt_dock_panel (un panneau)
Sert àDonner à une fenêtre PowerBuilder l'ergonomie d'un IDE moderne : l'utilisateur organise lui-même ses panneaux, et la disposition se retrouve à la session suivante

Comme tab, chaque panneau héberge un vrai contrôle PowerBuilder (dragobject) : userobject, DataWindow, ou un autre composant PBToolboxAI. Voir Héberger de vrais contrôles PowerBuilder.


Démarrage rapide #

// event open de la fenetre : les controles de panneau sont deja poses dessus
uo_dock.of_add_panel(/*key*/ "document", /*position*/ "", /*relative_to*/ "", /*size*/ 0, /*title*/ "Document", /*content*/ uo_editor)

// L'explorateur, accole au debut du document, sur 260 pixels
uo_dock.of_add_panel(/*key*/ "explorer", /*position*/ uo_dock.POSITION_START, /*relative_to*/ "document", /*size*/ 260, /*title*/ "Explorateur", /*content*/ uo_tree)

// Les proprietes, accolees a la fin du document, sur 300 pixels
uo_dock.of_add_panel(/*key*/ "properties", /*position*/ uo_dock.POSITION_END, /*relative_to*/ "document", /*size*/ 300, /*title*/ "Proprietes", /*content*/ uo_props)

// La zone centrale : ni fermable par le docking, ni flottante, ni masquable
uo_dock.is_main = "document"

Propriétés #

PropriétéTypeDéfautRôle
is_mainstring""Clé du panneau principal : la zone de document centrale, qui ne peut être ni masquée ni détachée, et sur laquelle aucun panneau ne s'empile. Posée avant l'ajout de ce panneau, elle est retenue et appliquée par son of_add_panel ; "" retire le panneau principal
ib_veto_closebooleanfalseOpt-in : demander avant qu'un panneau ne se ferme — la croix de son en-tête, Fermer / Fermer les autres du menu, la croix d'un panneau glissant et of_close_panel (déclenche ue_panel_closing, qui peut refuser ; un ordre refusé renvoie -4). Désactivé par défaut, comme tout événement annulable de la bibliothèque : posez true pour garder ouvert un panneau qui porte du travail non enregistré
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

Positions de docking #

Les constantes du composant alimentent as_position dans of_add_panel et of_move_panel :

ConstanteValeurEffet
POSITION_START"start"Le nouveau panneau se docke du côté début de lecture du panneau de référence (à gauche en écriture de gauche à droite)
POSITION_END"end"… du côté fin de lecture
POSITION_TOP"top"… au-dessus
POSITION_BOTTOM"bottom"… en dessous
POSITION_STACK"stack"Le panneau est empilé en onglet sur le panneau de référence. Valeur retenue si as_position est vide

Propriétés d'un panneau — n_pbt_dock_panel #

Obtenues par of_panel(cle).

PropriétéTypeDéfautRôle
is_titlestring""Titre affiché sur l'onglet du panneau ; vide (aucun titre donné), l'onglet porte la clé et le panneau principal n'a pas d'en-tête — lui donner un titre ensuite le fait apparaître. Accepte le balisage riche
is_short_titlestring""Forme courte du titre, pour les endroits où la place manque : le rail d'un panneau épinglé (toujours — c'est un liseré) et l'onglet d'une pile, mais seulement une fois que le titre complet n'y tient plus, ce qui est mesuré et non deviné. L'en-tête du panneau garde le titre complet. "" = pas de forme courte
ib_visiblebooleantrueAffiche ou masque ce panneau. Le panneau principal ne se masque pas ; masquer un panneau flottant referme sa fenêtre, et il reviendra ancré à sa place
ib_pinnedbooleantruetrue = épinglé en place ; false = tout le groupe du panneau (ses onglets compris) se replie en languettes sur le bord. Une languette déploie son panneau au survol (après 400 ms) ou tout de suite au clic ; ouvert au survol, il se replie quand la souris le quitte sans que le focus y soit, ouvert au clic il reste jusqu'à un clic ailleurs. le bouton d'épingle de l'en-tête lève ue_panel_pinned pour chaque panneau du groupe, et poser ib_pinned par le code aussi (un ordre le lève comme le geste)
ib_closablebooleantrueL'utilisateur peut-il fermer ce panneau (croix de l'en-tête, croix du panneau glissant, Fermer / Fermer les autres du menu) ? Posé à l'ajout par of_add_panel(…, ab_closable), modifiable à tout moment : la croix et les entrées du menu suivent aussitôt. of_close_panel refuse (-5) un panneau non fermable
is_header_colorstring""Couleur de l'en-tête de ce panneau. Vide = le thème décide ; HEADER_COLOR_ACCENT suit l'accent du thème (et le suit encore après un changement de thème, ce qu'un code fixe ne ferait pas) ; sinon un #rrggbb. La couleur de texte lisible est calculée avec
is_border_colorstring""Couleur de la bordure de ce panneau, même grammaire. Elle encadre le cadre et l'en-tête, qui portent chacun la leur : n'en colorer qu'une laisse une couture visible. Elle suit le panneau dans son volet glissant
is_tooltipstring""Info-bulle simple affichée au survol de l'item
is_super_tooltip_titlestring""Titre de l'info-bulle enrichie de l'item (prend le pas sur is_tooltip)
is_super_tooltip_textstring""Texte de l'info-bulle enrichie de l'item (balisage riche accepté)
is_super_tooltip_imagestring""Image de l'info-bulle enrichie de l'item
il_back_colorlong-1Fond de l'onglet de CE panneau dans une pile, et de sa languette sur le bord une fois dépunaisé (-1 = celui du composant, qui suit le thème). L'en-tête d'un panneau seul prend is_header_color
il_text_colorlong-1Couleur du texte de l'onglet et de la languette de CE panneau (-1 = celle du composant)
il_back_color_hoverlong-1Fond de l'onglet et de la languette de CE panneau au survol (-1 = celui du composant)
il_text_color_hoverlong-1Couleur du texte de l'onglet et de la languette de CE panneau au survol (-1 = celle du composant)
il_accentlong-1Accent de CE panneau (-1 = accent du composant) ; l'en-tête le suit quand is_header_color vaut HEADER_COLOR_ACCENT

Méthodes #

MéthodeRôle
of_add_panel (string as_key, string as_position, string as_relative_to, integer ai_size, string as_title, dragobject ado_content)Ajoute un panneau fermable et héberge le contrôle. as_relative_to = clé du panneau contre lequel il se docke (vide = la racine) ; ai_size = taille initiale en pixels (0 = automatique). Renvoie 0 une fois appliqué, -5 sur une clé vide, déjà prise ou contenant / ou une barre verticale, un contrôle déjà hébergé, un as_relative_to inconnu ou un empilement (POSITION_STACK) sur le panneau principal, ou une position inconnue — rien n'est alors touché, -6 en mode démo quand le dock porte déjà ses trois panneaux (le contrôle reste à sa place, visible), -2 si le composant n'est pas créé
of_add_panel (…, boolean ab_closable)Idem, avec ab_closable = false pour un panneau sans bouton de fermeture. Renvoie 0 une fois appliqué, -5 sur une clé vide, déjà prise ou contenant / ou une barre verticale, un contrôle déjà hébergé, un as_relative_to inconnu ou un empilement (POSITION_STACK) sur le panneau principal, ou une position inconnue — rien n'est alors touché, -6 en mode démo quand le dock porte déjà ses trois panneaux (le contrôle reste à sa place, visible), -2 si le composant n'est pas créé
of_select_panel (string as_key)Fait voir un panneau : au premier plan de sa pile, son volet glissant ouvert quand son groupe est replié, sa fenêtre remontée devant quand il flotte. Quand un panneau ancré passe au premier plan de sa pile, ue_panel_selected suit, comme pour un clic sur son onglet. Renvoie 0 une fois appliqué, -5 sur une clé inconnue ou un panneau MASQUÉ (le montrer est le rôle de ib_visible), -2 si le composant n'est pas créé
of_move_panel (string as_key, string as_target, string as_position)Réorganise depuis le code, exactement comme si l'utilisateur avait fait glisser l'onglet. Renvoie 0 une fois appliqué, -5 sur une clé inconnue, une cible (as_target) inconnue une position inconnue, un empilement sur le panneau principal ou un empilement DU panneau principal, -2 si le composant n'est pas créé
of_move_panel (string as_key, string as_target, string as_position, integer ai_index)Même chose, en donnant le rang du panneau dans la pile de la cible (1 = premier, 0 ou moins = dernier). Seule une pile est une liste ordonnée : l'index est ignoré pour POSITION_START / END / TOP / BOTTOM. Renvoie 0 une fois appliqué, -5 sur une clé inconnue, une cible (as_target) inconnue une position inconnue, un empilement sur le panneau principal ou un empilement DU panneau principal, -2 si le composant n'est pas créé
of_float_panel (string as_key)Détache le panneau dans une vraie fenêtre flottante déplaçable et redimensionnable ; un panneau déjà détaché auparavant retrouve la place de sa fenêtre. La refermer le re-docke (ue_panel_docked). Pas le panneau principal (is_main) : c'est la zone de document autour de laquelle les autres se rangent, il bâtit son propre en-tête, et il ne peut être ni détaché, ni masqué, ni fermé. ue_panel_floated suit, comme pour le bouton de l'en-tête, le double-clic sur l'en-tête ou sur l'onglet, ou Détacher dans le menu du clic droit. Renvoie 0 une fois appliqué, -5 sur une clé inconnue, le panneau principal ou un panneau MASQUÉ, -2 si le composant n'est pas créé
of_close_panel (string as_key)Ferme le panneau comme sa croix : il est masqué (ib_visible = true le réaffiche) et ue_panel_closed suit. Avec ib_veto_close = true, ue_panel_closing est posé d'abord. Renvoie 0 une fois appliqué, -4 quand votre ue_panel_closing a refusé (le panneau reste), -5 sur une clé inconnue, le panneau principal, un panneau masqué ou non fermable (ib_closable = false), -2 si le composant n'est pas créé
of_notify_panel (string as_key)Signale du contenu nouveau : si le panneau n'est pas visible, son onglet affiche un compteur d'éléments non vus, effacé à la sélection. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé
of_clear_notify (string as_key)Efface ce compteur sans afficher le panneau. Sélectionner l onglet était le seul autre moyen, ce qui est faux quand votre code sait que le contenu lui-même a disparu. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé
of_remove_panel (string as_key)Retire le panneau et rend le contrôle à sa fenêtre d'origine, à sa place, à sa taille et avec la visibilité qu'il avait avant of_add_panel. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé
of_get_layout ( )Renvoie la disposition courante (arbre des découpes, ratios, onglets, visibilité, panneaux flottants et place de leur fenêtre) sous forme de chaîne, à stocker en fichier, base ou registre
of_set_layout (string as_json)Restaure une disposition obtenue par of_get_layout. Les panneaux doivent avoir été recréés avant l'appel ; ceux absents de la disposition — ou tous, si elle n'en connaît aucun — rejoignent un groupe à côté des autres, jamais le panneau principal. Les panneaux flottants retrouvent leur fenêtre à sa place, ramenée sur un écran si le leur a disparu ; une disposition qui ne nomme aucun panneau principal garde le panneau principal courant. Renvoie 0 une fois appliqué, -5 sur un texte qui n'est pas une disposition (pas du JSON, ou sans tree) : le dock reste alors tel quel, -2 si le composant n'est pas créé
of_panel (string as_key)Handle n_pbt_dock_panel du panneau (créé au premier accès)
of_refresh_panel (string as_key)Rafraîchit le rendu d'un panneau construit hors écran, sans scintillement. Renvoie 0, -5 si la clé ne désigne aucun panneau, -2 si le composant n'est pas créé
of_relayout ( )Recalcule et republie toutes les zones pour que les contrôles hébergés soient repositionnés. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé
of_reset ( )Vide le conteneur : chaque contrôle hébergé est rendu à sa fenêtre d'origine, les handles de panneaux sont libérés, la disposition mémorisée est effacée. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé
of_set_redraw (boolean)Regroupe une rafale de modifications en un seul rendu. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé
of_save_as_png (string) · of_save_as_jpg (string)Exporte le rendu en image. Renvoie 0 une fois l'image écrite, -4 si l'écriture échoue, -2 si le composant n'est pas créé

Événements #

ÉvénementDéclenché quand
ue_panel_selected (string as_key)Un panneau ancré passe au premier plan de son groupe : clic sur son onglet ou son en-tête, flèches du bandeau, ou of_select_panel (un ordre de votre code le lève aussi)
ue_panel_closed (string as_key)Un panneau est fermé : la croix de son en-tête, Fermer ou Fermer les autres dans le menu du clic droit sur l'en-tête ou l'onglet, la croix d'un panneau glissant, ou of_close_panel (un ordre de votre code le lève aussi). Le panneau est masqué (ib_visible = true le réaffiche) ; avec ib_veto_close = true, seulement une fois que ue_panel_closing l'a permis
ue_panel_closing (string as_key) → booleanAnnulable, posé avant qu'un panneau ne se ferme — la croix de son en-tête, Fermer ou Fermer les autres du menu (une question par panneau), la croix d'un panneau glissant, ou of_close_panel —, et seulement quand ib_veto_close = true (désactivé par défaut). Renvoyez false pour garder le panneau ouvert (travail non enregistré) : ue_panel_closed ne suit pas, et of_close_panel renvoie -4
ue_panel_pinned (string as_key, boolean ab_pinned)Un panneau est épinglé (true) ou dépunaisé en masquage automatique (false) : bouton d'épingle de l'en-tête, bouton d'ancrage du volet, ou ib_pinned posé par votre code (un ordre le lève aussi)
ue_panel_floated (string as_key)Un panneau est détaché en fenêtre flottante : bouton de l'en-tête, double-clic sur l'en-tête ou sur l'onglet, Détacher dans le menu du clic droit, ou of_float_panel (un ordre de votre code le lève aussi). Une disposition restaurée (of_set_layout) ne lève rien
ue_panel_docked (string as_key)L'UTILISATEUR re-docke un panneau flottant : il ferme sa fenêtre, ou double-clique sur sa barre de titre — le panneau retrouve sa place
ue_layout_changed (string as_json)La disposition a changé (glissement, redimensionnement, docking, fenêtre flottante déplacée ou redimensionnée, mais aussi un panneau fermé, masqué, sélectionné, renommé, ou un autre panneau principal). Le paramètre porte la nouvelle disposition, prête à être enregistrée
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)

À la souris #

Au-delà du glisser-déposer des onglets et des séparateurs, trois gestes agissent sur un panneau — jamais sur le panneau principal :

GesteEffet
Double-clic sur l'en-tête d'un groupe ou sur un ongletDétache le panneau (pour l'en-tête : le panneau actif du groupe) dans une fenêtre flottante — ue_panel_floated
Double-clic sur la barre de titre d'une fenêtre flottanteRaccroche le panneau à sa place, comme la croix de la fenêtre — ue_panel_docked
Clic droit sur l'en-tête ou sur un ongletMenu Détacher / Fermer / Fermer les autres (les autres panneaux fermables du même groupe). Une entrée qui ne peut rien faire est grisée ; avec ib_veto_close = true, chaque fermeture pose ue_panel_closing — une question par panneau

Au clavier #

Le contenu d'un panneau est un vrai contrôle PowerBuilder : le clavier y appartient à votre code, comme dans n'importe quelle fenêtre. Ce que le composant prend en charge, c'est son propre habillage — en-têtes, onglets, splitters :

ToucheEffet
Flèches sur un ongletPassent au panneau précédent / suivant du groupe, et le sélectionnent. Un bandeau d'onglets est un seul arrêt de tabulation
Début / Fin sur un ongletPremier / dernier panneau du groupe
Flèches sur un splitterDéplacent la séparation de 2 %, dans l'axe du splitter seulement
Page haut / Page bas sur un splitterMême chose, par pas de 10 %
ÉchapReferme le panneau glissant ouvert depuis un bouton de bord

Un splitter est un separator focalisable qui annonce sa position ; les boutons d'en-tête (détacher, masquer, fermer) portent un nom, et le panneau actif d'un groupe est marqué aria-selected. Un déplacement au clavier remonte dans ue_layout_changed exactement comme un glissement à la souris.


Exemples #

Une fenêtre façon IDE #

// event open : chaque contenu est un vrai controle PB pose sur la fenetre
uo_dock.of_add_panel(/*key*/ "document", /*position*/ "", /*relative_to*/ "", /*size*/ 0, /*title*/ "Document", /*content*/ uo_editor)
uo_dock.of_add_panel(/*key*/ "explorer", /*position*/ uo_dock.POSITION_START, /*relative_to*/ "document", /*size*/ 260, /*title*/ "Explorateur", /*content*/ uo_tree)
uo_dock.of_add_panel(/*key*/ "properties", /*position*/ uo_dock.POSITION_END, /*relative_to*/ "document", /*size*/ 300, /*title*/ "Proprietes", /*content*/ uo_props)
uo_dock.of_add_panel(/*key*/ "output", /*position*/ uo_dock.POSITION_BOTTOM, /*relative_to*/ "document", /*size*/ 200, /*title*/ "Sortie", /*content*/ uo_console)

// Un second panneau empile en onglet sur "properties"
uo_dock.of_add_panel(/*key*/ "help", /*position*/ uo_dock.POSITION_STACK, /*relative_to*/ "properties", /*size*/ 0, /*title*/ "Aide", /*content*/ uo_help)

// Le document est la zone centrale
uo_dock.is_main = "document"

Mémoriser et restaurer la disposition de l'utilisateur #

// event close de la fenetre : enregistrer ce que l'utilisateur a organise
string ls_layout
ls_layout = uo_dock.of_get_layout()
of_save_setting(/*name*/ "main_dock", /*value*/ ls_layout)
// event open : RECREER les panneaux d'abord, restaurer ensuite
string ls_layout

// D'abord les panneaux : les of_add_panel ci-dessus
of_create_panels()

// Puis la disposition enregistree a la derniere fermeture, s'il y en a une
ls_layout = of_read_setting(/*name*/ "main_dock")
if ls_layout <> "" then uo_dock.of_set_layout(/*json*/ ls_layout)

L'ordre est impératif : of_set_layout ne crée aucun panneau, il ne fait que replacer ceux qui existent déjà.

Suivre les changements en continu #

// event ue_layout_changed de uo_dock : (string as_json)
// Enregistrement immediat, sans attendre la fermeture de la fenetre.
of_save_setting(/*name*/ "main_dock", /*value*/ as_json)

Piloter un panneau par son handle #

// Local variables
n_pbt_dock_panel lnv_panel

// Le panneau des proprietes : un titre qui compte les modifications, et replie sur son bord
lnv_panel = uo_dock.of_panel(/*key*/ "properties")
lnv_panel.is_title  = "Proprietes (3 modifiees)"
lnv_panel.ib_pinned = false        // se replie en languette sur le bord
// Masquer un panneau reserve aux administrateurs
uo_dock.of_panel(/*key*/ "audit").ib_visible = gb_administrator

Attirer l'attention sur un panneau en arrière-plan #

// Un traitement de fond a ecrit dans la console : signaler sans voler le focus
uo_dock.of_notify_panel(/*key*/ "output")

Réorganiser depuis le code #

// Deplacer un panneau comme si l'utilisateur avait fait glisser son onglet
uo_dock.of_move_panel(/*key*/ "output", /*target*/ "document", /*position*/ "bottom")

// L'empiler en onglet sur un autre panneau
uo_dock.of_move_panel(/*key*/ "help", /*target*/ "properties", /*position*/ "stack")

Détacher un panneau sur un second écran #

// Fenetre flottante native : l'utilisateur peut la poser sur un autre ecran
uo_dock.of_float_panel(/*key*/ "properties")
// event ue_panel_docked de uo_dock : (string as_key)
// L'utilisateur a referme la fenetre flottante : le panneau est revenu.
of_log(/*msg*/ "Panneau re-docke : " + as_key)

Fermer proprement un panneau #

// event ue_panel_closed de uo_dock : (string as_key)
// Retirer aussi le panneau du conteneur pour liberer le controle heberge.
uo_dock.of_remove_panel(/*key*/ as_key)

Refuser la fermeture d'un panneau qui a du travail non enregistré #

// event open de la fenetre : demander avant qu'un panneau se ferme (desactive par defaut)
uo_dock.ib_veto_close = true

// ue_panel_closing event of uo_dock : (string as_key) returns boolean
// L'editeur porte encore des modifications non enregistrees : son panneau reste ouvert.
if as_key = "editor" then
    if ib_editor_modified then return false
end if
return true

// Votre code pose la meme question : -4 quand elle est refusee
if uo_dock.of_close_panel(/*key*/ "editor") = -4 then
    st_status.Text = "Enregistrez le document avant de fermer l'editeur."
end if

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