1 module serializer; 2 3 import sdlang; 4 import editor; 5 import types; 6 import PixelPerfectEngine.graphics.common; 7 import PixelPerfectEngine.concrete.elements; 8 import std.utf; 9 import std.stdio; 10 import conv = std.conv; 11 12 public class WindowSerializer { 13 Tag root; 14 string filename; 15 public this(){ 16 root = new Tag(null, null); 17 Tag window = new Tag(root, null, "Window", [Value("window")]); 18 new Tag(window, null, "title", [Value("New Window")]); 19 new Tag(window, "size", "x", [Value(640)]); 20 new Tag(window, "size", "y", [Value(480)]); 21 new Tag(window, null, "extraButtons"); 22 } 23 public this(string filename) { 24 this.filename = filename; 25 } 26 public void store(string filename) { 27 this.filename = filename; 28 store(); 29 } 30 public @property @nogc string getFilename() { 31 return filename; 32 } 33 public void store() { 34 import std..string : toStringz; 35 string fileout = root.toSDLDocument("\t",1); 36 debug writeln(fileout); 37 File filestream = File(filename, "w"); 38 //filestream.open(); 39 filestream.write(fileout); 40 filestream.close(); 41 } 42 private Coordinate parseCoordinate(Tag t){ 43 return Coordinate(t.values[0].get!int,t.values[1].get!int,t.values[2].get!int,t.values[3].get!int); 44 } 45 private string parseCoordinateIntoString(Tag t){ 46 return conv.to!string(t.values[0].get!int) ~ ", " ~ conv.to!string(t.values[1].get!int) ~ ", " ~ 47 conv.to!string(t.values[2].get!int) ~ ", " ~ conv.to!string(t.values[3].get!int); 48 } 49 public void deserialize(DummyWindow dw, Editor e) { 50 root = parseFile(filename); 51 foreach(t0; root.all.tags){ 52 string name = t0.expectValue!string(), type; 53 WindowElement we; 54 switch(t0.getFullName.toString){ 55 case "Label": 56 we = new Label(toUTF32(t0.expectTagValue!string("text")), t0.expectTagValue!string("source"), 57 parseCoordinate(t0.expectTag("position"))); 58 dw.addElement(we); 59 type = "Label"; 60 break; 61 case "Button": 62 we = new Button(toUTF32(t0.expectTagValue!string("text")), t0.expectTagValue!string("source"), 63 parseCoordinate(t0.expectTag("position"))); 64 dw.addElement(we); 65 type = "Button"; 66 break; 67 case "SmallButton": 68 break; 69 case "TextBox": 70 we = new TextBox(toUTF32(t0.expectTagValue!string("text")), t0.expectTagValue!string("source"), 71 parseCoordinate(t0.expectTag("position"))); 72 dw.addElement(we); 73 type = "TextBox"; 74 break; 75 case "SmallCheckBox": 76 break; 77 case "CheckBox": 78 we = new CheckBox(toUTF32(t0.expectTagValue!string("text")), t0.expectTagValue!string("source"), 79 parseCoordinate(t0.expectTag("position"))); 80 dw.addElement(we); 81 type = "CheckBox"; 82 break; 83 case "SmallRadioButton": 84 break; 85 case "RadioButton": 86 we = new RadioButton(toUTF32(t0.expectTagValue!string("text")), t0.expectTagValue!string("source"), 87 parseCoordinate(t0.expectTag("position"))); 88 dw.addElement(we); 89 type = "RadioButton"; 90 break; 91 case "ListView": 92 int[] columnWidths; 93 dstring[] columnTexts; 94 const int headerHeight = t0.expectTag("header").expectValue!int(); 95 foreach(t1; t0.expectTag("header").tags){ 96 columnTexts ~= toUTF32(t1.values[0].get!string); 97 columnWidths ~= t1.values[1].get!int; 98 } 99 we = new ListView(new ListViewHeader(headerHeight, columnWidths, columnTexts), [], 100 t0.expectTagValue!string("source"), parseCoordinate(t0.expectTag("position"))); 101 dw.addElement(we); 102 type = "ListView"; 103 break; 104 case "Window": 105 dw.setTitle(toUTF32(t0.expectTagValue!string("title"))); 106 dw.setSize(t0.expectTagValue!int("size:x"),t0.expectTagValue!int("size:y")); 107 type = "Window"; 108 break; 109 case "HorizScrollBar": 110 we = new HorizScrollBar(t0.expectTagValue!int("maxValue"), t0.expectTagValue!string("source"), 111 parseCoordinate(t0.expectTag("position"))); 112 dw.addElement(we); 113 type = "HorizScrollBar"; 114 break; 115 case "VertScrollBar": 116 we = new VertScrollBar(t0.expectTagValue!int("maxValue"), t0.expectTagValue!string("source"), 117 parseCoordinate(t0.expectTag("position"))); 118 dw.addElement(we); 119 type = "VertScrollBar"; 120 break; 121 default: 122 break; 123 } 124 if (type != "Window") { 125 e.elements[name] = ElementInfo(we, name, type); 126 //e.elementTypes[name] = type; 127 } 128 } 129 e.updateElementList; 130 } 131 public void generateDCode(string outputFile){ 132 string outputCode = "import PixelPerfectEngine.concrete.window; \n\n", windowCtor, elementCtors, typeDefs; 133 foreach(t0; root.all.tags){ 134 string typeName = t0.name; 135 switch (typeName) { 136 case "Window": break; 137 case "SmallRadioButton": 138 elementCtors ~= "\t\t" ~ t0.getValue!string() ~ " = "; 139 typeDefs ~= "\t" ~ "RadioButton" ~ " " ~ t0.getValue!string() ~ ";\n"; 140 break; 141 case "SmallCheckBox": 142 elementCtors ~= "\t\t" ~ t0.getValue!string() ~ " = "; 143 typeDefs ~= "\t" ~ "CheckBox" ~ " " ~ t0.getValue!string() ~ ";\n"; 144 break; 145 default: 146 elementCtors ~= "\t\t" ~ t0.getValue!string() ~ " = "; 147 typeDefs ~= "\t" ~ typeName ~ " " ~ t0.getValue!string() ~ ";\n"; 148 break; 149 } 150 switch(typeName){ 151 case "Button", "Label", "TextBox", "CheckBox", "RadioButton": 152 elementCtors ~= "new " ~ typeName ~ "(\"" ~ t0.getTagValue!string("text") ~ "\"d, \"" ~ 153 t0.getTagValue!string("source") ~ "\", Box(" ~ parseCoordinateIntoString(t0.getTag("position")) ~ "));\n"; 154 break; 155 case "HorizScrollBar", "VertScrollBar": 156 elementCtors ~= "new " ~ typeName ~ "(\"" ~ conv.to!string(t0.getTagValue!int("maxValue")) ~ ", " ~ 157 t0.getTagValue!string("source") ~ "\", Box(" ~ parseCoordinateIntoString(t0.getTag("position")) ~ "));\n"; 158 break; 159 160 case "Window": 161 outputCode ~= "public class " ~ t0.getValue!string() ~ " : Window {\n"; 162 //string extraButtons; 163 /+Tag t1 = t0.getTag("extraButtons", null); 164 if(t1 !is null){ 165 if(t1.values.length){ 166 extraButtons = ", ["; 167 foreach(Value v; t1.values){ 168 extraButtons ~= v.get!string() ~ ", "; 169 } 170 extraButtons.length -= 2; 171 extraButtons = "]"; 172 } 173 }+/ 174 /+windowCtor = "super(\"" ~ t0.getTagValue!string("title") ~ "\"d, Box(0, 0, " ~ 175 conv.to!string(t0.getTagValue!int("size:x")) ~ ", " ~ conv.to!string(t0.getTagValue!int("size:y")) ~ " )" ~ 176 extraButtons ~ ");\n";+/ 177 windowCtor = "super(Box(0, 0, " ~ conv.to!string(t0.getTagValue!int("size:x")) ~ ", " ~ 178 conv.to!string(t0.getTagValue!int("size:y")) ~ "), \"" ~ t0.getTagValue!string("title") ~ "\");\n"; 179 break; 180 default: 181 break; 182 } 183 } 184 outputCode ~= typeDefs ~ "\tpublic this(){\n\t\t" ~ windowCtor ~ elementCtors ~ "\t}\n}\n"; 185 debug writeln(outputCode); 186 File filestream = File(outputFile, "w"); 187 //filestream.open(); 188 filestream.write(outputCode); 189 filestream.close(); 190 } 191 /** 192 * Returns a complete tag for editing a tree, etc. 193 */ 194 public Tag getTag(string target, string property){ 195 foreach(t0; root.all.tags){ 196 if(t0.getValue!string() == target){ 197 return t0.getTag(property); 198 } 199 } 200 return null; 201 } 202 /** 203 * Edits the value of an element. 204 * For MenuBar PopUpMenu trees, use the getTag function instead. 205 */ 206 public Value[] editValue(string target, string property, Value[] val){ 207 Value[] result; 208 foreach(t0; root.all.tags){ 209 if(t0.getValue!string() == target){ 210 result = t0.getTagValues(property); 211 t0.getTag(property).values = val; 212 return result; 213 } 214 } 215 return result; 216 } 217 public Value[] getValue(string target, string property){ 218 foreach(t0; root.all.tags){ 219 if(t0.getValue!string() == target){ 220 return t0.getTagValues(property); 221 } 222 } 223 return null; 224 } 225 public string renameWindow(string name){ 226 string oldname = root.getTag("Window").getValue!string(); 227 root.getTag("Window").values[0] = Value(name); 228 return oldname; 229 } 230 public string getWindowName(){ 231 return root.getTag("Window").getValue!string(); 232 } 233 public Value[] editWindowValue(string property, Value[] val){ 234 Value[] result = root.getTag("Window").getTag(property).values; 235 root.getTag("Window").getTag(property).values = val; 236 return result; 237 } 238 public Value[] getWindowValue(string property){ 239 return root.getTag("Window").getTag(property).values; 240 } 241 public void renameElement(string oldName, string newName){ 242 foreach(t; root.tags){ 243 if(t.getValue!string() == oldName){ 244 t.values[0] = Value(newName); 245 return; 246 } 247 } 248 } 249 public void addElement(string type, string name, Coordinate initPos){ 250 foreach(t; root.tags){ 251 if(t.getValue!string() == name) 252 throw new ElementCollisionException("Similarly named element already exists!"); 253 } 254 Tag t1 = new Tag(root, null, type, [Value(name)]); 255 switch(type){ 256 case "Label", "TextBox", "RadioButton", "CheckBox": 257 new Tag(t1, null, "text", [Value(name)]); 258 break; 259 case "Button": 260 new Tag(t1, null, "icon", [Value("null")]); 261 goto case "Label"; 262 case "ListView": 263 Tag t2 = new Tag(t1, null, "header", [Value(16)]); 264 new Tag(t2, null, null, [Value("col0"), Value(40)]); 265 new Tag(t2, null, null, [Value("col1"), Value(40)]); 266 break; 267 case "HorizScrollBar", "VertScrollBar": 268 //new Tag(t1, null, "barLength", [Value(1)]); 269 new Tag(t1, null, "maxValue", [Value(16)]); 270 break; 271 case "MenuBar": 272 Tag t2 = new Tag(t1, null, "options"); 273 Tag t3 = new Tag(t2, null, null, [Value("opt0")]); 274 new Tag(t3, null, null, [Value("opt0_0")]); 275 new Tag(t3, null, null, [Value("opt0_1")]); 276 Tag t4 = new Tag(t2, null, null, [Value("opt1")]); 277 new Tag(t4, null, null, [Value("opt1_0")]); 278 new Tag(t4, null, null, [Value("opt1_1")]); 279 break; 280 default: 281 break; 282 } 283 new Tag(t1, null, "source", [Value(name)]); 284 new Tag(t1, null, "position", [Value(initPos.left), Value(initPos.top), Value(initPos.right), Value(initPos.bottom)]); 285 //debug writeln(t1); 286 } 287 public void addElement(Tag tag){ 288 foreach(t; root.tags){ 289 if(t.values[0].get!string() == tag.values[0].get!string()) 290 throw new ElementCollisionException("Similarly named element already exists!"); 291 } 292 root.add(tag); 293 } 294 public Tag removeElement(string name){ 295 foreach(t; root.tags){ 296 if(t.values[0].get!string() == name){ 297 t.remove; 298 return t; 299 } 300 } 301 return null; 302 } 303 } 304 class ElementCollisionException : Exception{ 305 @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null) 306 { 307 super(msg, file, line, nextInChain); 308 } 309 310 @nogc @safe pure nothrow this(string msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__) 311 { 312 super(msg, file, line, nextInChain); 313 } 314 }