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 }