# dockcontainer — `u_pbt_dockcontainer` #

← Komponentenreferenz · Inhalt des Handbuchs

> Andockbare Panels im Stil von Visual Studio: Andocken per Drag & Drop, Stapeln als Registerkarten, verstellbare Trennlinien, schwebende Fenster, automatisches Ausblenden — und Speichern bzw. Wiederherstellen der Anordnung.

> ▶ Live ansehen — Demoanwendung, Kachel Dock container: die Vorschau, der zugehörige Code und diese Seite, nebeneinander.

## Auf einen Blick #

Userobject | `u_pbt_dockcontainer`
Item-Klasse | `n_pbt_dock_panel` (ein Panel)
Wofür | Einem PowerBuilder-Fenster die Ergonomie einer modernen IDE geben: Die Benutzer ordnen ihre Panels selbst an, und die Anordnung ist in der nächsten Sitzung wieder da

Wie bei tab beherbergt jedes Panel ein echtes PowerBuilder-Steuerelement (`dragobject`): ein Userobject, eine DataWindow oder eine weitere PBToolboxAI-Komponente. Siehe Echte PowerBuilder-Steuerelemente hosten.

## Schnellstart #

    // open-Event des Fensters : die Panel-Steuerelemente liegen bereits darauf
    uo_dock.of_add_panel(/*schluessel*/ "document", /*position*/ "", /*relativ_zu*/ "", &
                         /*groesse*/ 0, /*titel*/ "Dokument", /*inhalt*/ uo_editeur)

    uo_dock.of_add_panel(/*schluessel*/ "explorateur", /*position*/ uo_dock.POSITION_START, &
                         /*relativ_zu*/ "document", /*groesse*/ 260, &
                         /*titel*/ "Explorer", /*inhalt*/ uo_arbre)

    uo_dock.of_add_panel(/*schluessel*/ "proprietes", /*position*/ uo_dock.POSITION_END, &
                         /*relativ_zu*/ "document", /*groesse*/ 300, &
                         /*titel*/ "Eigenschaften", /*inhalt*/ uo_props)

    // Der zentrale Bereich : vom Docking weder schliessbar noch schwebend noch ausblendbar
    uo_dock.is_main = "document"

## Eigenschaften #

