====== Themes ======
Das Aussehen liegt **nicht** im Code der Controls, sondern in Themes. Weil
Vega alles selbst zeichnet, bestimmt ein Theme wirklich alles — bis
hinunter zur Titelleiste, die sonst der Fenstermanager malen würde.
===== Zwei Ebenen =====
^ Ebene ^ Was sie bestimmt ^ Wo ^
| ''TTheme'' | Grundfarben, Schriftgröße, Metriken, Skalierung | ''Vega/Theme.lyx'' |
| Stylesheet | Regeln je Controltyp, Zustand, Rolle, Klasse, Teil | ''Vega/Style.lyx'' |
Ein Control fragt zuerst das Stylesheet (''ResolvedStyle''), und was dort
nicht steht, kommt aus dem Theme:
var st: TStyleSet := self.ResolvedStyle();
canvas.FillRect(r, st.GetOr(SP_BACKGROUND, self.Color));
st.Destroy();
===== Der Fünf-Achsen-Selektor =====
Eine Regel greift nach fünf Merkmalen:
* **Typ** — ''button'', ''listView'', ''toolBar'', …
* **Zustand** — ''hover'', ''pressed'', ''checked'', ''disabled'',
''focused'', ''selected''
* **Rolle** — ''role primary'', frei vergebbar
* **Klasse** — ''class gefaehrlich'', frei vergebbar
* **Teil** — ''part header'', ''part thumb'', … für Controls aus
mehreren Flächen
Zustände dürfen geschachtelt werden; daraus wird eine Regel, die **beide**
verlangt:
checked { hover { background: #222222 } }
Ein Teil **erbt** vom Control: was es nicht selbst sagt, kommt von dort.
Ausdrücklich nicht vorhanden und nicht geplant: Selektorenketten und
Rechnungen.
===== .vtheme-Dateien =====
theme "firma.dunkel" extends "vega.dark" {
version 1
mode dark
tokens {
colors { marke: #0057B8 markeHover: #00468F }
metrics { rund: 4 }
}
button {
background: {colors.marke}
hover { background: {colors.markeHover} }
role primary { background: #C00000 }
}
listView {
background: #FFFFFF
part header {
background: #EAEAEA
hover { background: #DCDCDC }
}
}
}
* **''extends''** — alles, was nicht dasteht, kommt vom Basistheme. Eine
Datei muss also nicht vollständig sein.
* **Tokens** — benannte Werte, damit eine Farbe nur an einer Stelle
steht. Eingesetzt wird beim **Laden**, zur Laufzeit stehen überall
fertige Werte; die Kaskade wird dadurch nicht langsamer.
* **Farben** als ''#RRGGBB'' oder ''#RRGGBBAA'', dazu ''rgba(r,g,b,a)''.
===== Laden =====
RegisterThemeFile("themes/mein.vtheme", true); // true = strenger Modus
UseTheme("firma.dunkel");
Im **strengen** Modus ist ein Tippfehler ein Fehler mit Zeilennummer. Im
toleranten wird die Zeile übersprungen und der Rest geladen. Beim
Entwickeln streng, im Auslieferzustand tolerant — dieselbe Zweiteilung wie
beim LFM-Lader.
===== Vorlage =====
''themes/template.vtheme'' listet **jeden** bekannten Typ, Zustand und Teil
als Kommentar. Sie wird erzeugt, nicht von Hand gepflegt:
./.build/gen-theme-template > themes/template.vtheme
Ein fertiges Beispiel liegt in ''themes/corporate.vtheme'', und
''examples/theming.lyx'' zeigt das Umschalten zur Laufzeit.