1 module formoshlep.widget;
2 
3 import tags = dhtags.tags;
4 import attrs = dhtags.attrs;
5 import dhtags.tags.tag: HtmlFragment, HtmlString;
6 import vibe.http.server: HTTPServerRequest;
7 import std.conv: to;
8 import dlangui.core.events;
9 import openmethods;
10 mixin(registerMethods);
11 
12 package:
13 
14 struct FormoEvent
15 {
16     KeyEvent keyEvent;
17     MouseEvent mouseEvent;
18 }
19 
20 // Custom Widget methods:
21 void readState(virtual!Widget, HTTPServerRequest);
22 FormoEvent[] getEvents(virtual!Widget, HTTPServerRequest);
23 HtmlFragment toHtml(virtual!Widget);
24 
25 void readWidgetsState(Widget w, HTTPServerRequest req)
26 {
27     w.readState(req);
28 
29     for(auto i = 0; i < w.childCount; i++)
30         w.child(i).readWidgetsState(req);
31 }
32 
33 void processEvents(Widget w, HTTPServerRequest req)
34 {
35     FormoEvent[] events = w.getEvents(req);
36 
37     foreach(e; events)
38     {
39         if(e.keyEvent !is null)
40             w.onKeyEvent(e.keyEvent);
41 
42         if(e.mouseEvent !is null)
43             w.onMouseEvent(e.mouseEvent);
44     }
45 
46     for(auto i = 0; i < w.childCount; i++)
47         w.child(i).processEvents(req);
48 }
49 
50 public:
51 
52 // Custom methods implementation:
53 import dlangui.widgets.widget: Widget;
54 @method void _readState(Widget w, HTTPServerRequest req) {}
55 @method FormoEvent[] _getEvents(Widget w, HTTPServerRequest req) { return null; }
56 @method HtmlFragment _toHtml(Widget w) { assert(false, "HTML output isn't implemented"); }
57 
58 import dlangui.widgets.controls: TextWidget;
59 @method HtmlFragment _toHtml(TextWidget w)
60 {
61     return tags.span(w.text.to!string).addStyle(w);
62 }
63 
64 import dlangui.widgets.editors: EditLine;
65 @method void _readState(EditLine w, HTTPServerRequest req)
66 {
67     if(req.form.get(w.id, "IMPOSSIBLE_VALUE") != "IMPOSSIBLE_VALUE") //FIXME: remove that shit
68         w.text = req.form.get(w.id).to!dstring;
69 }
70 @method FormoEvent[] _getEvents(EditLine w, HTTPServerRequest req)
71 {
72     import std.exception: enforce;
73 
74     enforce(w.action is null);
75 
76     return null;
77 }
78 @method HtmlFragment _toHtml(EditLine w)
79 {
80     return tags.input(attrs.type="text", attrs.name=w.id, attrs.value=w.text.to!string, attrs.style=w.styleStr);
81 }
82 
83 import dlangui.widgets.controls: Button;
84 @method HtmlFragment _toHtml(Button w)
85 {
86     return tags.input(attrs.type="submit", attrs.name=w.id, attrs.value=w.text.to!string, attrs.style=w.styleStr);
87 }
88 @method FormoEvent[] _getEvents(Button w, HTTPServerRequest req)
89 {
90     if(req.form.get(w.id) is null)
91         return null;
92     else
93         return
94         [
95             FormoEvent(null, new MouseEvent(MouseAction.ButtonDown, MouseButton.Left, 0, -10, -10, 0)),
96             FormoEvent(null, new MouseEvent(MouseAction.ButtonUp,   MouseButton.Left, 0, -10, -10, 0))
97         ];
98 }
99 
100 import dlangui.widgets.controls: ImageWidget;
101 @method HtmlFragment _toHtml(ImageWidget w)
102 {
103     assert(w.drawable !is null);
104 
105     import dlangui.graphics.resources: drawableCache;
106 
107     auto d = w.drawable;
108 
109     return tags.img(attrs.src="/res/"~drawableCache._idToDrawableMap[w.drawableId]._filename, attrs.width=d.width, attrs.height=d.height);
110 }
111 
112 
113 import dlangui.widgets.controls: ImageTextButton;
114 @method HtmlFragment _toHtml(ImageTextButton w)
115 {
116     return
117         tags.button
118         (
119             (cast(LinearLayout) w)._toHtml
120         );
121 }
122 
123 import dlangui.widgets.layouts: LinearLayout, Orientation;
124 @method HtmlFragment _toHtml(LinearLayout w)
125 {
126     final switch(w.orientation)
127     {
128         case Orientation.Horizontal:
129             string ret;
130 
131             for(auto i = 0; i < w.childCount; i++)
132                 ret ~= w.child(i).toHtml.toString(false);
133 
134             return tags.div(attrs.style="width: auto; float: left")(ret);
135 
136         case Orientation.Vertical:
137             string ret;
138 
139             for(auto i = 0; i < w.childCount; i++)
140                 ret ~=
141                     tags.div(attrs.style="clear: both")
142                     (
143                         w.child(i).toHtml
144                     ).toString(false);
145 
146             return tags.div(attrs.style="float: left")(ret);
147     }
148 }
149 
150 private:
151 
152 static this()
153 {
154     updateMethods();
155 }
156 
157 string styleStr(Widget w)
158 {
159     import std.format;
160 
161     auto s = w.ownStyle;
162 
163     return
164         "color: "~s.textColor.format!"#%06X; "~
165         "font-size: "~s.fontSize.to!string~"px; "~
166         "font-weight: "~s.fontWeight.to!string;
167 }
168 
169 import dhtags.tags.tag: HtmlTag;
170 
171 HtmlTag addStyle(HtmlTag tag, Widget w)
172 {
173     import dhtags.attrs.attribute: HtmlAttribute;
174 
175     tag.attrs ~= HtmlAttribute("style", w.styleStr);
176 
177     return tag;
178 }