# 4. Designs und Erscheinungsbild #

← Gemeinsame Basis · Inhalt · Sprache und RTL →

## 4.1 Die Designs: zwei Achsen #

Ein Design besteht aus einem Stil und einem Modus:

Achse | Werte
--- | ---
Stil (`is_theme_style`) | `fluent` · `metro` · `office` · `office2007` · `office2003`
Modus (`is_theme_mode`) | `light` · `dark`

Das ergibt zehn Designs mit dem Namen `<style>-<mode>`: `fluent-light`, `fluent-dark`, `office2007-light`, `metro-dark`…

## 4.2 Das Standarddesign der Anwendung (empfohlen) #

Setzen Sie das Design einmal für die gesamte Anwendung, bevor das erste Fenster geöffnet wird. Es wird in jede Komponente vor deren erstem Rendering eingespeist: kein Aufblitzen eines hellen Stils in einer dunklen Anwendung.

    // Event open des Anwendungsobjekts
    PBT_SetDefaultTheme("fluent-dark")
    PBT_SetDefaultThemeAccent(RGB(0, 120, 212))   // optional

Ein Wechsel im laufenden Betrieb ist jederzeit möglich: Alle bereits geöffneten Komponenten erhalten sofort das neue Design.

    // Umschalten hell / dunkel ueber eine Schaltflaeche der Anwendung
    PBT_SetDefaultTheme("fluent-light")

Funktion | Wirkung
--- | ---
`PBT_SetDefaultTheme (string as_nom)` | Standarddesign des Prozesses (an alle Komponenten verteilt)
`PBT_GetDefaultTheme ( )` → string | Aktuelles Standarddesign
`PBT_SetDefaultThemeAccent (long al_couleur)` | Standard-Akzentfarbe (`-1` = native Akzentfarbe des Designs)
`PBT_GetDefaultThemeAccent ( )` → long | Aktueller Standardakzent

## 4.3 Das Design einer bestimmten Komponente #

Eine Komponente kann vom Standarddesign abweichen:

    uo_editeur.is_theme_style = uo_editeur.THEME_STYLE_OFFICE2007
    uo_editeur.is_theme_mode  = uo_editeur.THEME_MODE_DARK
    uo_editeur.il_theme_accent = RGB(200, 60, 40)     // -1 = Akzent des Designs

Eigenschaft | Typ | Standard | Zweck
--- | --- | --- | ---
`is_theme_style` | string | `fluent` | Visueller Stil (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)

Ein `of_reset()` bringt die Komponente auf das Standarddesign des Prozesses zurück.

> 💡 Am gepflegtesten bleibt ein einziges Design für die gesamte Anwendung. Behalten Sie das lokale Design Sonderfällen vor (einem bewusst kontrastierten Bereich, einer Designvorschau).

## 4.4 Eine Komponente, eine Gruppe oder ein Element umfärben #

Drei Reichweiten, dieselben Eigenschaften. Nichts zu benennen, nichts zu erraten.

    // Die ganze Komponente
    uo_ruban.il_theme_accent = RGB(0, 120, 90)

    // Eine Gruppe : alles darin folgt
    uo_ruban.of_tab("accueil").of_group("presse-papiers").il_accent = RGB(0, 120, 90)

    // Ein Element
    uo_liste.of_item("supprimer").il_text_color = RGB(200, 70, 70)
    uo_liste.of_item("supprimer").il_back_color = RGB(255, 235, 235)

    // Dieselben zwei, unter dem Zeiger
    uo_liste.of_item("supprimer").il_back_color_hover = RGB(255, 220, 220)

    // Zurueck zur Farbe der Komponente
    uo_liste.of_item("supprimer").il_text_color = -1

Eigenschaft | Wo | Was sie umfärbt
--- | --- | ---
`il_theme_accent` | die Komponente | ihren Akzent und alles daraus Abgeleitete: den lesbaren Text darauf, den Anwendungshintergrund, die Registerkarten-Unterstreichung
`il_accent` | ein Element-, Gruppen-, Registerkarten- oder Leisten-Handle | was diese Zone mit dem Akzent malt, einschließlich ihrer Nachfahren
`il_back_color` · `il_text_color` | dito | Hintergrund und Text des Elements
`il_back_color_hover` · `il_text_color_hover` | dito | dieselben zwei, unter dem Zeiger

`-1` stellt die Farbe wieder her, die die Komponente vorgibt und die selbst aus dem Thema stammt. Eine Elementfarbe übersteht den Neuaufbau der Komponente: sie wird von einer Stilregel getragen, die auf das Element zielt, nicht von einer Eigenschaft auf dem Knoten des Augenblicks. `of_reset()` löscht alles.

