1 module editor;
2 
3 import types;
4 import serializer;
5 import editorEvents;
6 
7 import pixelperfectengine.concrete.window;
8 import pixelperfectengine.system.input;
9 import pixelperfectengine.system.etc : csvParser, isInteger;
10 import pixelperfectengine.graphics.layers;
11 import pixelperfectengine.graphics.raster;
12 import pixelperfectengine.graphics.outputscreen;
13 import pixelperfectengine.system.config;
14 import std.bitmanip : bitfields;
15 public import collections.linkedhashmap;
16 
17 import conv = std.conv;
18 import stdio = std.stdio;
19 
20 public class TopLevelWindow : Window {
21 	public ListView objectList, propList;
22 	MenuBar mb;
23 	Editor editor;
24 	public this(int width, int height, Editor e) {
25 		import pixelperfectengine.graphics.draw;
26 		super(Box(0, 0, width, height), ""d, [], null);
27 		editor = e;
28 		PopUpMenuElement[] menuElements;
29 
30 		menuElements ~= new PopUpMenuElement("file", "File");
31 
32 		menuElements[0] ~= new PopUpMenuElement("new", "New window");
33 		menuElements[0] ~= new PopUpMenuElement("load", "Load window");
34 		menuElements[0] ~= new PopUpMenuElement("save", "Save window");
35 		menuElements[0] ~= new PopUpMenuElement("saveAs", "Save window as");
36 		menuElements[0] ~= new PopUpMenuElement("export", "Export window as D code" );
37 		menuElements[0] ~= new PopUpMenuElement("exit", "Exit application", "Alt + F4");
38 
39 		menuElements ~= new PopUpMenuElement("edit", "Edit");
40 
41 		menuElements[1] ~= new PopUpMenuElement("undo", "Undo");
42 		menuElements[1] ~= new PopUpMenuElement("redo", "Redo");
43 		menuElements[1] ~= new PopUpMenuElement("copy", "Copy");
44 		menuElements[1] ~= new PopUpMenuElement("cut", "Cut");
45 		menuElements[1] ~= new PopUpMenuElement("paste", "Paste");
46 
47 		menuElements ~= new PopUpMenuElement("elements", "Elements");
48 
49 		menuElements[2] ~= new PopUpMenuElement("Label", "Label");
50 		menuElements[2] ~= new PopUpMenuElement("Button", "Button");
51 		menuElements[2] ~= new PopUpMenuElement("TextBox", "TextBox");
52 		menuElements[2] ~= new PopUpMenuElement("ListView", "ListView");
53 		menuElements[2] ~= new PopUpMenuElement("CheckBox", "CheckBox");
54 		menuElements[2] ~= new PopUpMenuElement("RadioButton", "RadioButton");
55 		//menuElements[2] ~= new PopUpMenuElement("MenuBar", pt("MenuBar"), st("Ctrl + F7"));
56 		menuElements[2] ~= new PopUpMenuElement("HSlider", "HSlider");
57 		menuElements[2] ~= new PopUpMenuElement("VSlider", "VSlider");
58 
59 		menuElements ~= new PopUpMenuElement("help", "Help");
60 
61 		menuElements[3] ~= new PopUpMenuElement("helpFile", "Content");
62 		menuElements[3] ~= new PopUpMenuElement("about", "About");
63 
64 		mb = new MenuBar("mb", Box(0, 0, width-1, 15), menuElements);
65 		objectList = new ListView(new ListViewHeader(16, [128, 128], ["type"d, "name"d]), [], "objectList", 
66 				Box(644,20,width - 5,238));
67 		propList = new ListView(new ListViewHeader(16, [128,256], ["Prop"d,"Val"d]), [], "propList",
68 				Box(644,242,width - 5,477));
69 
70 		propList.editEnable = true;
71 
72 		addElement(mb);
73 		addElement(objectList);
74 		addElement(propList);
75 
76 		mb.onMenuEvent = &e.menuEvent;
77 		objectList.onItemSelect = &e.onObjectListSelect;
78 		propList.onTextInput = &e.onAttributeEdit;
79 	}
80 	public override void draw(bool drawHeaderOnly = false) {
81 		if(output.output.width != position.width || output.output.height != position.height)
82 			output = new BitmapDrawer(position.width(), position.height());
83 		
84 		StyleSheet ss = getStyleSheet();
85 		const Box bodyarea = Box(0, 0, position.width - 1, position.height - 1);
86 		drawFilledBox(bodyarea, ss.getColor("window"));
87 
88 		foreach (WindowElement we; elements) {
89 			we.draw();
90 		}
91 		
92 	}
93 }
94 /**
95  * Window to display the current layout.
96  */
97 public class DummyWindow : Window {
98 	Editor ed;
99 	public this(Box coordinates, dstring name, Editor ed) {
100 		super(coordinates, name);
101 		this.ed = ed;
102 	}
103 	///Passes mouse click event
104 	override public void passMCE(MouseEventCommons mec, MouseClickEvent mce) {
105 		//super.passMouseEvent(x,y,state,button);
106 		mce.x -= position.left;
107 		mce.y -= position.top;
108 		if(mce.button == MouseButton.Left){
109 			ed.clickEvent(mce.x, mce.y, mce.state);
110 		}else if(mce.button == MouseButton.Right){
111 			foreach(we; elements){
112 				const Box c = we.getPosition;
113 				if(c.isBetween(mce.x, mce.y))
114 					ed.selectEvent(we);
115 			}
116 		}
117 	}
118 	public void setWidth(int val) {
119 		position.width = val;
120 		draw();
121 	}
122 	public void setHeight(int val) {
123 		position.height = val;
124 		draw();
125 	}
126 	public void setSize(int width, int height) {
127 		position.width = width;
128 		position.height = height;
129 		draw();
130 	}
131 	override public void close() {
132 	//super.close;
133 	}
134 	/+override public void passMouseMotionEvent(int x, int y, int relX, int relY, ubyte button) {
135 
136 	}+/
137 	override public void passMME(MouseEventCommons mec, MouseMotionEvent mme) {
138 		if (mme.buttonState) {
139 			mme.x -= position.left;
140 			mme.y -= position.top;
141 			ed.dragEvent(mme.x, mme.y, mme.relX, mme.relY, mme.buttonState);
142 		}
143 	}
144 	public void drawSelection(Box box, bool crossHair = false) {
145 		draw();
146 		//stdio.writeln(box);
147 		drawBox(box, 17);
148 		if (crossHair) {
149 			const int width = position.width - 1, height = position.height - 1;
150 			
151 			drawLine(Point(0, box.top), box.cornerUL, 18);
152 			drawLine(Point(box.left, 0), box.cornerUL, 18);
153 
154 			drawLine(Point(width, box.top), box.cornerUR, 18);
155 			drawLine(Point(box.right, 0), box.cornerUR, 18);
156 
157 			drawLine(Point(0, box.bottom), box.cornerLL, 18);
158 			drawLine(Point(box.left, height), box.cornerLL, 18);
159 
160 			drawLine(Point(width, box.bottom), box.cornerLR, 18);
161 			drawLine(Point(box.right, height), box.cornerLR, 18);
162 		}
163 	}
164 }
165 
166 
167 
168 public class Editor : SystemEventListener, InputListener{
169 	WindowHandler		ewh;
170 	DummyWindow 		dw;
171 	SpriteLayer			sprtL;
172 	Raster				mainRaster;
173 	OutputScreen		outScrn;
174 	InputHandler		inputH;
175 	EditMode			mode;
176 	mixin(bitfields!(
177 		bool, "onExit", 1,
178 		bool, "undoPressed", 1,
179 		bool, "redoPressed", 1,
180 		bool, "delPressed", 1,
181 		bool, "moveElemMode", 1,
182 		bool, "resizeMode", 1,
183 		ubyte, "", 2,
184 	));
185 	Box					moveElemOrig;
186 	int					x0, y0;
187 	ElementType			typeSel;
188 	UndoableStack		eventStack;
189 	/+WindowElement[string] elements;
190 	string[string]		elementTypes;+/
191 	alias ElementInfoMap = LinkedHashMap!(string, ElementInfo);
192 	ElementInfoMap		elements;
193 	string				selection;
194 	ConfigurationProfile	config;
195 	TopLevelWindow		tlw;
196 
197 	static string[ElementType] nameBases;
198 	public this(){
199 		import pixelperfectengine.system.systemutility;
200 		import pixelperfectengine.system.file;
201 		
202 		sprtL = new SpriteLayer(RenderingMode.Copy);
203 		outScrn = new OutputScreen("WindowMaker for PPE/Concrete",1696,960);
204 		mainRaster = new Raster(848,480,outScrn,0);
205 		mainRaster.addLayer(sprtL,0);
206 		typeSel = ElementType.NULL;
207 
208 		ewh = new WindowHandler(1696,960,848,480,sprtL);
209 		mainRaster.loadPalette(loadPaletteFromFile("../system/concreteGUIE1.tga"));
210 		INIT_CONCRETE();
211 		inputH = new InputHandler();
212 		inputH.systemEventListener = this;
213 		inputH.inputListener = this;
214 		inputH.mouseListener = ewh;
215 		
216 		//ewh.setBaseWindow(new TopLevelWindow(848, 480, this));
217 		config = new ConfigurationProfile("config_wmfc.sdl", "../system/config_wmfc.sdl");
218 		{
219 			import pixelperfectengine.system.input.scancode;
220 			inputH.addBinding(BindingCode(ScanCode.ESCAPE, 0, Devicetype.Keyboard, 0, KeyModifier.LockKeys), InputBinding("sysesc"));
221 		}
222 		config.loadBindings(inputH);
223 
224 		PopUpElement.inputhandler = inputH;
225 		WindowElement.inputHandler = inputH;
226 		
227 		dw = new DummyWindow(Coordinate(0,16,640,480), "New Window"d, this);
228 		ewh.addWindow(dw);
229 		tlw = new TopLevelWindow(848, 480, this);
230 		ewh.setBaseWindow(tlw);
231 		eventStack = new UndoableStack(10);
232 		wserializer = new WindowSerializer();
233 		dwtarget = dw;
234 		editorTarget = this;
235 		//ewh.objectList.onItemSelect = &onObjectListSelect;
236 		//ewh.propList.onTextInput = &onAttributeEdit;
237 		updateElementList;
238 	}
239 	static this(){
240 		nameBases[ElementType.Label] = "label";
241 		nameBases[ElementType.Button] = "button";
242 		nameBases[ElementType.SmallButton] = "smallButton";
243 		nameBases[ElementType.TextBox] = "textBox";
244 		nameBases[ElementType.ListView] = "listView";
245 		nameBases[ElementType.RadioButton] = "radioButton";
246 		nameBases[ElementType.CheckBox] = "checkBox";
247 		nameBases[ElementType.HSlider] = "hSlider";
248 		nameBases[ElementType.VSlider] = "vSlider";
249 		nameBases[ElementType.MenuBar] = "menuBar";
250 	}
251 	public string getNextName(string input){
252 		for(int i ; true ; i++){
253 			//if(elements.get(input ~ conv.to!string(i), null) is null)
254 			string newname = input ~ conv.to!string(i);
255 			if(!elements.getPtr(newname))
256 				return newname;
257 		}
258 	}
259 	public void onObjectListSelect(Event ev){
260 		deinitElemMove;
261 		ListViewItem lbi = cast(ListViewItem)ev.aux;
262 		if(lbi[0].text.text != "Window"){
263 			selection = conv.to!string(lbi[1].text.text);
264 		}else{//Fill attribute list with data related to the window
265 			selection = "Window";
266 		}
267 		updatePropertyList;
268 	}
269 	public void onLoadFile(Event ev){
270 		FileEvent ev0 = cast(FileEvent)ev;
271 		wserializer = new WindowSerializer(ev0.getFullPath);
272 		wserializer.deserialize(dw, this);
273 	}
274 	public void onSaveFileAs(Event ev){
275 		FileEvent ev0 = cast(FileEvent)ev;
276 		wserializer.store(ev0.getFullPath);
277 	}
278 	public void onExportWindow(Event ev){
279 		FileEvent ev0 = cast(FileEvent)ev;
280 		wserializer.generateDCode(ev0.getFullPath);
281 	}
282 	public void onAttributeEdit(Event ev){
283 		import std.utf : toUTF8;
284 		CellEditEvent ev0 = cast(CellEditEvent)ev;
285 		dstring t = ev0.text.text;
286 		ListViewItem lbi = cast(ListViewItem) ev.aux;
287 		if(selection == "Window"){
288 			switch(lbi[0].text.text) {
289 				case "name":
290 					eventStack.addToTop(new WindowRenameEvent(conv.to!string(t)));
291 					return;
292 				case "title":
293 					eventStack.addToTop(new WindowRetitleEvent(t));
294 					return;
295 				case "size:x":
296 					eventStack.addToTop(new WindowWidthChangeEvent(conv.to!int(t)));
297 					return;
298 				case "size:y":
299 					eventStack.addToTop(new WindowHeightChangeEvent(conv.to!int(t)));
300 					return;
301 				default:
302 					return;
303 			}
304 		}else{
305 			switch(lbi[0].text.text){
306 				case "text":
307 					eventStack.addToTop(new TextEditEvent(t, selection));
308 					return;
309 				case "name":
310 					eventStack.addToTop(new RenameEvent(selection, conv.to!string(t)));
311 					selection = conv.to!string(t);
312 					return;
313 				case "position":
314 					dstring[] src = csvParser(t, ';');
315 					if(src.length == 4){
316 						Coordinate c;
317 						foreach(s; src){
318 							if(!isInteger(s)){
319 								ewh.message("Format Error!", "Value is not integer!");
320 								return;
321 							}
322 						}
323 						c.left = conv.to!int(src[0]);
324 						c.top = conv.to!int(src[1]);
325 						c.right = conv.to!int(src[2]);
326 						c.bottom = conv.to!int(src[3]);
327 						eventStack.addToTop(new PositionEditEvent(c, selection));
328 					}else{
329 						ewh.message("Format Error!", "Correct format is: [int];[int];[int];[int];");
330 					}
331 					return;
332 				case "source":
333 					eventStack.addToTop(new SourceEditEvent(selection, conv.to!string(t)));
334 					return;
335 				default:
336 					return;
337 			}
338 		}
339 	}
340 	public void clickEvent(int x, int y, bool state){
341 		if(typeSel != ElementType.NULL) {
342 			if(state) {
343 				x0 = x;
344 				y0 = y;
345 			}else{
346 				Box c;
347 				if(x > x0){
348 					c.left = x0;
349 					c.right = x;
350 				}else{
351 					c.left = x;
352 					c.right = x0;
353 				}
354 				if(y > y0){
355 					c.top = y0;
356 					c.bottom = y;
357 				}else{
358 					c.top = y;
359 					c.bottom = y0;
360 				}
361 				WindowElement we;
362 				string s, type;
363 				switch(typeSel){
364 					case ElementType.Label:
365 						s = getNextName("label");
366 						type = "Label";
367 						we = new Label(conv.to!dstring(s),s,c);
368 						break;
369 					case ElementType.Button:
370 						s = getNextName("button");
371 						type = "Button";
372 						we = new Button(conv.to!dstring(s),s,c);
373 						break;
374 					case ElementType.TextBox:
375 						s = getNextName("textBox");
376 						type = "TextBox";
377 						we = new TextBox(conv.to!dstring(s),s,c);
378 						break;
379 					case ElementType.ListView:
380 						s = getNextName("listView");
381 						type = "ListView";
382 						we = new ListView(new ListViewHeader(16, [40, 40], ["col0", "col1"]), [], s, c);
383 						break;
384 					case ElementType.CheckBox:
385 						s = getNextName("CheckBox");
386 						type = "CheckBox";
387 						we = new CheckBox(conv.to!dstring(s),s,c);
388 						break;
389 					case ElementType.RadioButton:
390 						s = getNextName("radioButton");
391 						type = "RadioButton";
392 						we = new RadioButton(conv.to!dstring(s),s,c);
393 						break;
394 					/+case ElementType.MenuBar:
395 						s = getNextName("menuBar");
396 						we = new MenuBar(s,c,[new PopUpMenuElement("menu0","menu0")]);+/
397 						//break;
398 					case ElementType.HSlider:
399 						s = getNextName("horizScrollBar");
400 						type = "HorizScrollBar";
401 						we = new HorizScrollBar(16,s,c);
402 						break;
403 					case ElementType.VSlider:
404 						s = getNextName("vertScrollBar");
405 						type = "VertScrollBar";
406 						we = new VertScrollBar(16,s,c);
407 						break;
408 					default:
409 						break;
410 				}
411 				eventStack.addToTop(new PlacementEvent(we, type, s));
412 				typeSel = ElementType.NULL;
413 				//updateElementList;
414 			}
415 		} else {
416 			if (state == ButtonState.Pressed) {
417 				if(!moveElemMode && elements.getPtr(selection)) {
418 					if (elements[selection].element.getPosition.isBetween(x,y)) {
419 						initElemMove;
420 						
421 					} else if (elements[selection].element.getPosition.right <= x + 1 && elements[selection].element.getPosition.bottom <= y + 1) {
422 						initElemResize;
423 						
424 					}
425 				}
426 			} else {
427 				finalizeElemMove;
428 				finalizeElemResize;
429 			}
430 		}
431 	}
432 	public void dragEvent(int x, int y, int relX, int relY, uint button) {
433 		if (moveElemMode) {
434 			Box temp = elements[selection].element.getPosition;
435 			if(temp.left + relX < 0) relX -= temp.left + relX;
436 			if(temp.right + relX >= dw.getPosition.width) relX -= (temp.right + relX) - dw.getPosition.width;
437 			if(temp.top + relY < 0) relY -= temp.top + relY;
438 			if(temp.bottom + relY >= dw.getPosition.height) relY -= (temp.bottom + relY) - dw.getPosition.height;
439 			temp.relMove(relX, relY);
440 			elements[selection].element.setPosition(temp);
441 			dw.draw();
442 		} else if (resizeMode) {
443 			x0 = x;
444 			y0 = y;
445 			dw.drawSelection(Box(elements[selection].element.getPosition.left, elements[selection].element.getPosition.top, x0, y0));
446 		} else if (typeSel != ElementType.NULL) {
447 			dw.drawSelection(Box(x0, y0, x, y), true);
448 		}
449 	}
450 
451 	public void updateElementList(){
452 		tlw.objectList.clear();
453 		tlw.objectList ~= new ListViewItem(16, ["Window"d, ""d]);
454 		foreach(s; elements){
455 			tlw.objectList ~= new ListViewItem(16, [conv.to!dstring(s.type), conv.to!dstring(s.name)]);
456 		}
457 		tlw.objectList.refresh();
458 	}
459 	public void updatePropertyList(){
460 		import sdlang;
461 		import std.utf;
462 		tlw.propList.clear();
463 		if(elements.getPtr(selection) !is null){
464 			string classname = elements[selection].type;
465 			tlw.propList ~= [new ListViewItem(16, ["name"d, conv.to!dstring(selection)], [TextInputFieldType.None, 
466 					TextInputFieldType.Text]), new ListViewItem(16, ["source"d, conv.to!dstring(wserializer.getValue(selection, 
467 					"source")[0].get!string())], [TextInputFieldType.None, TextInputFieldType.Text])];
468 			if(classname == "Label" || classname == "TextBox" || classname == "Button" || classname == "CheckBox" ||
469 					classname == "RadioButton"){
470 				tlw.propList ~= new ListViewItem(16, ["text", toUTF32(wserializer.getValue(selection, "text")[0].get!string())], 
471 						[TextInputFieldType.None, TextInputFieldType.Text]);
472 			}
473 			Value[] pos0 = wserializer.getValue(selection, "position");
474 			dstring pos1 = conv.to!dstring(pos0[0].get!int) ~ ";" ~ conv.to!dstring(pos0[1].get!int) ~ ";" ~
475 					conv.to!dstring(pos0[2].get!int) ~ ";" ~ conv.to!dstring(pos0[3].get!int) ~ ";";
476 			tlw.propList ~= new ListViewItem(16, ["position", pos1], [TextInputFieldType.None, TextInputFieldType.Text]);
477 			switch(classname){
478 				/+case "SmallButton", "SmallCheckBox", "SmallRadioButton", "CheckBox", "RadioButton":
479 					tlw.propList ~= new ListViewItem(16, [
480 							"iconPressed", conv.to!dstring(wserializer.getValue(selection, "iconPressed")[0].get!string())],
481 							[TextInputFieldType.None, TextInputFieldType.Text]);
482 					tlw.propList ~= new ListViewItem(16, [
483 							"iconUnpressed", conv.to!dstring(wserializer.getValue(selection, "iconUnpressed")[0].get!string())],
484 							[TextInputFieldType.None, TextInputFieldType.Text]);
485 					break;+/
486 				case "ListView":
487 					tlw.propList ~= new ListViewItem(16, ["header", "[...]"]);
488 					break;
489 				case "HorizScrollBar", "VertScrollBar":
490 					tlw.propList ~= [
491 							new ListViewItem(16, ["maxValue",conv.to!dstring(wserializer.getValue(selection,"maxValue")[0].get!int())],
492 							[TextInputFieldType.None, TextInputFieldType.Integer])];
493 					break;
494 				default:
495 					break;
496 			}
497 			
498 		}else{
499 			tlw.propList ~= [new ListViewItem(16, ["name", conv.to!dstring(wserializer.getWindowName)], 
500 					[TextInputFieldType.None, TextInputFieldType.Text]),
501 					new ListViewItem(16, ["title", toUTF32(wserializer.getWindowValue("title")[0].get!string())], 
502 					[TextInputFieldType.None, TextInputFieldType.Text]),
503 					new ListViewItem(16, ["size:x", conv.to!dstring(wserializer.getWindowValue("size:x")[0].get!int())], 
504 					[TextInputFieldType.None, TextInputFieldType.Integer]),
505 					new ListViewItem(16, ["size:y", conv.to!dstring(wserializer.getWindowValue("size:y")[0].get!int())], 
506 					[TextInputFieldType.None, TextInputFieldType.Integer])];
507 
508 			
509 		}
510 		tlw.propList.refresh();
511 	}
512 
513 	public void selectEvent(WindowElement we){
514 		foreach (s; elements) {
515 			if (s.element is we) {
516 				selection = s.name;
517 				updatePropertyList;
518 				return;
519 			}
520 		}
521 	}
522 
523 	public void menuEvent(Event ev){
524 		import pixelperfectengine.concrete.dialogs.filedialog : FileDialog;
525 		string source = (cast(MenuEvent)ev).itemSource;
526 		switch(source){
527 			case "export":
528 				ewh.addWindow(new FileDialog("Export Window"d, "export", &onExportWindow,
529 						[FileDialog.FileAssociationDescriptor("D file"d, ["*.d"])], "./", true));
530 				break;
531 			case "saveAs":
532 				ewh.addWindow(new FileDialog("Save Window as"d, "windowsaver", &onSaveFileAs,
533 						[FileDialog.FileAssociationDescriptor("SDL file"d, ["*.sdl"])], "./", true));
534 				break;
535 			case "save":
536 				if(wserializer.getFilename){
537 					wserializer.store;
538 				}else{
539 					ewh.addWindow(new FileDialog("Save Window as"d, "windowsaver", &onSaveFileAs,
540 							[FileDialog.FileAssociationDescriptor("SDL file"d, ["*.sdl"])], "./", true));
541 				}
542 				break;
543 			case "load":
544 				//stdio.writeln(&onLoadFile);
545 				ewh.addWindow(new FileDialog("Load Window"d, "windowloader", &onLoadFile,
546 						[FileDialog.FileAssociationDescriptor("SDL file"d, ["*.sdl"])], "./"));
547 				break;
548 			case "undo":
549 				eventStack.undo;
550 				break;
551 			case "redo":
552 				eventStack.redo;
553 				break;
554 			case "exit":
555 				onQuit;
556 				break;
557 			case "Label":
558 				typeSel = ElementType.Label;
559 				break;
560 			case "Button":
561 				typeSel = ElementType.Button;
562 				break;
563 			case "TextBox":
564 				typeSel = ElementType.TextBox;
565 				break;
566 			case "ListView":
567 				typeSel = ElementType.ListView;
568 				break;
569 			case "CheckBox":
570 				typeSel = ElementType.CheckBox;
571 				break;
572 			case "RadioButton":
573 				typeSel = ElementType.RadioButton;
574 				break;
575 			case "MenuBar":
576 				typeSel = ElementType.MenuBar;
577 				break;
578 			case "HSlider":
579 				typeSel = ElementType.HSlider;
580 				break;
581 			case "VSlider":
582 				typeSel = ElementType.VSlider;
583 				break;
584 			default:
585 				break;
586 		}
587 	}
588 	public void delElement() {
589 		if(selection != "Window" && selection.length)
590 			eventStack.addToTop(new DeleteEvent(elements[selection]));
591 	}
592 	public void initElemMove() {
593 		if(selection != "Window" && selection.length) {
594 			moveElemMode = true;
595 			moveElemOrig = elements[selection].element.getPosition;
596 		}
597 	}
598 	public void deinitElemMove() {
599 		if(moveElemMode) {
600 			moveElemMode = false;
601 			elements[selection].element.setPosition(moveElemOrig);
602 			dw.draw();
603 		}
604 	}
605 	public void finalizeElemMove() {
606 		if(moveElemMode) {
607 			moveElemMode = false;
608 			eventStack.addToTop(new MoveElemEvent(elements[selection].element.getPosition, moveElemOrig, selection));
609 		}
610 	}
611 	public void initElemResize() {
612 		if(selection == "Window") {
613 			
614 			
615 		} else if(selection.length) {
616 			resizeMode = true;
617 		}
618 	}
619 	public void deinitElemResize() {
620 		if(resizeMode) {
621 			resizeMode = false;
622 		}
623 	}
624 	public void finalizeElemResize() {
625 		if(resizeMode) {
626 			resizeMode = false;
627 			if(selection == "Window") {
628 
629 			} else if (selection.length) {
630 				if (x0 <= elements[selection].element.getPosition.left || y0 <= elements[selection].element.getPosition.top) {
631 					ewh.message("Resize error!", "Out of bound resizing!");
632 				} else {
633 					const Box newPos = Box(elements[selection].element.getPosition.left, elements[selection].element.getPosition.top, x0, y0);
634 					eventStack.addToTop(new MoveElemEvent(newPos, selection));
635 				}
636 			}
637 		}
638 	}
639 	public void whereTheMagicHappens(){
640 		while(!onExit){
641 			mainRaster.refresh();
642 			inputH.test();
643 		}
644 	}
645 	public void onQuit(){
646 		onExit = true;
647 	}
648 	public void controllerRemoved(uint ID){}
649 	public void controllerAdded(uint ID){}
650 	//public void keyPressed(string ID, uint timestamp, uint devicenumber, uint devicetype) {
651 	public void axisEvent(uint id, BindingCode code, uint timestamp, float value) {
652 
653 	}
654 	public void keyEvent(uint id, BindingCode code, uint timestamp, bool isPressed) {
655 		import pixelperfectengine.system.etc : hashCalc;
656 		if (isPressed) {
657 			switch(id){
658 				case hashCalc("undo"):
659 					eventStack.undo;
660 					break;
661 				case hashCalc("redo"):
662 					eventStack.redo;
663 					break;
664 				case hashCalc("del"):
665 					const string prevSelection = selection;
666 					selection = "window";
667 					eventStack.addToTop(new DeleteEvent(elements[prevSelection]));
668 					break;
669 				case hashCalc("sysesc"):
670 					deinitElemMove;
671 					deinitElemResize;
672 					typeSel = ElementType.NULL;
673 					break;
674 				case hashCalc("Label"):
675 					typeSel = ElementType.Label;
676 					break;
677 				case hashCalc("Button"):
678 					typeSel = ElementType.Button;
679 					break;
680 				case hashCalc("TextBox"):
681 					typeSel = ElementType.TextBox;
682 					break;
683 				case hashCalc("ListView"):
684 					typeSel = ElementType.ListView;
685 					break;
686 				case hashCalc("CheckBox"):
687 					typeSel = ElementType.CheckBox;
688 					break;
689 				case hashCalc("RadioButton"):
690 					typeSel = ElementType.RadioButton;
691 					break;
692 				case hashCalc("MenuBar"):
693 					typeSel = ElementType.MenuBar;
694 					break;
695 				case hashCalc("HSlider"):
696 					typeSel = ElementType.HSlider;
697 					break;
698 				case hashCalc("VSlider"):
699 					typeSel = ElementType.VSlider;
700 					break;
701 				default:
702 					break;
703 			}
704 		}
705 	}
706 	
707 }