Eigenschaft | Typ | Standard | Zweck
--- | --- | --- | ---
`is_main` | string | `""` | Schlüssel des Haupt-Panels: der zentrale Dokumentbereich, der weder ausgeblendet noch abgelöst werden kann. Das Panel muss bereits vorhanden sein
`is_theme_style` | string | `fluent` | Visueller Stil der Komponente (Konstanten `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Helle oder dunkle Variante (Konstanten `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Akzentfarbe dieser Komponente (`-1` = Akzent des Designs)
`is_tooltip` | string | `""` | Einfacher Tooltip beim Überfahren der Komponente
`is_super_tooltip_title` | string | `""` | Titel des erweiterten Tooltips (hat Vorrang vor `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Text des erweiterten Tooltips (Rich-Markup zulässig)
`is_super_tooltip_image` | string | `""` | Bild des erweiterten Tooltips

### Docking-Positionen #

Die Konstanten der Komponente speisen `as_position` in `of_add_panel` und `of_move_panel`:

Konstante | Wert | Wirkung
--- | --- | ---
`POSITION_START` | `"start"` | Das neue Panel dockt an der Seite des Leseanfangs des Referenz-Panels an (links bei Schreibrichtung von links nach rechts)
`POSITION_END` | `"end"` | … an der Seite des Leseendes
`POSITION_TOP` | `"top"` | … darüber
`POSITION_BOTTOM` | `"bottom"` | … darunter
`POSITION_STACK` | `"stack"` | Das Panel wird als Registerkarte auf das Referenz-Panel gestapelt. Dieser Wert gilt, wenn `as_position` leer ist

### Eigenschaften eines Panels — `n_pbt_dock_panel` #

Über `of_item(schluessel)` zu erhalten.

Eigenschaft | Typ | Standard | Zweck
--- | --- | --- | ---
`is_title` | string | `""` | Titel, der auf der Registerkarte des Panels angezeigt wird. Akzeptiert die Rich-Text-Auszeichnung
`is_short_title` | string | `""` | Kurzform des Titels für die Stellen mit wenig Platz: die Randleiste eines angehefteten Panels (immer — sie ist ein schmaler Streifen) und eine gestapelte Registerkarte, aber erst, wenn der volle Titel dort nicht mehr passt, was gemessen und nicht geraten wird. Die Kopfzeile des Panels behält den vollen Titel. `""` = keine Kurzform
`ib_visible` | boolean | `true` | Blendet dieses Panel ein oder aus
`ib_pinned` | boolean | `true` | `true` = an Ort und Stelle fixiert; `false` = das Panel klappt zu einer Lasche am Rand zusammen und fährt nur aus, wenn der Mauszeiger darüber steht (automatisches Ausblenden)
`is_header_color` | string | `""` | Kopfzeilenfarbe dieses Panels. Leer = das Thema entscheidet; `HEADER_COLOR_ACCENT` folgt der Themenakzentfarbe (auch nach einem Themenwechsel, anders als ein fester Code); sonst ein `#rrggbb`. Die lesbare Textfarbe wird mitgeliefert
`is_border_color` | string | `""` | Rahmenfarbe dieses Panels, gleiche Schreibweise. Sie umrandet den Rahmen und die Kopfzeile, die jeweils eine eigene besitzen: nur eine davon zu färben hinterlässt eine sichtbare Naht. Sie folgt dem Panel in sein Flyout
`is_tooltip` | string | `""` | Einfacher Tooltip beim Überfahren des Items
`is_super_tooltip_title` | string | `""` | Titel des erweiterten Item-Tooltips (hat Vorrang vor `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Text des erweiterten Item-Tooltips (Rich-Markup zulässig)
`is_super_tooltip_image` | string | `""` | Bild des erweiterten Item-Tooltips

## Methoden #

Methode | Zweck
--- | ---
`of_add_panel (string as_key, string as_position, string as_relative_to, integer ai_size, string as_title, dragobject ado_content)` | Fügt ein schließbares Panel hinzu und hostet das Steuerelement. `as_relative_to` = Schlüssel des Panels, an dem es andockt (leer = die Wurzel); `ai_size` = Anfangsgröße in Pixeln (`0` = automatisch)
`of_add_panel (…, boolean ab_closable)` | Dasselbe, mit `ab_closable = false` für ein Panel ohne Schließen-Schaltfläche
`of_select_panel (string as_key)` | Holt ein Panel in seiner Registerkartengruppe in den Vordergrund
`of_move_panel (string as_key, string as_target, string as_position)` | Ordnet aus dem Code neu an, genau so, als hätte der Benutzer die Registerkarte gezogen
`of_move_panel (string as_key, string as_target, string as_position, integer ai_index)` | Dasselbe, mit dem Rang des Panels im Stapel des Ziels (0 = erstes, `-1` = letztes). Nur ein Stapel ist eine geordnete Liste: Bei `POSITION_START` / `END` / `TOP` / `BOTTOM` wird der Index ignoriert
`of_float_panel (string as_key)` | Löst das Panel in ein echtes schwebendes Fenster ab, das verschoben und in der Größe geändert werden kann. Wird es geschlossen, dockt das Panel wieder an (`ue_panel_docked`)
`of_notify_panel (string as_key)` | Meldet neuen Inhalt: Ist das Panel nicht sichtbar, zeigt seine Registerkarte einen Zähler ungesehener Elemente, der beim Auswählen gelöscht wird
`of_clear_notify (string as_key)` | Löscht diesen Zähler, ohne das Panel anzuzeigen. Das Auswählen der Registerkarte war der einzige andere Weg, was falsch ist, wenn Ihr Code weiß, dass der Inhalt selbst verschwunden ist
`of_remove_panel (string as_key)` | Entfernt das Panel und gibt das Steuerelement an sein ursprüngliches Fenster zurück
`of_get_layout ( )` | Liefert die aktuelle Anordnung (Baum der Aufteilungen, Verhältnisse, Registerkarten, Sichtbarkeit) als Zeichenkette, bereit zur Ablage in einer Datei, einer Datenbank oder der Registry
`of_set_layout (string as_json)` | Stellt eine mit `of_get_layout` gewonnene Anordnung wieder her. Die Panels müssen vorher neu erstellt worden sein; Panels, die in der Anordnung fehlen, werden an die erste Gruppe angehängt
`of_item (string as_id)` | `n_pbt_dock_panel`-Handle des Panels (beim ersten Zugriff erzeugt)
`of_refresh_panel (string as_key)` | Frischt die Darstellung eines außerhalb des Bildschirms aufgebauten Panels auf, ohne Flackern
`of_relayout ( )` | Berechnet und veröffentlicht alle Bereiche neu, damit die gehosteten Steuerelemente neu positioniert werden
`of_reset ( )` | Leert den Container: Jedes gehostete Steuerelement geht an sein ursprüngliches Fenster zurück, die Panel-Handles werden freigegeben und die gespeicherte Anordnung wird gelöscht
`of_set_redraw (boolean)` | Fasst eine Folge von Änderungen zu einer einzigen Darstellung zusammen
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exportiert die Darstellung als Bild

## Events #

Event | Ausgelöst wenn
--- | ---
`ue_panel_selected (string as_key)` | Ein Panel wird zum aktiven Panel seiner Gruppe
`ue_panel_closed (string as_key)` | Der Benutzer schließt ein Panel
`ue_panel_pinned (string as_key, boolean ab_pinned)` | Ein Panel wird fixiert (`true`) oder für das automatische Ausblenden gelöst (`false`)
`ue_panel_floated (string as_key)` | Ein Panel wird in ein schwebendes Fenster abgelöst
`ue_panel_docked (string as_key)` | Ein schwebendes Panel wird wieder angedockt
`ue_layout_changed (string as_json)` | Die Anordnung hat sich geändert (Ziehen, Größenänderung, Andocken). Der Parameter trägt die neue Anordnung, bereit zum Speichern
`ue_ready ( )` | Die Komponente ist fertig geladen; alles zuvor Gesendete wurde nachgespielt
`ue_runtime_missing ( )` | Die WebView2-Runtime fehlt: die Komponente bleibt leer
`ue_bg_color (long al_color)` | Die Komponente hat ihre Design-Hintergrundfarbe berechnet; das Userobject hat sie bereits übernommen (`backcolor`)

## Über die Tastatur #

Der Inhalt eines Panels ist ein echtes PowerBuilder-Steuerelement: die Tastatur gehört dort Ihrem Code, wie in jedem Fenster. Was die Komponente übernimmt, ist ihr eigener Rahmen — Kopfzeilen, Registerkarten, Splitter:

Taste | Wirkung
--- | ---
Pfeile auf einer Registerkarte | Wechseln zum vorherigen / nächsten Panel der Gruppe und wählen es aus. Eine Registerkartenleiste ist ein einziger Tabulatorstopp
Pos1 / Ende auf einer Registerkarte | Erstes / letztes Panel der Gruppe
Pfeile auf einem Splitter | Verschieben die Trennung um 2 %, nur entlang der Achse des Splitters
Bild auf / Bild ab auf einem Splitter | Dasselbe, in Schritten von 10 %
Esc | Schließt das ausgefahrene Panel, das über eine Randschaltfläche geöffnet wurde

Ein Splitter ist ein fokussierbarer `separator`, der seine Position ansagt; die Schaltflächen der Kopfzeile (abdocken, ausblenden, schließen) tragen einen Namen, und das aktive Panel einer Gruppe ist mit `aria-selected` markiert. Eine Verschiebung über die Tastatur wird genau wie ein Ziehen mit der Maus über `ue_layout_changed` gemeldet.

## Beispiele #

### Ein Fenster im IDE-Stil #

    // open-Event : jeder Inhalt ist ein echtes PB-Steuerelement auf dem Fenster
    uo_dock.of_add_panel("document", "", "", 0, "Dokument", uo_editeur)
    uo_dock.of_add_panel("explorateur", uo_dock.POSITION_START,   "document", 260, "Explorer", uo_arbre)
    uo_dock.of_add_panel("proprietes",  uo_dock.POSITION_END,  "document", 300, "Eigenschaften",  uo_props)
    uo_dock.of_add_panel("sortie",      uo_dock.POSITION_BOTTOM, "document", 200, "Ausgabe",      uo_console)

    // Ein zweites Panel als Registerkarte auf "proprietes" gestapelt
    uo_dock.of_add_panel("aide", uo_dock.POSITION_STACK, "proprietes", 0, "Hilfe", uo_aide)

    uo_dock.is_main = "document"

### Die Anordnung des Benutzers merken und wiederherstellen #

    // close-Event des Fensters : speichern, was der Benutzer angeordnet hat
    string ls_disposition
    ls_disposition = uo_dock.of_get_layout()
    of_enregistrer_preference("dock_principal", ls_disposition)

    // open-Event : die Panels ZUERST neu erstellen, danach wiederherstellen
    string ls_disposition

    of_creer_les_panneaux()          // die of_add_panel-Aufrufe von oben

    ls_disposition = of_lire_preference("dock_principal")
    if ls_disposition <> "" then uo_dock.of_set_layout(ls_disposition)

> Die Reihenfolge ist zwingend: `of_set_layout` erzeugt kein Panel, es ordnet nur die bereits vorhandenen neu an.

### Änderungen fortlaufend verfolgen #

    // ue_layout_changed-Event von uo_dock : (string as_json)
    // Sofort gespeichert, ohne auf das Schliessen des Fensters zu warten.
    of_enregistrer_preference("dock_principal", as_json)

### Ein Panel über sein Handle steuern #

    n_pbt_dock_panel lnv_panneau

    lnv_panneau = uo_dock.of_item("proprietes")
    lnv_panneau.is_title  = "Eigenschaften (3 geändert)"
    lnv_panneau.ib_pinned = false        // klappt zu einer Lasche am Rand zusammen

    // Ein Panel ausblenden, das Administratoren vorbehalten ist
    uo_dock.of_item("audit").ib_visible = gb_administrateur

### Aufmerksamkeit auf ein Panel im Hintergrund lenken #

    // Ein Hintergrundvorgang hat in die Konsole geschrieben : melden, ohne den Fokus zu stehlen
    uo_dock.of_notify_panel("sortie")

### Aus dem Code neu anordnen #

    // Ein Panel verschieben, als haette der Benutzer seine Registerkarte gezogen
    uo_dock.of_move_panel(/*schluessel*/ "sortie", /*ziel*/ "document", /*position*/ "bottom")

    // Es als Registerkarte auf ein anderes Panel stapeln
    uo_dock.of_move_panel(/*schluessel*/ "aide", /*ziel*/ "proprietes", /*position*/ "stack")

### Ein Panel auf einen zweiten Bildschirm ablösen #

    // Natives schwebendes Fenster : der Benutzer kann es auf einen anderen Bildschirm legen
    uo_dock.of_float_panel("proprietes")

    // ue_panel_docked-Event von uo_dock : (string as_key)
    // Der Benutzer hat das schwebende Fenster geschlossen : das Panel ist zurueck.
    of_journaliser("Panel wieder angedockt : " + as_key)

### Ein Panel sauber schließen #

    // ue_panel_closed-Event von uo_dock : (string as_key)
    // Das Panel auch aus dem Container entfernen, um das gehostete Steuerelement freizugeben.
    uo_dock.of_remove_panel(as_key)

## Best Practices #

- Legen Sie immer ein Haupt-Panel mit `is_main` fest: Ohne zentralen Bereich können die Benutzer alles ausblenden und stehen vor einem leeren Fenster.
- Speichern Sie die Anordnung bei `ue_layout_changed` statt nur beim Schließen: So geht bei einem unsauberen Beenden nichts verloren.
- `of_set_layout` kommt nach den `of_add_panel`-Aufrufen, niemals davor.
- Verwenden Sie `of_notify_panel` für Hintergrundvorgänge: Das ist weniger aufdringlich als ein Dialogfeld, und die Information bleibt sichtbar.
- Ein gehostetes Steuerelement ist ein natives Fenster: Es zeichnet sich über der Web-Ebene, kein visueller Effekt der Komponente kann darüber liegen.
- Rufen Sie `of_reset()` vor jedem Neuaufbau auf: Ohne diesen Aufruf bleiben die zuvor gehosteten Steuerelemente in den geleerten Container umgehängt, und die Wiederverwendung eines Schlüssels schlägt fehl.
- Für einfache, sich gegenseitig ausschließende Seiten, ohne Andocken und ohne Schweben, ist tab leichtgewichtiger.

← Komponentenreferenz · Inhalt des Handbuchs