1 module common;
2 
3 /* 
4 GUI technology stack:
5 * program text is parsed to
6 * DOM that is traversed by high level renderer that issues
7 * graphics command independent on anything like OS, drivers et al
8 * low level renderer that renders gfx command to target
9 * target - framebuffer, texture etc
10 
11 every visual has x, y (origin), width and height. but all of them may be optional. for example the root visual has x and y equal to zero. Also child visuals parameter can be calculated and doen't need to be set. 
12 
13 Only mandatory values are:
14 	current x, y, width and height. Current x and y are given in parent visual coordinate system.
15 	count of widgets
16 	direction
17 	alignment
18 	justification
19 	wrapping
20 */
21 
22 /// What direction the children are laid out in
23 enum Direction { 
24 	row,           // items are placed in row from start to end
25 	column,        // items are placed in column from start to end
26 	rowReverse,    // items are placed in row from end to start
27 	columnReverse, // items are placed in column from end to start
28 }
29 /// Cross axis aligment
30 enum Alignment { 
31 	stretch,  // items fill the parent in the direction of the cross axis
32 	center,   // items maintain their intrinsic dimensions, but are centered along the cross axis
33 	start,    // items are aligned at the start of the cross axis
34 	end,      // items are aligned at the end of the cross axis
35 }
36 
37 /// Main axis alignment
38 enum Justification {
39 	start,   // items sit at the start of the main axis
40 	end,     // items sit at the end of the main axis
41 	center,  // items sit in the center of the main axis
42 	around,  // items are evenly distributed along the main axis, with a bit of space left at either end
43 	between, // like `around` except that it doesn't leave any space at either end.
44 }
45 
46 struct WorkArea
47 {
48 	float x, y, w, h, margin, padding;
49 }
50 
51 struct Attributes
52 {
53 	import std.typecons : Nullable;
54 
55 	private Nullable!Direction _direction;
56 	private Nullable!int _margin;
57 	private Nullable!int _padding;
58 
59 	ref auto direction()
60 	{
61 		return _direction;
62 	}
63 
64 	ref auto margin()
65 	{
66 		return _margin;
67 	}
68 
69 	ref auto padding()
70 	{
71 		return _padding;
72 	}
73 }
74 
75 /// Full description of current renderer state
76 /// for debug use
77 struct RenderState
78 {
79 	// node(widget) name
80 	string name;
81 	WorkArea area;
82 	Direction direction;
83 
84 	// for debug purposes
85 	long misc;
86 	int nestingLevel;
87 }
88 
89 class DomNode
90 {
91 	bool state;
92 	DomNode[] child;
93 	Attributes attributes;
94 	string name;
95 
96 	this(bool s, DomNode[] ch)
97 	{
98 		state = s;
99 		child = ch;
100 	}
101 }
102 
103 auto makeDom(Data)(Data data)
104 {
105 	import traverse : traverseImpl;
106 
107 	static struct DomMaker
108 	{
109 		DomNode[] current;
110 	}
111 
112 	auto dommaker = DomMaker();
113 	dommaker.current ~= new DomNode(false, null);
114 	traverseImpl!(domLeaf, domNodeEnter, domNodeLeave)(dommaker, data);
115 	assert(dommaker.current.length);
116 	assert(dommaker.current[0].child.length);
117 
118 	return dommaker.current[0].child[0];
119 }
120 
121 auto domLeaf(Context, Data)(ref Context ctx, Data data)
122 {
123 	// do nothing
124 }
125 
126 auto domNodeEnter(Context, Data)(ref Context ctx, Data data)
127 {
128 	import std.array : back;
129 	auto node = new DomNode(false, null);
130 	node.name = typeof(data).stringof;
131 	ctx.current.back.child ~= node;
132 	ctx.current ~= node;
133 }
134 
135 auto domNodeLeave(Context, Data)(ref Context ctx, Data data)
136 {
137 	import std.array : popBack;
138 	ctx.current.popBack;
139 }
140 
141 void printDom(Context, Node)(ref Context ctx, Node mn)
142 {
143 	import std.stdio;
144 	import std.range;
145 
146 	write("\n", "-".repeat(ctx.indent).join, "state: ");
147 	ctx.indent += 4;
148 	scope(exit) ctx.indent -= 4;
149 	write(mn.state, " '", mn.name, "' ", mn.child.length);
150 	foreach(ch; mn.child)
151 		printDom(ctx, ch);
152 }