1 module windowDataLoader;
2 
3 import sdlang;
4 import app;
5 import PixelPerfectEngine.graphics.common;
6 
7 import std.conv;
8 import std.variant;
9 import std.utf;
10 import std.stdio;
11 import elementTypes;
12 import PixelPerfectEngine.concrete.elements;
13 
14 public enum AttributeType{
15 	INTEGER,
16 	ASCIISTRING,
17 	UTFSTRING,
18 	FLOAT,
19 	MULTISTRING,
20 	MULTIUTFSTRING,
21 	LISTBOXELEMENT,
22 	MENUBARELEMENT,
23 }
24 
25 public class WindowData {
26 	private Tag root; /// Stores all the data
27 	public string filename, windowName;
28 	public this(){
29 		root = new Tag();
30 		Tag t0 = new Tag(root, null, "Window");
31 		new Tag(t0, null, "width", [Value(640)]);
32 		new Tag(t0, null, "height", [Value(480 - 16)]);
33 		new Tag(t0, null, "title",[Value("New project")]);
34 		new Tag(t0, null, "name",[Value("NewWindow")]);
35 		new Tag(t0, null, "extraButtons");
36 		new Tag(t0, null, "elements");
37 		windowName = "NewWindow";
38 		//writeln(root.toSDLDocument());
39 	}
40 	public this(string filename){
41 		this.filename = filename;
42 	}
43 	public WindowElement[string] deserialize(string path = this.filename){
44 		root = parseFile(path);
45 		if(!root)
46 			throw new WindowDataException("File access error!");
47 		mainApp.ewh.dw = new DummyWindow(Coordinate(0, 0, root.getTag("Window").getTagValue!int("width"), root.getTag("Window").getTagValue!int("height")), toUTF16(root.getTag("Window").getTagValue!string("title")));
48 		windowName = root.getTag("Window").getTagValue!string("name");
49 		WindowElement[string] result;
50 		foreach(Tag t0; root.expectTag("Window").expectTag("elements").tags){
51 			Coordinate c = Coordinate(t0.expectTagValue!int("Coordinate:left"),t0.expectTagValue!int("Coordinate:top"),t0.expectTagValue!int("Coordinate:right"),t0.expectTagValue!int("Coordinate:bottom"));
52 			WindowElement we;
53 			switch(t0.name){
54 				case "Button":
55 					we = new Button(toUTF16(t0.expectTagValue!string("text")),t0.expectTagValue!string("source"),c);
56 					break;
57 				case "Label":
58 					we = new Label(toUTF16(t0.expectTagValue!string("text")),t0.expectTagValue!string("source"),c);
59 					break;
60 				case "TextBox":
61 					we = new TextBox(toUTF16(t0.expectTagValue!string("text")),t0.expectTagValue!string("source"),c);
62 					break;
63 				case "ListBox":
64 					ListBoxHeader lbh;
65 					wstring[] lbhStrings;
66 					int[] lbhWidth;
67 					foreach(Tag t1; t0.expectTag("header").tags){
68 						lbhStrings ~= toUTF16(t1.expectValue!string());
69 						lbhWidth ~= t1.expectValue!int();
70 					}
71 					lbh = new ListBoxHeader(lbhStrings, lbhWidth);
72 					we = new ListBox(t0.expectTagValue!string("source"),c, null, lbh, t0.expectTagValue!int("rowHeight"));
73 					break;
74 				case "HSlider":
75 					we = new HSlider(t0.expectTagValue!int("maxValue"),t0.expectTagValue!int("barLength"),t0.expectTagValue!string("source"),c);
76 					break;
77 				case "VSlider":
78 					we = new VSlider(t0.expectTagValue!int("maxValue"),t0.expectTagValue!int("barLength"),t0.expectTagValue!string("source"),c);
79 					break;
80 				case "RadioButtonGroup":
81 					wstring[] options;
82 					foreach(Value v1; t0.expectTag("options").values){
83 						options ~= toUTF16(v1.get!string());
84 					}
85 					we = new RadioButtonGroup(toUTF16(t0.expectTagValue!string("text")),t0.expectTagValue!string("source"),c,options,t0.expectTagValue!int("rowHeight"),0);
86 					break;
87 				case "CheckBox":
88 					we = new CheckBox(toUTF16(t0.expectTagValue!string("text")),t0.expectTagValue!string("source"),c);
89 					break;
90 				case "MenuBar":
91 					PopUpMenuElement[] elements = fetchMenuBarElements(t0.expectTag("elements"));
92 					we = new MenuBar(t0.expectTagValue!string("source"),c, elements);
93 					break;
94 				default:
95 					break;
96 			}
97 			result[t0.expectTagValue!string("name")] = we;
98 			mainApp.ewh.dw.addElement(we, 0);
99 		}
100 
101 		return result;
102 	}
103 	/+public PopUpMenu[] fetchMenuBarElements(Tag t){
104 		PopUpMenu[] result;
105 		foreach(Tag t0; t.tags){
106 			if(t0.name == "popUpMenu"){
107 				string source = t0.expectTagValue!string("source");
108 				int iconWidth = t0.getTagValue!int("iconWidth");
109 				PopUpMenuElement[] subelements = fetchMenuBarSubelements(t0.expectTag("elements"));
110 				result ~= new PopUpMenu(subelements, source, iconWidth);
111 			}
112 		}
113 		return result;
114 	}+/
115 	public PopUpMenuElement[] fetchMenuBarElements(Tag t){
116 		PopUpMenuElement[] result;
117 		foreach(Tag t1; t.tags){
118 			wstring text = toUTF16(t1.expectTagValue!string("text"));
119 			wstring secondaryText = toUTF16(t1.getTagValue!string("secondaryText"));
120 			string source = t1.expectTagValue!string("source");
121 			PopUpMenuElement e = new PopUpMenuElement(source, text, secondaryText);
122 			Tag t2 = t1.getTag("elements");
123 			if(t2){
124 				e.loadSubElements(fetchMenuBarElements(t2));
125 			}
126 			result ~= e;
127 		}
128 		return result;
129 	}
130 	public void serialize(string path = this.filename){
131 		import std.file;
132 		string data = root.toSDLDocument();
133 		std.file.write(path, data);
134 	}
135 	public void exportToDLangFile(string path, string tab = "\t"){
136 		import std.file;
137 		string result = "import PixelPerfectEngine.concrete.window;\n", ctor;
138 		// Generate class header
139 		result ~= "public class " ~ windowName ~ " : Window, ActionListener { \n";
140 		// Generate basic ctor for class 
141 		ctor ~= tab ~ "this(){" ~ "\n" ~ tab ~ tab
142 				~ "super(Coordinate(0, 0, " ~ to!string(root.expectTag("Window").expectTagValue!int("width")) ~ ", " ~ to!string(root.expectTag("Window").expectTagValue!int("height")) ~ "), \""
143 				~ root.expectTag("Window").expectTagValue!string("title") ~ "\"w);\n";
144 		// Add elements to the class as members, then add them to the ctor
145 		foreach(Tag t0; root.expectTag("Window").expectTag("elements").tags){
146 			string coordinate = "Coordinate(" ~ to!string(t0.expectTagValue!int("Coordinate:left")) ~ ", " ~ to!string(t0.expectTagValue!int("Coordinate:top")) ~ ", "
147 					~ to!string(t0.expectTagValue!int("Coordinate:right")) ~ ", " ~ to!string(t0.expectTagValue!int("Coordinate:bottom")) ~ ")";
148 			switch(t0.name){
149 				case "Label":
150 					result ~= tab ~ "Label " ~ t0.expectTagValue!string("name") ~ ";\n";
151 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new Label(\"" ~ t0.expectTagValue!string("text") ~ "\"w, \"" ~ t0.expectTagValue!string("source") 
152 							~ "\", " ~ coordinate ~ ");\n";
153 					break;
154 				case "Button":
155 					result ~= tab ~ "Button " ~ t0.expectTagValue!string("name") ~ ";\n";
156 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new Button(\"" ~ t0.expectTagValue!string("text") ~ "\"w, \"" ~ t0.expectTagValue!string("source") 
157 							~ "\", " ~ coordinate ~ ");\n";
158 					break;
159 				case "CheckBox":
160 					result ~= tab ~ "CheckBox " ~ t0.expectTagValue!string("name") ~ ";\n";
161 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new CheckBox(\"" ~ t0.expectTagValue!string("text") ~ "\"w, \"" ~ t0.expectTagValue!string("source") 
162 							~ "\", " ~ coordinate ~ ");\n";
163 					break;
164 				case "TextBox":
165 					result ~= tab ~ "TextBox " ~ t0.expectTagValue!string("name") ~ ";\n";
166 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new TextBox(\"" ~ t0.expectTagValue!string("text") ~ "\"w, \"" ~ t0.expectTagValue!string("source") 
167 							~ "\", " ~ coordinate ~ ");\n";
168 					break;
169 				case "RadioButtonGroup":
170 					result ~= tab ~ "RadioButtonGroup " ~ t0.expectTagValue!string("name") ~ ";\n";
171 					string options;
172 					foreach(Value v0; t0.expectTag("options").values){
173 						options ~= "\"" ~ v0.get!string() ~ "\"w, ";
174 					}
175 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new RadioButtonGroup(\"" ~ t0.expectTagValue!string("text") ~ "\"w, \"" ~ t0.expectTagValue!string("source") 
176 							~ "\", " ~ coordinate ~ ",[ " ~ options ~ "], " ~ to!string(t0.expectTagValue!int("rowHeight")) ~ ", 0);\n";
177 					break;
178 				case "ListBox":
179 					result ~= tab ~ "ListBox " ~ t0.expectTagValue!string("name") ~ ";\n";
180 					string headerStr, headerInt;
181 					foreach(Tag t1; t0.expectTag("header").tags){
182 						headerStr ~= "\"" ~ t1.values[0].get!string() ~ "\"w, ";
183 						headerInt ~= to!string(t1.values[1].get!int()) ~ ", ";
184 					}
185 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new ListBox(\"" ~ t0.expectTagValue!string("source") ~ coordinate ~ "null, new ListBoxHeader([" 
186 							~ headerStr ~ "], [" ~ headerInt ~ "]), " ~ to!string(t0.expectTagValue!int("rowHeight")) ~ ");\n";
187 					break;
188 				case "VSlider":
189 					result ~= tab ~ "VSlider " ~ t0.expectTagValue!string("name") ~ ";\n";
190 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new VSlider(" ~ to!string(t0.expectTagValue!int("barLength")) ~ ", " ~ to!string(t0.expectTagValue!int("maxValue")) 
191 							~ ", \"" ~ t0.expectTagValue!string("source") ~ "\", " ~ coordinate ~ ");\n";
192 					break;
193 				case "HSlider":
194 					result ~= tab ~ "HSlider " ~ t0.expectTagValue!string("name") ~ ";\n";
195 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new HSlider(" ~ to!string(t0.expectTagValue!int("barLength")) ~ ", " ~ to!string(t0.expectTagValue!int("maxValue")) 
196 							~ ", \"" ~ t0.expectTagValue!string("source") ~ "\", " ~ coordinate ~ ");\n";
197 					break;
198 				case "MenuBar":
199 					result ~= tab ~ "MenuBar " ~ t0.expectTagValue!string("name") ~ ";\n";
200 					ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ " = new MenuBar(" ~ ", \"" ~ t0.expectTagValue!string("source") ~ "\", " ~ coordinate ~ 
201 							generateCodeForMenubarElements(t0.expectTag("elements")) ~ ");\n";
202 					break;
203 				default:
204 					break;
205 			}
206 			ctor ~= tab ~ tab ~ "addElement(" ~ t0.expectTagValue!string("name") ~ ", EventProperties.MOUSE);\n";
207 			//ctor ~= tab ~ tab ~ t0.expectTagValue!string("name") ~ ".al ~= this;\n";
208 		}
209 		result ~= ctor ~ tab ~ "}\n}";
210 		write(path, result);
211 	}
212 	/**
213 	 * Generates the menubar elements into string
214 	 */
215 	public string generateCodeForMenubarElements(Tag t){
216 		if(t){
217 			string result = "[";
218 			foreach(Tag t0 ; t.tags){
219 				string secondaryText = t0.getTagValue!string("secondaryText", "null");
220 				string foo = secondaryText == "null" ? "" : "\"";
221 				result ~= "new PopUpMenuElement(\"" ~ t0.expectTagValue!string("source") ~ "\", \"" ~ t0.expectTagValue!string("text") ~ "\", " ~ foo ~ secondaryText ~ foo ~ "," ~
222 						generateCodeForMenubarElements(t0.getTag("elements")) ~ ");\n";
223 			}
224 			return result ~ "]";
225 		}else
226 			return "null";
227 	}
228 	/**
229 	 * Changes the title of the Window
230 	 */
231 	public void setWindowTitle(wstring s){
232 		foreach(Tag t0; root.tags){
233 			if(t0.name() == "Window"){
234 				foreach(Tag t1; t0.tags){
235 					if(t1.name == "title"){
236 						t1.values[0] = Value(toUTF8(s));
237 						return;
238 					}
239 				}
240 				return;
241 			}
242 		}
243 	}
244 	/**
245 	 * Adds an extrabutton
246 	 */
247 	public void addExtraButton(string s){
248 		foreach(Tag t0; root.tags){
249 			if(t0.name() == "Window"){
250 				foreach(Tag t1; t0.tags){
251 					if(t1.name == "extraButton"){
252 						t1.add(Value(s));
253 						return;
254 					}
255 				}
256 				return;
257 			}
258 		}
259 	}
260 	/**
261 	 * Removes an extrabutton
262 	 */
263 	public void removeExtraButton(string s){
264 		foreach(Tag t0; root.tags){
265 			if(t0.name() == "Window"){
266 				foreach(Tag t1; t0.tags){
267 					if(t1.name == "extraButton"){
268 						Value[] v;
269 						foreach(Value v0; t1.values){
270 							if(v0 != s){
271 								v ~= v0;
272 							}
273 						}
274 						t1.values = v;
275 						return;
276 					}
277 				}
278 				return;
279 			}
280 		}
281 	}
282 	/**
283 	 *
284 	 */
285 	public void addWindowElement(string type, string name, wstring text, Coordinate position){
286 		string utf8text = toUTF8(text);
287 		foreach(Tag t0; root.tags){
288 			if(t0.name() == "Window"){
289 				foreach(Tag t1; t0.tags){
290 					if(t1.name == "elements"){
291 						Tag t2 = new Tag(t1, null, type);
292 						//new Tag(t2, null, "position", [Value(position.top),Value(position.left),Value(position.bottom),Value(position.right)]);
293 						new Tag(t2, "Coordinate", "top", [Value(position.top)]);
294 						new Tag(t2, "Coordinate", "left", [Value(position.left)]);
295 						new Tag(t2, "Coordinate", "bottom", [Value(position.bottom)]);
296 						new Tag(t2, "Coordinate", "right", [Value(position.right)]);
297 						new Tag(t2, null, "source", [Value(name)]);
298 						new Tag(t2, null, "name", [Value(name)]);
299 						switch(type){
300 							case "Label" , "TextBox", "CheckBox":
301 								new Tag(t2, null, "text", [Value(utf8text)]);
302 								break;
303 							case "Button":
304 								new Tag(t2, null, "text", [Value(utf8text)]);
305 								new Tag(t2, null, "icon", [Value("NULL")]);
306 								break;
307 							case "SmallButton":
308 								new Tag(t2, null, "iconPressed", [Value("NULL")]);
309 								new Tag(t2, null, "iconUnpressed", [Value("NULL")]);
310 								break;
311 							case "ListBox":
312 								new Tag(t2, null, "rowHeight", [Value(16)]);
313 								Tag t3 = new Tag(t2, null, "header");
314 								new Tag(t3, null, "column", [Value("Col0"), Value(40)]);
315 								new Tag(t3, null, "column", [Value("Col1"), Value(40)]);
316 								break;
317 							case "RadioButtonGroup":
318 								new Tag(t2, null, "text", [Value(utf8text)]);
319 								new Tag(t2, null, "rowHeight", [Value(16)]);
320 								//new Tag(t2, null, "header");
321 								new Tag(t2, null, "options", [Value("option0"), Value("option1")]);
322 								break;
323 							case "HSlider" , "VSlider":
324 								new Tag(t2, null, "maxValue", [Value(10)]);
325 								new Tag(t2, null, "barLength", [Value(1)]);
326 								break;
327 							case "Menubar":
328 								new Tag(t2, null, "elements");
329 								break;
330 							default:
331 								break;
332 						}
333 					}
334 				}
335 			}
336 		}
337 		writeln(root.toSDLDocument());
338 	}
339 	//template typeOf(T){
340 	public void editElementAttribute(string eName, string attrName, wstring value){
341 		if(eName == windowName){
342 			Tag t1 = root.expectTag("Window");
343 			foreach(foo; t1.namespaces){
344 				foreach(Tag t3; foo.tags){
345 					if(t3.getFullName().toString() == attrName){
346 						if(attrName == "title"){
347 							t3.values[0] = Value(toUTF8(value));
348 						}else if(t3.values[0].convertsTo!int()){
349 							t3.values[0] = Value(to!int(value));
350 						}else{
351 							t3.values[0] = Value(to!string(value));
352 						}
353 					}
354 				}	
355 			}
356 		}else{
357 			Tag t1 = root.expectTag("Window").expectTag("elements");
358 			foreach(Tag t2; t1.tags){
359 				if(t2.getTagValue!string("name") == eName){
360 					foreach(foo; t2.namespaces){
361 						foreach(Tag t3; foo.tags){
362 							if(t3.getFullName().toString() == attrName){
363 								if(attrName == "text"){
364 									t3.values[0] = Value(toUTF8(value));
365 								}else if(t3.values[0].convertsTo!int()){
366 									t3.values[0] = Value(to!int(value));
367 								}else{
368 									t3.values[0] = Value(to!string(value));
369 								}
370 							}
371 						}
372 					}
373 				}
374 			}
375 		}
376 	}
377 	//}
378 				
379 	public void removeElement(string eName){
380 		foreach(Tag t0; root.expectTag("Window").expectTag("elements").tags){
381 			if(t0.getTagValue!string("name") == eName){
382 				t0.remove();
383 				return;
384 			}
385 		}
386 	}
387 	public ElementParameter[] getElementAttributes(string eName){
388 		ElementParameter[] result;
389 		if(eName == windowName){
390 			Tag t1 = root.expectTag("Window");
391 			foreach(Tag t3; t1.tags){
392 				ElementParameter e = new ElementParameter();
393 				if(t3.getFullName().toString() != "elements"){
394 					e.name = to!string(t3.getFullName().toString());
395 					if(e.name == "title"){
396 						e.type = ElementValueParameter.Text;
397 						e.text = toUTF16(t3.getValue!string());
398 					}else if(t3.values.length == 1){
399 						if(t3.values[0].convertsTo!string()){
400 							e.type = ElementValueParameter.Description;
401 							e.text = to!wstring(t3.getValue!string());
402 						}else if(t3.values[0].convertsTo!int()){
403 							e.type = ElementValueParameter.Numeric;
404 							e.numeric = t3.getValue!int();
405 						}
406 					}else{
407 						e.type = ElementValueParameter.OpensANewWindow;
408 						e.text = "...";
409 					}
410 					result ~= e;
411 				}
412 			}
413 			return result;
414 		}
415 		
416 		Tag t1 = root.expectTag("Window").expectTag("elements");
417 		foreach(Tag t2; t1.tags){
418 			if(t2.getTagValue!string("name") == eName){
419 				foreach(foo; t2.namespaces){
420 					foreach(Tag t3; foo.tags){
421 						ElementParameter e = new ElementParameter();
422 						e.name = t3.getFullName().toString();
423 						if(e.name == "text"){
424 							e.type = ElementValueParameter.Text;
425 							e.text = toUTF16(t3.getValue!string());
426 						}else if(t3.values.length == 1 && (t3.getFullName().name != "options" || t3.getFullName().name != "elements" || t3.getFullName().name != "header")){
427 							if(t3.values[0].convertsTo!string()){
428 								e.type = ElementValueParameter.Description;
429 								e.text = to!wstring(t3.getValue!string());
430 							}else if(t3.values[0].convertsTo!int()){
431 								e.type = ElementValueParameter.Numeric;
432 								e.numeric = t3.getValue!int();
433 							}
434 						}else{
435 							e.type = ElementValueParameter.OpensANewWindow;
436 							e.text = "<...>";
437 						}
438 						result ~= e;
439 					}
440 				}
441 			}
442 		}
443 		return result;
444 	}
445 	public wstring[2][] getElements(){
446 		wstring[2][] result;
447 		wstring[2] subresult;
448 		subresult[0] = to!wstring(windowName);
449 		subresult[1] = "Window";
450 		result ~= subresult;
451 		Tag t1 = root.expectTag("Window").expectTag("elements");
452 
453 		foreach(Tag t2; t1.tags){
454 			subresult[1] = to!wstring((t2.name));
455 			subresult[0] = to!wstring(t2.getTagValue!string("name"));
456 			result ~= subresult;
457 		}
458 		//writeln(result);
459 				
460 		return result;
461 	}
462 	private void generateStyleSheet(Tag t){
463 		new Tag(t, "StyleSheet", "font");
464 		new Tag(t, "StyleSheet", "windowAscent");
465 		new Tag(t, "StyleSheet", "windowDescent");
466 	}
467 }
468 public class WindowDataException : Exception{
469 	public this(string msg, string file = __FILE__, size_t line =  __LINE__, Throwable next = null) {
470 		super(msg, file, line, next);
471 	}
472 }