`il_accent` färbt nur um, was die Zone mit dem Akzent malt — eine Auswahl, eine aktive Unterstreichung, einen Fortschrittsbalken. Eine Komponente, die ihn nie benutzt, zeigt davon nichts: für „diesen Eintrag in Rot“ sind `il_back_color` und `il_text_color` die richtigen Werkzeuge, gelesen von jeder Komponente mit Elementen.

### Die Schrift der ganzen Anwendung #

    PBT_SetDefaultFont("Segoe UI", 14)

Ein Aufruf kleidet jede lebende Komponente und die danach erzeugten — die Schrift wird ihnen vor dem ersten Zeichnen eingespielt. Eine leere Familie oder eine Größe von `0` gibt diese Hälfte dem Thema zurück.

## 4.5 Der Hintergrund der Komponente wird an PowerBuilder gemeldet #

Jede Komponente zeichnet ihren Hintergrund gemäß dem Design und meldet dann ihre Farbe: Das Userobject übernimmt diese Farbe (`backcolor`) und löst `ue_bg_color` aus, damit das Fenster und die benachbarten PowerBuilder-Steuerelemente dazu passen.

    // Event ue_bg_color einer Komponente
    parent.backcolor = al_color
    st_titre.backcolor = al_color

Genau dadurch lassen sich PBToolboxAI-Komponenten und native PowerBuilder-Steuerelemente im dunklen Design ohne sichtbaren Übergang mischen.

## 4.6 Bilder und Symbole #

Überall dort, wo eine Komponente einen Bildpfad erwartet (Symbol einer Schaltfläche, Kachel, `[picture=…]`…), werden vier Formen akzeptiert:

Form | Beispiel | Verwendung
--- | --- | ---
Datei | `img\logo.png` | Bild unverändert (png, jpg, gif, bmp, ico, svg, webp)
DLL-Ressource | `img\packimages.dll:RIBBON` | In einer Ressourcen-DLL verpacktes Bild
`mono:` | `mono:img\save.svg` | Einfarbige Fläche in der Designfarbe: nur die Form zählt
`tint:` | `tint:img\logo_couleur.png` | Duotone: Die innere Schattierung moduliert die Designfarbe

- `mono:` verwenden Sie für alle einfarbigen Glyphen (weiße oder schwarze Symbole): Sie werden im hellen wie im dunklen Design automatisch umgefärbt.
- `tint:` harmonisiert ein farbiges Symbol mit dem Design und erhält dabei seine Verläufe. Niemals auf einer weißen Glyphe verwenden (sie bliebe weiß).
- Ohne Präfix bleibt das mehrfarbige Bild unverändert.

Die Form `pfad.dll:name` lädt eine Ressource aus einer Bilder-DLL (nach Art von `packimages.dll`), die schreibgeschützt geöffnet wird (`LOAD_LIBRARY_AS_DATAFILE`, es wird kein Code ausgeführt). So müssen Sie nicht Hunderte einzelner Dateien ausliefern.

### Sofortige Anzeige: `of_icon` #

Eine kleine Glyphe, die über `of_icon()` übergeben wird, ist in den Befehl eingebettet (kein Ladevorgang hin und zurück): Sie erscheint schon beim ersten Rendering, ohne das Flackern eines nachträglich geladenen Symbols.

    lnv_bar.of_add_button("save", "Speichern", uo_toolbar.of_icon("mono:img\save.svg"))

Im Gebrauch transparent: Ab einer bestimmten Größe liefert `of_icon` den ursprünglichen Pfad zurück (das Bild wird dann wie gewohnt geladen und zwischengespeichert).

## 4.7 Rich-Text-Auszeichnung #

Jede beliebige Beschriftung jeder Komponente akzeptiert eine Auszeichnung nach Art von BBCode: Titel einer Registerkarte, Beschriftung einer Schaltfläche, Text der Statusleiste, Toast-Meldung, Titel eines Panels, Text eines Tooltips…

Die Einträge der integrierten Menüs folgen derselben Regel — Kontextmenü einer Registerkarte, `···`-Liste der nicht mehr passenden Registerkarten, Spaltenmenüs eines Rasters: Die im Menü angezeigte Beschriftung ist die des Steuerelements, samt Auszeichnung.

Der Text wird als Textknoten und `<span>` gerendert: eine HTML-Injektion ist nicht möglich.

