Skin-Vertrag

Der Skin-Vertrag definiert, wie die Shell und ihre Add-ins visuell gestaltet werden. Er besteht aus einer Farbpalette, semantischen Tokens, einer Zustandsabbildung, Grafik-Elementen und Größen-Properties. Jedes Skin-Paket implementiert diesen Vertrag, und der Host wendet ihn auf alle Controls an — sowohl die eigenen als auch die der Add-ins.

Für Add-in-Entwickler bedeutet das: Wenn ein Add-in Standard-LCL-Controls verwendet, wird es automatisch korrekt geskinnt. Nur Add-ins mit eigener Zeichenlogik müssen den Skin-Vertrag aktiv abfragen und die richtigen Tokens verwenden.

Die Shell liefert zwei Skins aus: WShell (kühles Blau-Grau, Light + Dark) und Meadow (warme Cremetöne mit Terracotta-Akzent, nur Light). Beide implementieren denselben Vertrag mit identischer Token-Struktur — nur die Palettenwerte unterscheiden sich. Alle Beispiele auf dieser Seite zeigen beide Skins im Vergleich.

Zurück zur Übersicht.

Mitgelieferte Skins

Die Shell enthält zwei vorgefertigte Skins, die im Skin-Picker unter der Kategorie WShell nebeneinander stehen.

WShell

