1 module dlangui.widgets.metadata;
2 
3 import dlangui.widgets.widget;
4 
5 interface WidgetMetadataDef {
6     Widget create();
7     /// short class name, e.g. "EditLine"
8     string className();
9     /// module name, e.g. "dlangui.widgets.editors"
10     string moduleName();
11     /// full class name, e.g. "dlangui.widgets.editors.EditLine"
12     string fullName();
13 }
14 
15 struct WidgetSignalMetadata {
16     string name;
17     string typeString;
18     //TypeTuple
19     TypeInfo returnType;
20     TypeInfo paramsType;
21 }
22 
23 private __gshared WidgetMetadataDef[string] _registeredWidgets;
24 
25 WidgetMetadataDef findWidgetMetadata(string name) {
26     if (auto p = name in _registeredWidgets) 
27         return *p;
28     return null;
29 }
30 
31 void registerWidgetMetadata(string name, WidgetMetadataDef metadata) {
32     _registeredWidgets[name] = metadata;
33 }
34 
35 WidgetSignalMetadata[] getSignalList(alias T)() {
36     WidgetSignalMetadata[] res;
37     foreach(m; __traits(allMembers, T)) {
38         static if (__traits(compiles, (typeof(__traits(getMember, T, m))))){
39             // skip non-public members
40             static if (__traits(getProtection, __traits(getMember, T, m)) == "public") {
41                 static if (__traits(compiles, __traits(getMember, T, m).params_t ) && __traits(compiles, __traits(getMember, T, m).return_t)) {
42                     alias ti = typeof(__traits(getMember, T, m));
43                     res ~= WidgetSignalMetadata(m, 
44                                                 __traits(getMember, T, m).return_t.stringof ~ __traits(getMember, T, m).params_t.stringof,
45                                                 typeid(__traits(getMember, T, m).return_t),
46                                                 typeid(__traits(getMember, T, m).params_t));
47                 }
48             }
49         }
50     }
51     return res;
52 }
53 
54 string generateMetadataClass(alias t)() {
55     //pragma(msg, moduleName!t);
56     import std.traits;
57     //pragma(msg, getSignalList!t);
58     immutable string metadataClassName = t.stringof ~ "Metadata";
59     return "class " ~ metadataClassName ~ " : WidgetMetadataDef { \n" ~
60         "    override Widget create() {\n" ~
61         "        return new " ~ moduleName!t ~ "." ~ t.stringof ~ "();\n" ~
62         "    }\n" ~
63         "    override string className() {\n" ~
64         "        return \"" ~ t.stringof ~ "\";\n" ~
65         "    }\n" ~
66         "    override string moduleName() {\n" ~
67         "        return \"" ~ moduleName!t ~ "\";\n" ~
68         "    }\n" ~
69         "    override string fullName() {\n" ~
70         "        return \"" ~ moduleName!t ~ "." ~ t.stringof ~ "\";\n" ~
71         "    }\n" ~
72         "}\n";
73 }
74 
75 string generateRegisterMetadataClass(alias t)() {
76     immutable string metadataClassName = t.stringof ~ "Metadata";
77     return "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ metadataClassName ~ "());\n";
78 }
79 
80 string registerWidgets(T...)(string registerFunctionName = "__gshared static this") {
81     string classDefs;
82     string registerDefs;
83     foreach(t; T) {
84         //pragma(msg, t.stringof);
85         //pragma(msg, moduleName!t);
86         //
87         immutable string classdef = generateMetadataClass!t;
88         //pragma(msg, classdef);
89         immutable string registerdef = generateRegisterMetadataClass!t;
90         //pragma(msg, registerdef);
91         classDefs ~= classdef;
92         registerDefs ~= registerdef;
93         //registerWidgetMetadata(T.stringof, new Metadata());
94     }
95     return classDefs ~ "\n" ~ registerFunctionName ~ "() {\n" ~ registerDefs ~ "}";
96 }
97 
98 /// returns true if passed name is identifier of registered widget class
99 bool isWidgetClassName(string name) {
100     return (name in _registeredWidgets) !is null;
101 }
102