Inhaltsverzeichnis
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:
- Palette — Basis-Farbdefinitionen
- Tokens — Semantische Zuordnung von UI-Elementen zu Palettenfarben
- StateMap — Farbzuordnung für visuelle Zustände (Normal, Hover, Pressed, …)
- Elements — SVG- und PNG-Grafiken für UI-Bauteile (Scrollbars, Tabs, Buttons, …)
- 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.