WShell ist das Standard-Skin mit einer kühlen Blau-Grau-Palette, inspiriert von modernen IDE-Oberflächen. Es bietet eine Light- und eine Dark-Variante. Die Akzentfarbe ist ein sattes Blau (#005FB8), das für Links, aktive Tabs und Fokus-Indikatoren verwendet wird.

Meadow

Meadow ist ein warmes Skin mit cremefarbenen Hintergründen, sanften Beige-Borders und einem Terracotta-Akzent (#C15F3C). Es bietet ausschließlich eine Light-Variante. Die Farbgebung orientiert sich an natürlichen, erdigen Tönen und erzeugt eine augenschonende Arbeitsumgebung, die sich bewusst vom kühlen Standard abhebt.

Die folgende Tabelle vergleicht die wichtigsten Palettenwerte beider Skins:

Token WShell Meadow Rolle
Background0 #F8F8F8 #F4F3EE Haupt-Hintergrund
Foreground100 #3B3B3B #2D2B27 Primärer Text
PrimaryBackground0 #005FB8 #C15F3C Akzentfarbe
EditBackground0 #FFFFFF #FDFCFA Editierfläche
EditBackground-100 #ADD6FF #F0D6C8 Selektion
Line100 #CECECE #C8C3B8 Starke Border
SecondaryBackground0 #E5E5E5 #E8E5DE Sekundär-Fläche
Brush #3B3B3B #2D2B27 SVG-Strich
Paint #F8F8F8 #F4F3EE SVG-Füllung
AccentPaint #005FB8 #C15F3C SVG-Akzent

Beide Skins teilen dieselben SVG-Elemente, dieselbe Token-Struktur und dieselbe StateMap. Nur die Palette unterscheidet sich. Add-ins, die den Skin-Vertrag korrekt einhalten, funktionieren in beiden Skins automatisch.

Aufbau eines Skins

Ein Skin besteht aus einer manifest.json-Datei und einem Verzeichnis mit Grafik-Elementen. Die Manifest-Datei folgt dem Schema WvdS.SkinPackage/1.0 und enthält fünf Abschnitte:

  1. Palette — Basis-Farbdefinitionen
  2. Tokens — Semantische Zuordnung von UI-Elementen zu Palettenfarben
  3. StateMap — Farbzuordnung für visuelle Zustände (Normal, Hover, Pressed, …)
  4. Elements — SVG- und PNG-Grafiken für UI-Bauteile (Scrollbars, Tabs, Buttons, …)
  5. Properties — Abstände, Schriftgrößen, Rahmenbreiten und Rendering-Optionen

Palette

Die Palette definiert die Grundfarben als Hex-Werte. Alle anderen Teile des Skins referenzieren ausschließlich Palettennamen, niemals rohe Hex-Werte. Dadurch kann ein Dark-Theme die gesamte Farbgebung ändern, indem es nur die Palette überschreibt.

Hintergrundfarben

Token Light Verwendung
Background0 #F8F8F8 Haupt-Hintergrund (Controls, Panels)
Background100 #F8F8F8 Gleiche Stufe wie Background0
Background-100 #E5E5E5 Abgedunkelter Hintergrund (Sidebar-Headers)
Background200 #FFFFFF Hellerer Hintergrund (Menüs, Popups)
Background-200 #D4D4D4 Dunkelster Hintergrund der Neutral-Reihe

Die Namenskonvention folgt einem Intensitätssystem: 0 ist der Basiswert, positive Zahlen (100, 200) werden heller, negative (-100, -200) werden dunkler. In der Dark-Variante kehrt sich die Richtung um — 100 wird dunkler und -100 heller.

Vordergrundfarben

Token Light Verwendung
Foreground100 #3B3B3B Primärer Text (volle Intensität)
Foreground50 #616161 Sekundärer Text (mittlere Intensität)
Foreground25 #ACACAC Deaktivierter Text (niedrige Intensität)

Die Zahlen 100, 50, 25 stehen für die relative Kontrastwirkung. Foreground100 hat den höchsten Kontrast zum Hintergrund, Foreground25 den niedrigsten. Dieses System macht es einfach, Texthierarchien zu gestalten, ohne über konkrete Farbwerte nachdenken zu müssen.

Editor-Farben

Token Light Verwendung
EditBackground0 #FFFFFF Editierbare Fläche (Eingabefelder, Code-Editor)
EditBackground-50 #F8F8F8 Alternierende Zeilen in Grids
EditBackground-100 #ADD6FF Selektion in editierbaren Controls
EditBackground-200 #D0D0D0 Hover-Zustand in editierbaren Controls
EditForeground100 #3B3B3B Text in editierbaren Controls
EditForeground50 #A0A0A0 Placeholder-Text in Eingabefeldern

Primärfarben (Akzent)

Token Light Verwendung
PrimaryBackground0 #005FB8 Primäre Akzentfarbe (Links, aktive Elemente)
PrimaryBackground-100 #004E99 Hover über Akzent-Elementen
PrimaryBackground-200 #003D7A Gedrückter Zustand auf Akzent-Elementen
PrimaryBackground100 #B0D4F1 Heller Akzent-Hintergrund (Badges, Markierungen)
PrimaryForeground100 #FFFFFF Text auf Akzent-Hintergrund
PrimaryForeground25 #B0D4F1 Dezenter Text auf Akzent-Hintergrund

Die Primärfarbe ist die Hauptakzentfarbe der Anwendung. Sie wird für interaktive Elemente verwendet: Links, aktive Tabs, ausgewählte Baumknoten und Fokus-Indikatoren. In der Dark-Variante wechselt der Basiswert von #005FB8 zu #0078D4.

Sekundärfarben

Token Light Verwendung
SecondaryBackground0 #5F6A79 Sekundäre UI-Elemente (Tags, Badges)
SecondaryBackground-100 #4C5563 Hover-Zustand auf sekundären Elementen
SecondaryBackground-200 #3A414D Gedrückter Zustand
SecondaryForeground100 #FFFFFF Text auf sekundärem Hintergrund

Linien und Rahmen

Token Light Verwendung
Line100 #CECECE Starke Trennlinien (Bereichsgrenzen)
Line50 #E5E5E5 Mittlere Trennlinien (innerhalb von Panels)
Line25 #F0F0F0 Dezente Trennlinien (Grid-Zeilen)

Statusfarben

Token Light Verwendung
Red #E51400 Fehler, kritische Zustände
Green #60A917 Erfolg, Bestätigungen
Blue #0050EF Informationen, Links
Yellow #E3C800 Warnungen

Brush- und Paint-Farben

Das Brush/Paint-System ist die interne Farbmaschine für SVG-Elemente. Es trennt Vordergrund (Brush) und Hintergrund (Paint) konsequent:

Token Light Rolle
Brush #444444 Primärer Strich (Icons, Glyphen)
BrushLight #808080 Dezenter Strich (inaktive Elemente)
BrushMajor #999999 Strich für deaktivierte Zustände
BrushMinor #B3B3B3 Noch dezenterer Strich
Paint #F3F3F3 Primäre Füllung (Hintergrund)
PaintHigh #FFFFFF Helle Füllung (fokussierte Elemente)
PaintShadow #E0E0E0 Schatten-Füllung
PaintDeepShadow #C8C8C8 Tieferer Schatten
AccentPaint #005FB8 Akzent-Füllung (aktive/hovere Elemente)
AccentPaintDark #004A8F Dunkle Akzent-Füllung (gedrückter Zustand)
AccentPaintLight #3388CC Helle Akzent-Füllung
AccentPaintLighter #CCE4F7 Hellste Akzent-Füllung (Hover-Hintergrund)
AccentBrush #FFFFFF Strich auf Akzent-Hintergrund
AccentBrushLight #B0D4F1 Dezenter Strich auf Akzent-Hintergrund

UI-spezifische Farben

Neben den generischen Palettenfarben definiert das Skin auch Farben für spezifische Shell-Bereiche:

Token Verwendung
TitleBarBackground Titelleiste der Anwendung
TitleBarText Text in der Titelleiste
RibbonTabStripBg Hintergrund der Ribbon-Tab-Leiste
ButtonBg, ButtonHoverBg Buttons (normal, Hover)
ButtonSecondaryBg, ButtonSecondaryFg Sekundäre Buttons
CheckboxBg, CheckboxBorder Checkboxen
DropdownBg, DropdownBorder, DropdownListBg Dropdown-Controls
MenuBg, MenuBorder Popup-Menüs
NotificationBg, NotificationBorder Benachrichtigungen
EditorGutterAdded, EditorGutterDeleted, EditorGutterModified Git-Indikatoren im Editor-Gutter
SearchResultHighlightColor Hervorhebung von Suchergebnissen
ResourceColor01 bis ResourceColor12 Zwölf Kategoriefarben (Kalender, Tags, Diagramme)

Tokens

Tokens bilden die Brücke zwischen einem UI-Element und seiner Palettenfarbe. Ein Token sagt: „Dieses UI-Element verwendet diese Palettenfarbe.“ Wenn sich die Palette ändert (weil der Benutzer das Theme wechselt), ändern sich automatisch alle UI-Elemente, die auf die betroffenen Palettenfarben verweisen.

Auszug aus den wichtigsten Tokens:

Token Palettenfarbe Bedeutung
BackColor PrimaryBackground0 Primärer Hintergrund aktiver Elemente
ContentColor EditBackground0 Inhaltsbereich (Editoren, Grids)
SelectionColor EditBackground-100 Selektion in Listen und Grids
HotTrackedColor EditBackground-200 Hover-Hervorhebung
DisabledTextColor Foreground25 Deaktivierter Text
TabHeaderTextColor Foreground100 Text in Tab-Reitern
HyperLinkTextColor PrimaryBackground0 Hyperlinks
GridLikeControlContentEvenColor EditBackground-50 Alternierende Grid-Zeilen
SpreadSheetSelectionColor PrimaryBackground0 Zellauswahl in Tabellen

Zustandsabbildung (StateMap)

Die StateMap definiert, wie Farben sich mit dem visuellen Zustand eines Controls ändern. Jeder Zustand hat zwei Farbkanäle: Mask (Strichfarbe/Vordergrund) und Element (Füllfarbe/Hintergrund).

Zustand Mask Element Wann
Normal Brush Paint Ruhezustand, kein Benutzer-Input
Hot AccentPaint AccentPaintLighter Maus schwebt über dem Element
Pressed AccentPaintDark AccentPaintLight Element wird gedrückt (Mausklick)
Disabled BrushMajor Paint Element ist deaktiviert
Focused AccentPaint PaintHigh Element hat den Tastaturfokus
Active White AccentPaint Element ist aktiv (ausgewählter Tab)
ActiveHot White Red Aktives Element wird überfahren
Checked AccentPaint AccentPaintLight Checkbox/Radio ist angehakt
CheckedHot AccentPaintDark AccentPaintLighter Angehaktes Element wird überfahren
CheckedDisabled BrushMajor PaintShadow Angehaktes Element ist deaktiviert
Inactive BrushLight PaintShadow Fenster ist nicht im Vordergrund
Minimized BrushLight Paint Fenster ist minimiert
DroppedDown AccentPaint AccentPaintLight Dropdown ist geöffnet

Die StateMap ist zentral für die SVG-Farbersetzung. SVG-Grafiken verwenden die Platzhalterfarben #707070 (wird zu Mask ersetzt) und #000000 (wird zu Element ersetzt). Der Host rendert dasselbe SVG in verschiedenen Zuständen, indem er die Platzhalter durch die Zustandsfarben ersetzt.

Grafik-Elemente

Das Skin liefert über 70 SVG- und PNG-Grafiken für UI-Bauteile. Jedes Element hat einen Namen, einen Dateipfad und Metadaten:

Kategorie Elemente Beschreibung
Bar/Toolbar BarCustomize, BarDragGrip, BarSubItemArrow Toolbar-Bedienelemente
Tabs TabButtonVert, TabGroupButton, TabHeaderCloseButton Tab-Reiter und Schließen-Button
Navigation Navigator, NavigatorGlyphs Baumknoten-Grafiken (Expand/Collapse)
Scrollbar ScrollButton, ScrollButtonGlyphs Scrollleisten-Pfeile
Checkboxen CheckEditGlyphs, RadioButton, RadioButtonGlyphs Häkchen, Kreise, Punkte
Menü PopupMenuCheck Menü-Häkchen
Dock DockWindowButtonGlyphs Schließen/Minimieren für Dockfenster
StatusBar StatusBarBackground Hintergrundform der Statusleiste
Toggle ToggleSwitchBackground, ToggleSwitchTrack Ein/Aus-Schalter
Sonstiges LoadingBig, RatingStars, Pushpin, SortShape Ladeanzeige, Bewertung, Pin, Sortierung

Jedes Element kann mehrere Zustands-Varianten enthalten. Die Varianten sind vertikal gestapelt (jeder Zustand hat eine feste Höhe), und der Host wählt anhand der StateMap den passenden Ausschnitt.

Properties

Properties steuern Abstände, Schriftgrößen, Rahmenbreiten und Rendering-Verhalten. Sie sind die dritte Dimension des Skins neben Farbe und Grafik.

Typografie

Property Wert Beschreibung
FontSize 7 Standard-Schriftgröße in Punkten
captionFontSize 9 Überschriften
monoFontSize 10 Monospace-Schrift (Code, Log)
monoFontName Cascadia Mono Monospace-Schriftart
statusBarFontSize 8 StatusBar-Text
FontDelta 4 Größenanpassung für kontextabhängige Skalierung
FontDeltaCompact 2 Kompakte Variante der Größenanpassung
FontBold false Standard-Schriftstärke

Abstände und Padding

Property Wert Beschreibung
HorizontalIndent 12 Horizontaler Einzug in Panels
LeftIndent 16 Linker Einzug (Baumknoten, Listen)
TextPadding 4 Abstand zwischen Text und Rahmen
ChildItemOffset 16 Einrückung von Kind-Elementen in Bäumen
RowIndentNear 10 Abstand am Zeilenanfang
RowIndentFar 10 Abstand am Zeilenende
IndentBetweenRows 2 Vertikaler Abstand zwischen Zeilen
IndentBetweenColumns 2 Horizontaler Abstand zwischen Spalten
DistanceBetweenGroups 0 Abstand zwischen Toolbar-Gruppen
DistanceBetweenRootGroups 8 Abstand zwischen Haupt-Toolbar-Gruppen

Rahmen und Linien

Property Wert Beschreibung
BorderWidth 1 Standard-Rahmenbreite
SelectedBorderWidth 3 Rahmen für ausgewählte Elemente
HighlightedBorderWidth 1 Rahmen für hervorgehobene Elemente
CornerRadius 0 Eckenradius (0 = eckig)

Tabs

Property Wert Beschreibung
ActiveTabHeaderUpGrow 2 Aktiver Tab ragt oben über
ActiveTabHeaderHGrow 5 Aktiver Tab ist horizontal breiter
ActiveTabHeaderDownGrow 1 Aktiver Tab ragt unten über

Alpha-Transparenz

Property Wert Beschreibung
BackColorAlpha 64 Transparenz von Hintergrundflächen
BorderColorAlpha 255 Rahmen vollständig deckend
SelectionColorAlpha 255 Selektion vollständig deckend
PanelBackColorAlpha 224 Panel-Hintergrund leicht transparent

Rendering-Optionen

Property Wert Beschreibung
IsVectorSkin true SVG-Grafiken verwenden (statt PNG)
ApplyEditorAdvancedMode true Erweitertes Editor-Rendering
UseRoundedWindowCorners false Keine abgerundeten Fensterecken
MergeBorders false Rahmen nicht verschmelzen
DisplayCustomizeButtonOutsideQAT true Anpassen-Button außerhalb der QuickBar

Dark-Variante

Das WShell-Skin enthält eine vollständige Dark-Variante. Der Host wechselt zwischen Light und Dark, indem er die Palette austauscht. Die Token-Zuordnungen, die StateMap und die Properties bleiben identisch — nur die Farbwerte ändern sich.

Wesentliche Unterschiede in der Dark-Palette:

Token Light Dark
Background0 #FFFFFF #1E1E1E
Foreground100 #1E1E1E #CCCCCC
PrimaryBackground0 #005FB8 #0078D4
EditBackground0 #FFFFFF #1E1E1E
Line100 #CECECE #444444
Brush #444444 #CCCCCC
Paint #F3F3F3 #2D2D2D

Die Inversion ist konsistent: Was in Light hell ist, ist in Dark dunkel, und umgekehrt. Die Intensitätsstufen bleiben relativ erhalten — Foreground100 ist immer der kontrastreichste Text, Foreground25 immer der dezenteste.

Skin-Vertrag für Add-ins

Add-ins, die Standard-LCL-Controls verwenden (TButton, TEdit, TListView, etc.), werden automatisch geskinnt. Der Host wendet die Palette und die StateMap auf alle Controls an, ohne dass das Add-in etwas tun muss.

Wenn ein Add-in eigene Zeichenlogik verwendet (Canvas.Brush.Color := …), muss es die Skin-Farben über IThemeService abfragen und auf Theme-Wechsel reagieren:

procedure TMyCustomControl.Paint;
begin
  // Nicht: Canvas.Brush.Color := clWhite;
  // Stattdessen: Skin-Token verwenden
  Canvas.Brush.Color := FHost.Theme.GetColor('EditBackground0');
  Canvas.Font.Color := FHost.Theme.GetColor('EditForeground100');
  Canvas.FillRect(ClientRect);
end;
// Auf Theme-Wechsel reagieren
AContext.Subscribe(
  FHost.Theme.OnDidChangeTheme(
    TThemeChangeHandler.Create(
      procedure(const AEventName, APayload: string)
      begin
        Invalidate;  // Neuzeichnen mit neuen Farben
      end
    )
  )
);

Add-ins, die eigene Themes als Contribution bereitstellen, legen eine Theme-Datei an, die die Palette überschreibt. Das Kapitel Manifest beschreibt die Deklaration, und das Paketformat erklärt, wo die Datei im Paket liegt.

Weiter zu Sicherheit oder zurück zur Übersicht.

Zuletzt geändert: den 15.03.2026 um 23:23