initial visual theme thing

This commit is contained in:
Adam D. Ruppe 2021-05-08 09:50:29 -04:00
parent f3d22c9bf4
commit 12149ab75d
1 changed files with 77 additions and 2 deletions

View File

@ -1215,6 +1215,17 @@ struct WidgetPainter {
+/ +/
Rectangle[] invalidatedRectangles; Rectangle[] invalidatedRectangles;
private static IVisualTheme _visualTheme;
static @property IVisualTheme visualTheme() {
if(_visualTheme is null)
_visualTheme = new DefaultVisualTheme();
return _visualTheme;
}
static @property void visualTheme(IVisualTheme theme) {
_visualTheme = theme;
}
// all this stuff is a dangerous experiment.... // all this stuff is a dangerous experiment....
static class ScriptableVersion { static class ScriptableVersion {
@ -2074,7 +2085,10 @@ class Widget {
painter.setClipRectangle(Point(0, 0), width, height); painter.setClipRectangle(Point(0, 0), width, height);
erase(painter); erase(painter);
paint(painter); if(painter.visualTheme)
painter.visualTheme.doPaint(this, painter);
else
paint(painter);
redrawRequested = false; redrawRequested = false;
actuallyPainted = true; actuallyPainted = true;
@ -2838,7 +2852,10 @@ class ScrollableWidget : Widget {
painter.setClipRectangle(scrollOrigin + Point(2, 2) /* border */, width - 4, height - 4); painter.setClipRectangle(scrollOrigin + Point(2, 2) /* border */, width - 4, height - 4);
//erase(painter); // we paintFrameAndBackground above so no need //erase(painter); // we paintFrameAndBackground above so no need
paint(painter); if(painter.visualTheme)
painter.visualTheme.doPaint(this, painter);
else
paint(painter);
actuallyPainted = true; actuallyPainted = true;
redrawRequested = false; redrawRequested = false;
@ -8939,3 +8956,61 @@ interface Reflectable {
So generally the existing virtual functions are just the default for the class. But individual objects So generally the existing virtual functions are just the default for the class. But individual objects
or stylesheets can override this. The virtual ones count as tag-level specificity in css. or stylesheets can override this. The virtual ones count as tag-level specificity in css.
+/ +/
interface IVisualTheme {
void doPaint(Widget widget, WidgetPainter painter);
string getProperty(Widget widget, string propertyName);
final T getProperty(T, string propertyName)(Widget widget) {
return T.init;
}
}
private int baseClassCount(Class)() {
int count = 0;
static if(is(Class bases == super)) {
foreach(base; bases)
static if(is(base == class))
count += 1 + baseClassCount!base;
}
return count;
}
class VisualTheme(CRTP) : IVisualTheme {
string getProperty(Widget widget, string propertyName) { return null; }
final void doPaint(Widget widget, WidgetPainter painter) {
auto derived = cast(CRTP) cast(void*) this;
scope void delegate(Widget, WidgetPainter) bestMatch;
int bestMatchScore;
static if(__traits(hasMember, CRTP, "paint"))
foreach(overload; __traits(getOverloads, CRTP, "paint")) {
static if(is(typeof(overload) Params == __parameters)) {
static assert(Params.length == 2);
static assert(is(Params[0] : Widget));
static assert(is(Params[1] == WidgetPainter));
static assert(is(typeof(&__traits(child, derived, overload)) == delegate));
alias type = Params[0];
if(cast(type) widget) {
auto score = baseClassCount!type;
if(score > bestMatchScore) {
bestMatch = cast(typeof(bestMatch)) &__traits(child, derived, overload);
bestMatchScore = score;
}
}
} else static assert(0, "paint should be a method.");
}
if(bestMatch)
bestMatch(widget, painter);
else
widget.paint(painter);
}
}
final class DefaultVisualTheme : VisualTheme!DefaultVisualTheme {}