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;
93 AddControl(form, GridSnap, GridSnap);
99 void ::ListClasses(DesignerBase designer, Class _class)
102 if(eClass_GetProperty(_class, "icon"))
103 designer.AddToolBoxClass(_class);
105 for(link = _class.derivatives.first; link; link = link.next)
106 designer.AddToolBoxClass(link.data);
110 void ListToolBoxClasses(DesignerBase designer)
113 Class commonControlClass = eSystem_FindClass(_class.module, "CommonControl");
114 for(link = commonControlClass.derivatives.first; link; link = link.next)
116 ListSubClasses(designer, link.data);
120 void ::ListSubClasses(DesignerBase designer, Class c)
123 ListClasses(designer, c);
124 for(link = c.derivatives.first; link; link = link.next)
125 ListSubClasses(designer, link.data);
128 void ::PrepareTestObject(DesignerBase designer, Window test)
130 test.parent = designer;
133 void ::DestroyObject(Window window)
135 // Better way to safeguard this? Still needed?
136 // if(eInstance_FindMethod(window, "Destroy"))
148 void ::FixProperty(Property prop, Window object)
150 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
152 if(!strcmp(prop.name, "parent"))
154 if(object.parent == guiApp.desktop)
155 object.parent = designer.form;
157 if(object.parent == designer.form)
159 ObjectInfo previous = object.object;
160 while((previous = previous.prev) && ((Window)previous.instance).parent != designer.form);
162 object.parent.children.Move(object, (Window)previous.instance);
166 if(!strcmp(prop.name, "master") && !object.master)
167 object.master = designer.form;
169 if(!strcmp(prop.name, "visible"))
171 object.setVisible = !object.style.hidden;
172 object.visible = true;
176 void ::CreateNew(EditBox editBox, Size clientSize, const char * name, const char * inherit)
178 int w = 632, h = 438;
179 if(clientSize.w - 40 -200 < w)
181 w = (clientSize.w - 40 - 200);
190 editBox.Printf("import \"ecere\"\n\n");
191 editBox.Printf("class %s : %s\n", name, inherit);
192 editBox.Printf("{\n");
194 editBox.Printf(" caption = $\"%s\";\n", name);
195 //editBox.Printf(" background = Color { 212, 208, 200 };\n");
197 editBox.Printf(" background = formColor;\n");
198 editBox.Printf(" borderStyle = sizable;\n");
199 editBox.Printf(" hasMaximize = true;\n");
200 editBox.Printf(" hasMinimize = true;\n");
201 editBox.Printf(" hasClose = true;\n");
202 //editBox.Printf(" position = { 20, 20 };\n");
203 editBox.Printf(" clientSize = { %d, %d };\n", w, h);
206 //editBox.Printf(" Button ok { parent = this, position = { 100, 100 }, size = { 80, 20 } };\n");
208 //editBox.Printf("\n Button ok\n {\n parent = this;\n\n bool NotifyClicked()\n {\n }\n };\n");
209 editBox.Printf("}\n");
212 editBox.Printf("class %s : %s\n", "SecondForm", inherit);
213 editBox.Printf("{\n");
214 editBox.Printf(" caption = \"%s\";\n", "SecondForm");
215 editBox.Printf(" background = Color { 100, 90, 120 };\n");
216 editBox.Printf(" borderStyle = sizable;\n");
217 editBox.Printf(" hasMaximize = true;\n");
218 editBox.Printf(" hasMinimize = true;\n");
219 editBox.Printf(" hasClose = true;\n");
220 editBox.Printf(" position = { 20, 20 };\n");
221 editBox.Printf(" size = { %d, %d };\n", 320, 200);
222 editBox.Printf(" Button ok { parent = this, caption = \"OK\", position = { A_RIGHT|10, A_RIGHT|10 }, size = { 80, 20 } };\n");
223 editBox.Printf("}\n");
228 void OnRedraw(Surface surface)
230 DrawSelection(master, surface);
233 bool OnMouseMove(int x, int y, Modifiers mods)
235 if(mods.isSideEffect)
238 if(x >= 0 && y >=0 && x < clientSize.w && y < clientSize.h)
243 Window parent = FindWindow(form, master, moved, x,y, true, null, null);
244 Window curParent = moved.parent;
246 int dx = x - xClicked;
247 int dy = y - yClicked;
249 if(resizeX || resizeY)
252 parent = (moved == form) ? master : form;
254 int w = moved.size.w;
255 int h = moved.size.h;
257 Anchor anchor = moved.anchor;
259 x = xBefore + parentBefore.absPosition.x - curParent.absPosition.x + parentBefore.clientStart.x - curParent.clientStart.x;
260 y = yBefore + parentBefore.absPosition.y - curParent.absPosition.y + parentBefore.clientStart.y - curParent.clientStart.y;
262 box.left = moved.absPosition.x - absPosition.x - clientStart.x;
263 box.top = moved.absPosition.y - absPosition.y - clientStart.y;
264 box.right = box.left + moved.size.w - 1;
265 box.bottom= box.top + moved.size.h - 1;
270 if(resizeX || resizeY)
295 w = Max(w, GridSnap);
300 h = Max(h, GridSnap);
303 if(resizeX < 0) x -= x % GridSnap;
304 if(resizeY < 0) y -= y % GridSnap;
310 if(parent != curParent)
312 Window master = moved.master;
314 x += curParent.absPosition.x - parent.absPosition.x + curParent.clientStart.x - parent.clientStart.x;
315 y += curParent.absPosition.y - parent.absPosition.y + curParent.clientStart.y - parent.clientStart.y;
317 moved.parent = parent;
320 ObjectInfo previous = moved.object;
321 while((previous = previous.prev) && ((Window)previous.instance).parent != form);
323 moved.parent.children.Move(moved, (Window)previous.instance);
326 moved.master = master;
332 activeDesigner.ModifyCode();
334 moved.Move(x, y, w, h);
336 if(resizeX < 0 || resizeY < 0)
341 x = Min(x, xBefore + wBefore - w);
346 y = Min(y, yBefore + hBefore - h);
348 moved.Move(x, y, w, h);
355 x = moved.position.x;
356 y = moved.position.y;
360 vpw = parent.clientSize.w;
361 vph = parent.clientSize.h;
367 else if(moved.style.fixed) // TOFIX: moved.borderStyle.fixed
369 if(!moved.dontScrollHorz && parent.scrollArea.w) vpw = parent.scrollArea.w;
370 if(!moved.dontScrollVert && parent.scrollArea.h) vph = parent.scrollArea.h;
373 if(anchor.left.type == offset) anchor.left.distance = x;
374 else if(anchor.left.type == relative) anchor.left.percent = (float)x / vpw;
375 if(anchor.top.type == offset) anchor.top.distance = y;
376 else if(anchor.top.type == relative) anchor.top.percent = (float)y / vph;
377 if(anchor.right.type == offset) anchor.right.distance = vpw - (x + w);
378 //else if(anchor.right.type == relative) anchor.right.percent = (float) (x + w) / vpw;
379 else if(anchor.right.type == relative) anchor.right.percent = (float) (vpw - (x + w)) / vpw;
380 if(anchor.bottom.type == offset) anchor.bottom.distance = vph - (y + h);
381 //else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (y + h) / vph;
382 else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (vph - (y + h)) / vph;
384 if(!anchor.left.type && !anchor.right.type)
386 anchor.horz.distance = (x + w / 2) - (vpw / 2);
387 //anchor.horz.type = anchor.horz.distance ? offset : 0;
389 else if(anchor.horz.type == middleRelative) anchor.horz.percent = (float) ((x + w / 2) - (vpw / 2)) / vpw;
390 if(!anchor.top.type && !anchor.bottom.type)
392 anchor.vert.distance = (y + h / 2) - (vph / 2);
393 //anchor.vert.type = anchor.vert.distance ? offset : 0;
395 else if(anchor.vert.type == middleRelative) anchor.vert.percent = (float)((y + h / 2) - (vph / 2)) / vph;
397 moved.anchor = anchor;
400 x = moved.position.x;
401 y = moved.position.y;
405 box.left = Min(box.left, moved.absPosition.x - absPosition.x - clientStart.x);
406 box.top = Min(box.top, moved.absPosition.y - absPosition.y - clientStart.y);
407 box.right = Max(box.right, moved.absPosition.x - absPosition.x - clientStart.x + moved.size.w - 1);
408 box.bottom= Max(box.bottom, moved.absPosition.y - absPosition.y - clientStart.y + moved.size.h - 1);
416 //activeDesigner.Update(box);
418 activeDesigner.UpdateProperties();
427 bool OnMouseOver(int x, int y, Modifiers mods)
429 x += absPosition.x - activeDesigner.absPosition.x + clientStart.x - activeDesigner.clientStart.x;
430 y += absPosition.y - activeDesigner.absPosition.y + clientStart.y - activeDesigner.clientStart.y;
432 if(x >= 0 && y >=0 && x < activeDesigner.clientSize.w && y < activeDesigner.clientSize.h)
434 if(activeDesigner.isDragging && !mods.isSideEffect)
435 activeDesigner.Activate();
442 bool OnMouseLeave(Modifiers mods)
444 // activeDesigner.classDesigner.ReleaseCapture();
448 bool OnLeftButtonDown(int x, int y, Modifiers mods)
450 const char * objectClass = activeDesigner.objectClass;
452 if(!objectClass && selected)
454 Window control = FindWindow(form, master, null, x, y, false, null, null);
455 bool onBorder = false;
456 //Window parent = selected.parent;
457 //if(control && (parent == control || parent == control.parent))
459 int cx = selected.absPosition.x - absPosition.x - clientStart.x;
460 int cy = selected.absPosition.y - absPosition.y - clientStart.y;
461 int cw = selected.size.w;
462 int ch = selected.size.h;
467 if(x >= cx - 7 && x < cx + cw + 6 && y >= cy - 7 && y < cy)
470 if(x >= cx - 7 && x < cx)
476 else if(x >= cx + cw/2 - 3 && x < cx + cw/2 + 3)
482 else if(x >= cx + cw && x < cx + cw + 6)
489 else if(x >= cx - 7 && x < cx + cw + 6 && y >= cy + ch && y < cy + ch + 6)
492 if(x >= cx - 7 && x < cx && y >= cy + ch && y < cy + ch + 6)
498 else if(x >= cx + cw/2 - 3 && x < cx + cw/2 + 3 && y >= cy + ch && y < cy + ch + 6)
504 else if(x >= cx + cw && x < cx + cw + 6 && y >= cy + ch && y < cy + ch + 6)
511 else if(x >= cx - 7 && x < cx && y >= cy - 7 && y < cy + ch + 6)
514 if(y >= cy + ch/2 - 3 && y < cy + ch/2 + 3)
521 else if(x >= cx + cw && x < cx + cw + 6 && y >= cy - 7 && y < cy + ch + 6)
524 if(y >= cy + ch / 2 - 3 && y < cy + ch/2 + 3)
540 Window parent = control.parent;
543 ((control == form) ? (Window)this : form).SetMouseRangeToWindow();
545 ((control == form) ? (Window)this : form).SetMouseRangeToClient();
550 if(selected != control)
551 activeDesigner.SelectObjectFromDesigner(control.object);
554 //activeDesigner.Update(null);
557 xBefore = control.position.x;
558 yBefore = control.position.y;
559 parentBefore = control.parent;
560 this.onBorder = onBorder;
561 wBefore = control.size.w;
562 hBefore = control.size.h;
568 void AddControl(Window parent, int x, int y)
570 const char * objectClass = activeDesigner.objectClass;
573 Class c = eSystem_FindClass(form._class.module, objectClass);
575 c = eSystem_FindClass(form._class.module.application, objectClass);
578 control = (Window)eInstance_New(c);
580 activeDesigner.CodeAddObject(control, &object);
584 x += parent.position.x + parent.clientStart.x;
585 y += parent.position.y + parent.clientStart.y;
586 parent = parent.parent;
589 control.object = object;
591 control.parent = parent;
592 control.master = form;
597 control.position.x = x;
598 control.position.y = y;
599 control.caption = object.name;
601 LockControls(control, control);
606 ObjectInfo previous = control.object;
607 while((previous = previous.prev) && ((Window)previous.instance).parent != form);
609 control.parent.children.Move(control, (Window)previous.instance);
612 activeDesigner.SheetAddObject(object);
614 //selected = control;
615 //activeDesigner.Update(null);
620 bool OnLeftButtonUp(int x, int y, Modifiers mods)
625 resizeX = resizeY = 0;
630 const char * objectClass = activeDesigner.objectClass;
633 Window parent = FindWindow(form, activeDesigner, null, x, y, true, &x, &y);
635 AddControl(parent, x, y);
641 bool OnLeftDoubleClick(int x, int y, Modifiers mods)
643 Window control = FindWindow(form, activeDesigner, null, x, y, false, &x, &y);
644 if(control && selected == control)
646 activeDesigner.AddDefaultMethod(control, form);
647 return false; // Prevent OnLeftButtonDown to be sent to the activated code editor
652 void ::LockControls(Window window, Window control)
656 if(window == control)
658 ObjectInfo object = window.object;
659 window.OnDestroy = ecere::gui::OnDestroy;
660 window.OnSysKeyDown = ecere::gui::OnSysKey;
661 window.OnSysKeyHit = ecere::gui::OnSysKey;
662 window.OnSysKeyUp = ecere::gui::OnSysKey;
664 if(object != object.oClass)
666 window.OnActivate = Control_OnActivate;
667 window.OnClose = null;
671 window.control = control;
672 for(child = window.firstChild; child; child = child.next)
674 LockControls(child, control);
678 void DrawSelection(Window window, Surface surface)
681 for(control = window.lastChild; control; control = control.prev)
683 if(selected == control)
685 //Window parent = selected.parent;
688 int w = selected.size.w;
689 int h = selected.size.h;
691 x = selected.absPosition.x - absPosition.x - clientStart.x;
692 y = selected.absPosition.y - absPosition.y - clientStart.y;
694 surface.SetBackground(Color {170, 170, 170});
695 surface.Area(x - 7, y - 7, x + w - 1 + 7, y-1);
696 surface.Area(x - 7, y + h, x + w - 1 + 7, y + h - 1 + 7);
697 surface.Area(x - 7, y - 7, x - 1, y + h - 1 + 7);
698 surface.Area(x + w, y - 7 , x + w - 1 + 7, y + h - 1 + 7);
700 surface.SetBackground(white);
702 surface.Area(x - 6, y - 6, x-1, y-1);
703 surface.Area(x + w/2 - 2, y - 6, x + w/2 + 2, y - 1);
704 surface.Area(x + w + 1, y - 6, x + w-1 + 6, y-1);
706 surface.Area(x - 6, y + h + 1, x-1, y + h - 1 + 6);
707 surface.Area(x + w/2 - 2, y + h + 1, x + w/2 + 2, y + h - 1 + 6);
708 surface.Area(x + w + 1, y + h + 1, x + w-1 + 6, y + h - 1 + 6);
710 surface.Area(x - 6, y + h/2 - 2, x-1, y + h /2 + 2);
711 surface.Area(x + w, y + h/2 - 2, x + w-1 + 6, y + h /2 + 2);
713 surface.SetForeground(black);
715 surface.Rectangle(x - 7, y - 7, x-1, y-1);
716 surface.Rectangle(x + w/2 - 3, y - 7, x + w/2 + 3, y - 1);
717 surface.Rectangle(x + w, y - 7, x + w-1 + 7, y-1);
719 surface.Rectangle(x - 7, y + h, x-1, y + h - 1 + 7);
720 surface.Rectangle(x + w/2 - 3, y + h, x + w/2 + 3, y + h - 1 + 7);
721 surface.Rectangle(x + w, y + h, x + w-1 + 7, y + h - 1 + 7);
723 surface.Rectangle(x - 7, y + h/2 - 3, x-1, y + h /2 + 3);
724 surface.Rectangle(x + w, y + h/2 - 3, x + w-1 + 7, y + h /2 + 3);
726 DrawSelection(control, surface);
731 static bool Control_OnActivate(Window window, bool active, Window previous, bool * goOn, bool direct)
741 static Window GetWindow(Window window, int x, int y, int * rx, int * ry)
743 Window result = null, control;
744 for(control = window.lastChild; control; control = control.prev)
746 int cx = control.position.x;
747 int cy = control.position.y;
748 int cw = control.size.w;
749 int ch = control.size.h;
751 if(x >= cx && x < cx + cw && y >= cy && y < cy + ch)
753 x -= control.position.x + control.clientStart.x;
754 y -= control.position.y + control.clientStart.y;
755 result = GetWindow(control, x, y, rx, ry);
768 static Window FindWindow(Window form, Window window, Window moved, int x, int y, bool asParent, int * dx, int * dy)
770 Window result = null, control;
771 for(control = window.lastChild; control; control = control.prev)
773 if(control != moved && control.control == control && (!asParent || control.name))
775 if(!form || control == form)
777 int cx = control.position.x - (asParent ? 0 : 7);
778 int cy = control.position.y - (asParent ? 0 : 7);
779 int cw = control.size.w + (asParent ? 0 : 14);
780 int ch = control.size.h + (asParent ? 0 : 14);
782 int sx = x - (control.position.x + control.clientStart.x);
783 int sy = y - (control.position.y + control.clientStart.y);
784 if((sx >= 0 && sy >= 0 && sx < control.clientSize.w && sy < control.clientSize.h) ||
785 !(x >= cx && x < cx + cw && y >= cy && y < cy + ch))
786 result = FindWindow(null, control, moved, sx, sy, asParent, dx, dy);
789 else if(x >= cx && x < cx + cw && y >= cy && y < cy + ch)
802 static void OnDestroy(Window window)
804 FormDesigner designer = activeDesigner ? (FormDesigner)activeDesigner.classDesigner : null;
806 if(designer && designer.form)
807 activeDesigner.DeleteObject(window.object);
810 static bool OnSysKey(Window window, Key key, unichar ch)
815 static void DrawGrid(Window window, Surface surface)
818 int w = window.clientSize.w;
819 int h = window.clientSize.h;
820 Color background = window.background;
823 if(background.r > 128 || background.g > 128)
824 surface.SetForeground(black);
826 surface.SetForeground(white);
828 for(y = GridSnap; y < h; y += GridSnap)
829 for(x = GridSnap; x < w; x += GridSnap)
830 surface.PutPixel(x, y);
833 static bool OnKeyDown(Window window, Key key, unichar ch)
835 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
838 if(designer.selected && designer.selected != designer.form)
840 bool confirmation = activeDesigner.ObjectContainsCode(designer.selected.object);
843 confirmation = MessageBox { type = okCancel, master = window.master, caption = $"Deleting control with code", contents = $"Control contains code. Delete anyways?" }.Modal() != ok;
845 // Confirmation if control contains other controls
848 Window child = designer.selected.firstChild;
849 for( ; child; child = child.next)
851 if(child.control == child)
859 confirmation = MessageBox { type = okCancel, master = window.master, caption = $"Deleting control with children", contents = $"Control contains other controls. Delete control and children?"}.Modal() != ok;
864 activeDesigner.ModifyCode();
866 designer.selected.Destroy(0);
867 //activeDesigner.Update(null);
868 designer.Update(null);