7 class FormDesigner : ClassDesignerBase
14 // clickThrough = true;
19 int xClicked, yClicked;
26 // CLASS EDITOR METHODS
27 void SelectObject(ObjectInfo object, Window control)
29 if((object && form != object.oClass.instance) || !object)
34 form = (Window)(object ? object.oClass.instance : null);
42 //activeDesigner.Update(null);
45 void ::CreateObject(DesignerBase designer, Window instance, ObjectInfo object, bool isClass, Window _class)
47 instance.object = object;
48 instance.formDesigner = true;
49 LockControls(instance, instance);
52 // TESTING THIS IN POST... instance.visible = false;
53 instance.parent = designer;
54 instance.OnRedraw = DrawGrid;
55 //instance.OnLeftButtonUp = ecere::OnLeftButtonUp;
56 //instance.OnLeftButtonDown = ecere::OnLeftButtonDown;
57 //instance.OnLeftDoubleClick = ecere::OnLeftDoubleClick;
58 instance.OnSysKeyDown = ecere::gui::OnKeyDown;
63 // instance.parent = _class;
67 void ::PostCreateObject(Window instance, ObjectInfo object, bool isClass, Window _class)
69 if(instance.displayDriver && !strcmp(instance.displayDriver, "LFB")) return;
70 instance.setVisible = instance.visible;
73 instance.visible = false;
76 else if(instance.parent == guiApp.desktop) // TOCHECK: Verify if there's 2 guiApp/desktop's to be worried about
77 instance.autoCreate = false;
79 instance.visible = true;
82 void ::DroppedObject(Window instance, ObjectInfo object, bool isClass, Window _class)
84 instance.parent = _class;
85 instance.caption = object.name;
94 selected.absPosition.x - absPosition.x - clientStart.x + selected.clientStart.x + GridSnap,
95 selected.absPosition.y - absPosition.y - clientStart.y + selected.clientStart.y + GridSnap, 0);
100 void ::ListClasses(DesignerBase designer, Class _class)
103 if(eClass_GetProperty(_class, "icon"))
104 designer.AddToolBoxClass(_class);
106 for(link = _class.derivatives.first; link; link = link.next)
107 designer.AddToolBoxClass(link.data);
111 void ListToolBoxClasses(DesignerBase designer)
114 Class commonControlClass = eSystem_FindClass(_class.module, "CommonControl");
115 for(link = commonControlClass.derivatives.first; link; link = link.next)
117 ListSubClasses(designer, link.data);
121 void ::ListSubClasses(DesignerBase designer, Class c)
124 ListClasses(designer, c);
125 for(link = c.derivatives.first; link; link = link.next)
126 ListSubClasses(designer, link.data);
129 void ::PrepareTestObject(DesignerBase designer, Window test)
131 test.parent = designer;
134 void ::DestroyObject(Window window)
136 // Better way to safeguard this? Still needed?
137 // if(eInstance_FindMethod(window, "Destroy"))
149 void ::FixProperty(Property prop, Window object)
151 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
153 if(!strcmp(prop.name, "parent"))
155 if(object.parent == guiApp.desktop)
156 object.parent = designer.form;
158 if(object.parent == designer.form)
160 ObjectInfo previous = object.object;
161 while((previous = previous.prev) && ((Window)previous.instance).parent != designer.form);
163 object.parent.children.Move(object, (Window)previous.instance);
167 if(!strcmp(prop.name, "master") && !object.master)
168 object.master = designer.form;
170 if(!strcmp(prop.name, "visible"))
172 object.setVisible = !object.style.hidden;
173 object.visible = true;
177 void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit)
179 int w = 632, h = 438;
180 if(clientSize.w - 40 -200 < w)
182 w = (clientSize.w - 40 - 200);
191 editBox.Printf("import \"ecere\"\n\n");
192 editBox.Printf("class %s : %s\n", name, inherit);
193 editBox.Printf("{\n");
195 editBox.Printf(" caption = \"%s\";\n", name);
196 //editBox.Printf(" background = Color { 212, 208, 200 };\n");
198 editBox.Printf(" background = formColor;\n");
199 editBox.Printf(" borderStyle = sizable;\n");
200 editBox.Printf(" hasMaximize = true;\n");
201 editBox.Printf(" hasMinimize = true;\n");
202 editBox.Printf(" hasClose = true;\n");
203 //editBox.Printf(" position = { 20, 20 };\n");
204 editBox.Printf(" clientSize = { %d, %d };\n", w, h);
207 //editBox.Printf(" Button ok { parent = this, position = { 100, 100 }, size = { 80, 20 } };\n");
209 //editBox.Printf("\n Button ok\n {\n parent = this;\n\n bool NotifyClicked()\n {\n }\n };\n");
210 editBox.Printf("}\n");
213 editBox.Printf("class %s : %s\n", "SecondForm", inherit);
214 editBox.Printf("{\n");
215 editBox.Printf(" caption = \"%s\";\n", "SecondForm");
216 editBox.Printf(" background = Color { 100, 90, 120 };\n");
217 editBox.Printf(" borderStyle = sizable;\n");
218 editBox.Printf(" hasMaximize = true;\n");
219 editBox.Printf(" hasMinimize = true;\n");
220 editBox.Printf(" hasClose = true;\n");
221 editBox.Printf(" position = { 20, 20 };\n");
222 editBox.Printf(" size = { %d, %d };\n", 320, 200);
223 editBox.Printf(" Button ok { parent = this, caption = \"OK\", position = { A_RIGHT|10, A_RIGHT|10 }, size = { 80, 20 } };\n");
224 editBox.Printf("}\n");
229 void OnRedraw(Surface surface)
231 DrawSelection(master, surface);
234 bool OnMouseMove(int x, int y, Modifiers mods)
236 if(mods.isSideEffect)
239 if(x >= 0 && y >=0 && x < clientSize.w && y < clientSize.h)
244 Window parent = FindWindow(form, master, moved, x,y, true, null, null);
245 Window curParent = moved.parent;
247 int dx = x - xClicked;
248 int dy = y - yClicked;
250 if(resizeX || resizeY)
253 parent = (moved == form) ? master : form;
255 int w = moved.size.w;
256 int h = moved.size.h;
258 Anchor anchor = moved.anchor;
260 x = xBefore + parentBefore.absPosition.x - curParent.absPosition.x + parentBefore.clientStart.x - curParent.clientStart.x;
261 y = yBefore + parentBefore.absPosition.y - curParent.absPosition.y + parentBefore.clientStart.y - curParent.clientStart.y;
263 box.left = moved.absPosition.x - absPosition.x - clientStart.x;
264 box.top = moved.absPosition.y - absPosition.y - clientStart.y;
265 box.right = box.left + moved.size.w - 1;
266 box.bottom= box.top + moved.size.h - 1;
271 if(resizeX || resizeY)
296 w = Max(w, GridSnap);
301 h = Max(h, GridSnap);
304 if(resizeX < 0) x -= x % GridSnap;
305 if(resizeY < 0) y -= y % GridSnap;
311 if(parent != curParent)
313 Window master = moved.master;
315 x += curParent.absPosition.x - parent.absPosition.x + curParent.clientStart.x - parent.clientStart.x;
316 y += curParent.absPosition.y - parent.absPosition.y + curParent.clientStart.y - parent.clientStart.y;
318 moved.parent = parent;
321 ObjectInfo previous = moved.object;
322 while((previous = previous.prev) && ((Window)previous.instance).parent != form);
324 moved.parent.children.Move(moved, (Window)previous.instance);
327 moved.master = master;
333 activeDesigner.ModifyCode();
335 moved.Move(x, y, w, h);
337 if(resizeX < 0 || resizeY < 0)
342 x = Min(x, xBefore + wBefore - w);
347 y = Min(y, yBefore + hBefore - h);
349 moved.Move(x, y, w, h);
356 x = moved.position.x;
357 y = moved.position.y;
361 vpw = parent.clientSize.w;
362 vph = parent.clientSize.h;
368 else if(moved.style.fixed) // TOFIX: moved.borderStyle.fixed
370 if(!moved.dontScrollHorz && parent.scrollArea.w) vpw = parent.scrollArea.w;
371 if(!moved.dontScrollVert && parent.scrollArea.h) vph = parent.scrollArea.h;
374 if(anchor.left.type == offset) anchor.left.distance = x;
375 else if(anchor.left.type == relative) anchor.left.percent = (float)x / vpw;
376 if(anchor.top.type == offset) anchor.top.distance = y;
377 else if(anchor.top.type == relative) anchor.top.percent = (float)y / vph;
378 if(anchor.right.type == offset) anchor.right.distance = vpw - (x + w);
379 //else if(anchor.right.type == relative) anchor.right.percent = (float) (x + w) / vpw;
380 else if(anchor.right.type == relative) anchor.right.percent = (float) (vpw - (x + w)) / vpw;
381 if(anchor.bottom.type == offset) anchor.bottom.distance = vph - (y + h);
382 //else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (y + h) / vph;
383 else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (vph - (y + h)) / vph;
385 if(!anchor.left.type && !anchor.right.type)
387 anchor.horz.distance = (x + w / 2) - (vpw / 2);
388 //anchor.horz.type = anchor.horz.distance ? offset : 0;
390 else if(anchor.horz.type == middleRelative) anchor.horz.percent = (float) ((x + w / 2) - (vpw / 2)) / vpw;
391 if(!anchor.top.type && !anchor.bottom.type)
393 anchor.vert.distance = (y + h / 2) - (vph / 2);
394 //anchor.vert.type = anchor.vert.distance ? offset : 0;
396 else if(anchor.vert.type == middleRelative) anchor.vert.percent = (float)((y + h / 2) - (vph / 2)) / vph;
398 moved.anchor = anchor;
401 x = moved.position.x;
402 y = moved.position.y;
406 box.left = Min(box.left, moved.absPosition.x - absPosition.x - clientStart.x);
407 box.top = Min(box.top, moved.absPosition.y - absPosition.y - clientStart.y);
408 box.right = Max(box.right, moved.absPosition.x - absPosition.x - clientStart.x + moved.size.w - 1);
409 box.bottom= Max(box.bottom, moved.absPosition.y - absPosition.y - clientStart.y + moved.size.h - 1);
417 //activeDesigner.Update(box);
419 activeDesigner.UpdateProperties();
428 bool OnMouseOver(int x, int y, Modifiers mods)
430 x += absPosition.x - activeDesigner.absPosition.x + clientStart.x - activeDesigner.clientStart.x;
431 y += absPosition.y - activeDesigner.absPosition.y + clientStart.y - activeDesigner.clientStart.y;
433 if(x >= 0 && y >=0 && x < activeDesigner.clientSize.w && y < activeDesigner.clientSize.h)
435 if(activeDesigner.isDragging && !mods.isSideEffect)
436 activeDesigner.Activate();
443 bool OnMouseLeave(Modifiers mods)
445 // activeDesigner.classDesigner.ReleaseCapture();
449 bool OnLeftButtonDown(int x, int y, Modifiers mods)
451 char * objectClass = activeDesigner.objectClass;
453 if(!objectClass && selected)
455 Window control = FindWindow(form, master, null, x, y, false, null, null);
456 bool onBorder = false;
457 Window parent = selected.parent;
458 //if(control && (parent == control || parent == control.parent))
460 int cx = selected.absPosition.x - absPosition.x - clientStart.x;
461 int cy = selected.absPosition.y - absPosition.y - clientStart.y;
462 int cw = selected.size.w;
463 int ch = selected.size.h;
468 if(x >= cx - 7 && x < cx + cw + 6 && y >= cy - 7 && y < cy)
471 if(x >= cx - 7 && x < cx)
477 else if(x >= cx + cw/2 - 3 && x < cx + cw/2 + 3)
483 else if(x >= cx + cw && x < cx + cw + 6)
490 else if(x >= cx - 7 && x < cx + cw + 6 && y >= cy + ch && y < cy + ch + 6)
493 if(x >= cx - 7 && x < cx && y >= cy + ch && y < cy + ch + 6)
499 else if(x >= cx + cw/2 - 3 && x < cx + cw/2 + 3 && y >= cy + ch && y < cy + ch + 6)
505 else if(x >= cx + cw && x < cx + cw + 6 && y >= cy + ch && y < cy + ch + 6)
512 else if(x >= cx - 7 && x < cx && y >= cy - 7 && y < cy + ch + 6)
515 if(y >= cy + ch/2 - 3 && y < cy + ch/2 + 3)
522 else if(x >= cx + cw && x < cx + cw + 6 && y >= cy - 7 && y < cy + ch + 6)
525 if(y >= cy + ch / 2 - 3 && y < cy + ch/2 + 3)
541 Window parent = control.parent;
544 ((control == form) ? (Window)this : form).SetMouseRangeToWindow();
546 ((control == form) ? (Window)this : form).SetMouseRangeToClient();
551 if(selected != control)
552 activeDesigner.SelectObjectFromDesigner(control.object);
555 //activeDesigner.Update(null);
558 xBefore = control.position.x;
559 yBefore = control.position.y;
560 parentBefore = control.parent;
561 this.onBorder = onBorder;
562 wBefore = control.size.w;
563 hBefore = control.size.h;
569 bool OnLeftButtonUp(int x, int y, Modifiers mods)
574 resizeX = resizeY = 0;
579 char * objectClass = activeDesigner.objectClass;
582 Window parent = FindWindow(form, activeDesigner, null, x, y, true, &x, &y);
586 Window control = (Window)eInstance_New(eSystem_FindClass(form._class.module, objectClass));
588 activeDesigner.CodeAddObject(control, &object);
592 x += parent.position.x + parent.clientStart.x;
593 y += parent.position.y + parent.clientStart.y;
594 parent = parent.parent;
597 control.object = object;
599 control.parent = parent;
600 control.master = form;
605 control.position.x = x;
606 control.position.y = y;
607 control.caption = object.name;
609 LockControls(control, control);
614 ObjectInfo previous = control.object;
615 while((previous = previous.prev) && ((Window)previous.instance).parent != form);
617 control.parent.children.Move(control, (Window)previous.instance);
620 activeDesigner.SheetAddObject(object);
622 //selected = control;
623 //activeDesigner.Update(null);
631 bool OnLeftDoubleClick(int x, int y, Modifiers mods)
633 Window control = FindWindow(form, activeDesigner, null, x, y, false, &x, &y);
634 if(control && selected == control)
636 activeDesigner.AddDefaultMethod(control, form);
637 return false; // Prevent OnLeftButtonDown to be sent to the activated code editor
642 void ::LockControls(Window window, Window control)
646 if(window == control)
648 ObjectInfo object = window.object;
649 window.OnDestroy = ecere::gui::OnDestroy;
650 window.OnSysKeyDown = ecere::gui::OnSysKey;
651 window.OnSysKeyHit = ecere::gui::OnSysKey;
652 window.OnSysKeyUp = ecere::gui::OnSysKey;
654 if(object != object.oClass)
656 window.OnActivate = Control_OnActivate;
657 window.OnClose = null;
661 window.control = control;
662 for(child = window.firstChild; child; child = child.next)
664 LockControls(child, control);
668 void DrawSelection(Window window, Surface surface)
670 Window result = null, control;
671 for(control = window.lastChild; control; control = control.prev)
673 if(selected == control)
675 Window parent = selected.parent;
678 int w = selected.size.w;
679 int h = selected.size.h;
681 x = selected.absPosition.x - absPosition.x - clientStart.x;
682 y = selected.absPosition.y - absPosition.y - clientStart.y;
684 surface.SetBackground(Color {170, 170, 170});
685 surface.Area(x - 7, y - 7, x + w - 1 + 7, y-1);
686 surface.Area(x - 7, y + h, x + w - 1 + 7, y + h - 1 + 7);
687 surface.Area(x - 7, y - 7, x - 1, y + h - 1 + 7);
688 surface.Area(x + w, y - 7 , x + w - 1 + 7, y + h - 1 + 7);
690 surface.SetBackground(white);
692 surface.Area(x - 6, y - 6, x-1, y-1);
693 surface.Area(x + w/2 - 2, y - 6, x + w/2 + 2, y - 1);
694 surface.Area(x + w + 1, y - 6, x + w-1 + 6, y-1);
696 surface.Area(x - 6, y + h + 1, x-1, y + h - 1 + 6);
697 surface.Area(x + w/2 - 2, y + h + 1, x + w/2 + 2, y + h - 1 + 6);
698 surface.Area(x + w + 1, y + h + 1, x + w-1 + 6, y + h - 1 + 6);
700 surface.Area(x - 6, y + h/2 - 2, x-1, y + h /2 + 2);
701 surface.Area(x + w, y + h/2 - 2, x + w-1 + 6, y + h /2 + 2);
703 surface.SetForeground(black);
705 surface.Rectangle(x - 7, y - 7, x-1, y-1);
706 surface.Rectangle(x + w/2 - 3, y - 7, x + w/2 + 3, y - 1);
707 surface.Rectangle(x + w, y - 7, x + w-1 + 7, y-1);
709 surface.Rectangle(x - 7, y + h, x-1, y + h - 1 + 7);
710 surface.Rectangle(x + w/2 - 3, y + h, x + w/2 + 3, y + h - 1 + 7);
711 surface.Rectangle(x + w, y + h, x + w-1 + 7, y + h - 1 + 7);
713 surface.Rectangle(x - 7, y + h/2 - 3, x-1, y + h /2 + 3);
714 surface.Rectangle(x + w, y + h/2 - 3, x + w-1 + 7, y + h /2 + 3);
716 DrawSelection(control, surface);
721 static bool Control_OnActivate(Window window, bool active, Window previous, bool * goOn, bool direct)
731 static Window GetWindow(Window window, int x, int y, int * rx, int * ry)
733 Window result = null, control;
734 for(control = window.lastChild; control; control = control.prev)
736 int cx = control.position.x;
737 int cy = control.position.y;
738 int cw = control.size.w;
739 int ch = control.size.h;
741 if(x >= cx && x < cx + cw && y >= cy && y < cy + ch)
743 x -= control.position.x + control.clientStart.x;
744 y -= control.position.y + control.clientStart.y;
745 result = GetWindow(control, x, y, rx, ry);
758 static Window FindWindow(Window form, Window window, Window moved, int x, int y, bool asParent, int * dx, int * dy)
760 Window result = null, control;
761 for(control = window.lastChild; control; control = control.prev)
763 if(control != moved && control.control == control && (!asParent || control.name))
765 if(!form || control == form)
767 int cx = control.position.x - (asParent ? 0 : 7);
768 int cy = control.position.y - (asParent ? 0 : 7);
769 int cw = control.size.w + (asParent ? 0 : 14);
770 int ch = control.size.h + (asParent ? 0 : 14);
772 int sx = x - (control.position.x + control.clientStart.x);
773 int sy = y - (control.position.y + control.clientStart.y);
774 if((sx >= 0 && sy >= 0 && sx < control.clientSize.w && sy < control.clientSize.h) ||
775 !(x >= cx && x < cx + cw && y >= cy && y < cy + ch))
776 result = FindWindow(null, control, moved, sx, sy, asParent, dx, dy);
779 else if(x >= cx && x < cx + cw && y >= cy && y < cy + ch)
792 static void OnDestroy(Window window)
794 FormDesigner designer = activeDesigner ? (FormDesigner)activeDesigner.classDesigner : null;
796 if(designer && designer.form)
797 activeDesigner.DeleteObject(window.object);
800 static bool OnSysKey(Window window, Key key, unichar ch)
805 static void DrawGrid(Window window, Surface surface)
808 int w = window.clientSize.w;
809 int h = window.clientSize.h;
810 Color background = window.background;
813 if(background.r > 128 || background.g > 128)
814 surface.SetForeground(black);
816 surface.SetForeground(white);
818 for(y = GridSnap; y < h; y += GridSnap)
819 for(x = GridSnap; x < w; x += GridSnap)
820 surface.PutPixel(x, y);
823 static bool OnKeyDown(Window window, Key key, unichar ch)
825 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
828 if(designer.selected && designer.selected != designer.form)
830 bool confirmation = activeDesigner.ObjectContainsCode(designer.selected.object);
833 confirmation = MessageBox { type = okCancel, master = window.master, caption = $"Deleting control with code", contents = $"Control contains code. Delete anyways?" }.Modal() != ok;
835 // Confirmation if control contains other controls
838 Window child = designer.selected.firstChild;
839 for( ; child; child = child.next)
841 if(child.control == child)
849 confirmation = MessageBox { type = okCancel, master = window.master, caption = $"Deleting control with children", contents = $"Control contains other controls. Delete control and children?"}.Modal() != ok;
854 activeDesigner.ModifyCode();
856 designer.selected.Destroy(0);
857 //activeDesigner.Update(null);
858 designer.Update(null);