Tag | Wirkung
--- | ---
`[b] [i] [u] [s]` / `[strike]` | Fett, kursiv, unterstrichen, durchgestrichen
`[sub] [super]` | Tiefgestellt, hochgestellt
`[red]…[/red]` (benannte Farben) | Textfarbe (`red`, `green`, `blue`, `orange`, `teal`…)
`[accent]…[/accent]` | Akzentfarbe des aktuellen Designs
`[color=#rrggbb]` / `[color=accent]` | Textfarbe
`[bk=#rrggbb]` / `[backcolor=accent]` | Hintergrundfarbe
`[font=Consolas]` | Schriftart
`[size=14]` | Absolute Größe in Punkt (6 bis 200)
`[size+=30]` / `[size-=20]` | Relative Größe in % (standardmäßig 20 %)
`[picture=pfad]` / `[picture=pfad,breite,höhe]` | Eingebettetes Bild
`[br]` / `[linebreak]` / `[br:3]` | Zeilenumbruch (oder n Umbrüche)
`[separator]` | Waagerechte Linie
`[hyperlink=url]…[/hyperlink]` | Klickbarer Bereich: Der Link öffnet sich immer im Browser des Benutzers, in jeder Komponente. Das Event `ue_hyperlink(as_url)` wird zusätzlich ausgelöst, bei den Komponenten, die es anbieten
`[action=id]…[/action]` | Klickbarer Bereich → Event `ue_action(as_id)`, als Link dargestellt
`[invisibleaction=id]…[/invisibleaction]` | Klickbarer Bereich → `ue_action`, ohne den Linkstil
`[bullet]…[/bullet]` | Aufzählungspunkt: Listeneintrag, dessen Folgezeilen an der ersten ausgerichtet werden statt unter dem Zeichen (hängender Einzug). `[bullet=-]` ändert das Zeichen
`[foldarea:Titel]…[/foldarea]` | Einklappbarer Block: anklickbare Kopfzeile (`−` / `+`) über einem eingerückten Inhalt. Der Titel akzeptiert Auszeichnungen
`[foldarea-closed:Titel]…[/foldarea]` | Derselbe Block, bei der Anzeige eingeklappt
`[[` / `]]` | Maskierung: `[[b]]` zeigt `[b]` an, ohne es zu interpretieren

    uo_texte.is_text = "Willkommen bei [b][accent]PBToolboxAI[/accent][/b] [size-=20]v1.0[/size-=20]" &
                       + "[br]Lesen Sie die [hyperlink=https://pbtoolboxai.net]Dokumentation[/hyperlink]."

    uo_tab.of_add_page("clients", "[b]Kunden[/b] [size-=20](128)[/size-=20]", uo_clients)

    uo_st.is_text = "Das Tag [[b]] macht [b]fett[/b]"   // zeigt an: Das Tag [b] macht fett

Daten unverändert anzeigen. Ein Wert aus Ihrer Datenbank kann Klammern enthalten: Er würde interpretiert. `of_escape_markup()`, auf jeder Komponente verfügbar, verdoppelt sie für Sie — umschließen Sie die Daten, nie die Auszeichnung, die Sie selbst geschrieben haben.

    // Fachdaten koennen Klammern enthalten : ohne Maskierung werden sie
    // INTERPRETIERT und der Text in Klammern verschwindet.
    ls_libelle = "Saldo [netto]"
    uo_st.is_text = "Konto : " + ls_libelle                          // zeigt : Konto :
    uo_st.is_text = "Konto : " + uo_st.of_escape_markup(ls_libelle)  // zeigt : Konto : Saldo [netto]

Ein Text ohne Tag verursacht keinerlei Mehraufwand (schneller Pfad). Unbekannte Tags werden ignoriert und ihr Inhalt bleibt erhalten. Ein `[hyperlink]` öffnet sich überall — Beschriftung, Registerkartentitel, Statusleistenfeld, Toast, Dialog: der Unterbau erledigt das. Das Event `ue_action` dagegen wird nur von interaktiven Textkomponenten (`statictext`) ausgegeben; anderswo dient `[action]` allein der Formatierung.

Nur `http`, `https` und `mailto` werden geöffnet. Eine Beschriftung trägt oft Daten aus Ihrer Datenbank: dem System ein beliebiges Schema zu übergeben, würde eine Beschriftung in einen Programmstarter verwandeln.

Ein `[foldarea]` ist ein Block: Er nimmt die gesamte Breite ein und klappt bei einem Klick auf seine Kopfzeile ein — ohne Umweg über PowerBuilder. Blöcke lassen sich verschachteln, und wenn die Komponente der Höhe ihres Inhalts folgt (`ib_auto_height`), wird diese Höhe bei jedem Ein- und Ausklappen erneut gemeldet. Der Titel ist ebenfalls Auszeichnungstext: Nichts wird für Sie fett gesetzt, `[foldarea:[b]Total[/b]]` erledigt das.

← Gemeinsame Basis · Inhalt · Sprache und RTL →