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 LockControls(instance, instance);
51 // TESTING THIS IN POST... instance.visible = false;
52 instance.parent = designer;
53 instance.OnRedraw = DrawGrid;
54 //instance.OnLeftButtonUp = ecere::OnLeftButtonUp;
55 //instance.OnLeftButtonDown = ecere::OnLeftButtonDown;
56 //instance.OnLeftDoubleClick = ecere::OnLeftDoubleClick;
57 instance.OnSysKeyDown = ecere::gui::OnKeyDown;
62 // instance.parent = _class;
66 void ::PostCreateObject(Window instance, ObjectInfo object, bool isClass, Window _class)
68 if(instance.displayDriver && !strcmp(instance.displayDriver, "LFB")) return;
69 instance.setVisible = instance.visible;
72 instance.visible = false;
75 else if(instance.parent == guiApp.desktop) // TOCHECK: Verify if there's 2 guiApp/desktop's to be worried about
76 instance.autoCreate = false;
78 instance.visible = true;
81 void ::DroppedObject(Window instance, ObjectInfo object, bool isClass, Window _class)
83 instance.parent = _class;
84 instance.text = object.name;
93 selected.absPosition.x - absPosition.x - clientStart.x + selected.clientStart.x + GridSnap,
94 selected.absPosition.y - absPosition.y - clientStart.y + selected.clientStart.y + GridSnap, 0);
99 void ::ListClasses(DesignerBase designer, Class _class)
102 designer.AddToolBoxClass(_class);
104 for(link = _class.derivatives.first; link; link = link.next)
105 designer.AddToolBoxClass(link.data);
109 void ListToolBoxClasses(DesignerBase designer)
112 Class commonControlClass = eSystem_FindClass(_class.module, "CommonControl");
113 for(link = commonControlClass.derivatives.first; link; link = link.next)
115 ListClasses(designer, link.data);
119 void ::PrepareTestObject(DesignerBase designer, Window test)
121 test.parent = designer;
124 void ::DestroyObject(Window window)
126 // Better way to safeguard this? Still needed?
127 // if(eInstance_FindMethod(window, "Destroy"))
139 void ::FixProperty(Property prop, Window object)
141 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
143 if(!strcmp(prop.name, "parent"))
145 if(object.parent == guiApp.desktop)
146 object.parent = designer.form;
148 if(object.parent == designer.form)
150 ObjectInfo previous = object.object;
151 while((previous = previous.prev) && ((Window)previous.instance).parent != designer.form);
153 object.parent.children.Move(object, (Window)previous.instance);
157 if(!strcmp(prop.name, "master") && !object.master)
158 object.master = designer.form;
160 if(!strcmp(prop.name, "visible"))
162 object.setVisible = !object.style.hidden;
163 object.visible = true;
167 void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit)
169 int w = 640, h = 480;
170 if(clientSize.w - 40 -200 < w)
172 w = (clientSize.w - 40 - 200);
181 editBox.Printf("import \"ecere\"\n\n");
182 editBox.Printf("class %s : %s\n", name, inherit);
183 editBox.Printf("{\n");
185 editBox.Printf(" text = \"%s\";\n", name);
186 //editBox.Printf(" background = Color { 212, 208, 200 };\n");
188 editBox.Printf(" background = activeBorder;\n");
189 editBox.Printf(" borderStyle = sizable;\n");
190 editBox.Printf(" hasMaximize = true;\n");
191 editBox.Printf(" hasMinimize = true;\n");
192 editBox.Printf(" hasClose = true;\n");
193 //editBox.Printf(" position = { 20, 20 };\n");
194 editBox.Printf(" size = { %d, %d };\n", w, h);
197 //editBox.Printf(" Button ok { parent = this, position = { 100, 100 }, size = { 80, 20 } };\n");
199 //editBox.Printf("\n Button ok\n {\n parent = this;\n\n bool NotifyClicked()\n {\n }\n };\n");
200 editBox.Printf("}\n");
203 editBox.Printf("class %s : %s\n", "SecondForm", inherit);
204 editBox.Printf("{\n");
205 editBox.Printf(" text = \"%s\";\n", "SecondForm");
206 editBox.Printf(" background = Color { 100, 90, 120 };\n");
207 editBox.Printf(" borderStyle = sizable;\n");
208 editBox.Printf(" hasMaximize = true;\n");
209 editBox.Printf(" hasMinimize = true;\n");
210 editBox.Printf(" hasClose = true;\n");
211 editBox.Printf(" position = { 20, 20 };\n");
212 editBox.Printf(" size = { %d, %d };\n", 320, 200);
213 editBox.Printf(" Button ok { parent = this, text = \"OK\", position = { A_RIGHT|10, A_RIGHT|10 }, size = { 80, 20 } };\n");
214 editBox.Printf("}\n");
219 void OnRedraw(Surface surface)
221 DrawSelection(master, surface);
224 bool OnMouseMove(int x, int y, Modifiers mods)
226 if(mods.isSideEffect)
229 if(x >= 0 && y >=0 && x < clientSize.w && y < clientSize.h)
234 Window parent = FindWindow(form, master, moved, x,y, true, null, null);
235 Window curParent = moved.parent;
237 int dx = x - xClicked;
238 int dy = y - yClicked;
240 if(resizeX || resizeY)
243 parent = (moved == form) ? master : form;
245 int w = moved.size.w;
246 int h = moved.size.h;
248 Anchor anchor = moved.anchor;
250 x = xBefore + parentBefore.absPosition.x - curParent.absPosition.x + parentBefore.clientStart.x - curParent.clientStart.x;
251 y = yBefore + parentBefore.absPosition.y - curParent.absPosition.y + parentBefore.clientStart.y - curParent.clientStart.y;
253 box.left = moved.absPosition.x - absPosition.x - clientStart.x;
254 box.top = moved.absPosition.y - absPosition.y - clientStart.y;
255 box.right = box.left + moved.size.w - 1;
256 box.bottom= box.top + moved.size.h - 1;
261 if(resizeX || resizeY)
286 w = Max(w, GridSnap);
291 h = Max(h, GridSnap);
294 if(resizeX < 0) x -= x % GridSnap;
295 if(resizeY < 0) y -= y % GridSnap;
301 if(parent != curParent)
303 Window master = moved.master;
305 x += curParent.absPosition.x - parent.absPosition.x + curParent.clientStart.x - parent.clientStart.x;
306 y += curParent.absPosition.y - parent.absPosition.y + curParent.clientStart.y - parent.clientStart.y;
308 moved.parent = parent;
311 ObjectInfo previous = moved.object;
312 while((previous = previous.prev) && ((Window)previous.instance).parent != form);
314 moved.parent.children.Move(moved, (Window)previous.instance);
317 moved.master = master;
323 activeDesigner.ModifyCode();
325 moved.Move(x, y, w, h);
327 if(resizeX < 0 || resizeY < 0)
332 x = Min(x, xBefore + wBefore - w);
337 y = Min(y, yBefore + hBefore - h);
339 moved.Move(x, y, w, h);
346 x = moved.position.x;
347 y = moved.position.y;
351 vpw = parent.clientSize.w;
352 vph = parent.clientSize.h;
358 else if(moved.style.fixed) // TOFIX: moved.borderStyle.fixed
360 if(!moved.dontScrollHorz && parent.scrollArea.w) vpw = parent.scrollArea.w;
361 if(!moved.dontScrollVert && parent.scrollArea.h) vph = parent.scrollArea.h;
364 if(anchor.left.type == offset) anchor.left.distance = x;
365 else if(anchor.left.type == relative) anchor.left.percent = (float)x / vpw;
366 if(anchor.top.type == offset) anchor.top.distance = y;
367 else if(anchor.top.type == relative) anchor.top.percent = (float)y / vph;
368 if(anchor.right.type == offset) anchor.right.distance = vpw - (x + w);
369 //else if(anchor.right.type == relative) anchor.right.percent = (float) (x + w) / vpw;
370 else if(anchor.right.type == relative) anchor.right.percent = (float) (vpw - (x + w)) / vpw;
371 if(anchor.bottom.type == offset) anchor.bottom.distance = vph - (y + h);
372 //else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (y + h) / vph;
373 else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (vph - (y + h)) / vph;
375 if(!anchor.left.type && !anchor.right.type)
377 anchor.horz.distance = (x + w / 2) - (vpw / 2);
378 //anchor.horz.type = anchor.horz.distance ? offset : 0;
380 else if(anchor.horz.type == middleRelative) anchor.horz.percent = (float) ((x + w / 2) - (vpw / 2)) / vpw;
381 if(!anchor.top.type && !anchor.bottom.type)
383 anchor.vert.distance = (y + h / 2) - (vph / 2);
384 //anchor.vert.type = anchor.vert.distance ? offset : 0;
386 else if(anchor.vert.type == middleRelative) anchor.vert.percent = (float)((y + h / 2) - (vph / 2)) / vph;
388 moved.anchor = anchor;
391 x = moved.position.x;
392 y = moved.position.y;
396 box.left = Min(box.left, moved.absPosition.x - absPosition.x - clientStart.x);
397 box.top = Min(box.top, moved.absPosition.y - absPosition.y - clientStart.y);
398 box.right = Max(box.right, moved.absPosition.x - absPosition.x - clientStart.x + moved.size.w - 1);
399 box.bottom= Max(box.bottom, moved.absPosition.y - absPosition.y - clientStart.y + moved.size.h - 1);
407 //activeDesigner.Update(box);
409 activeDesigner.UpdateProperties();
418 bool OnMouseOver(int x, int y, Modifiers mods)
420 x += absPosition.x - activeDesigner.absPosition.x + clientStart.x - activeDesigner.clientStart.x;
421 y += absPosition.y - activeDesigner.absPosition.y + clientStart.y - activeDesigner.clientStart.y;
423 if(x >= 0 && y >=0 && x < activeDesigner.clientSize.w && y < activeDesigner.clientSize.h)
425 if(activeDesigner.isDragging && !mods.isSideEffect)
426 activeDesigner.Activate();
433 bool OnMouseLeave(Modifiers mods)
435 // activeDesigner.classDesigner.ReleaseCapture();
439 bool OnLeftButtonDown(int x, int y, Modifiers mods)
441 char * objectClass = activeDesigner.objectClass;
443 if(!objectClass && selected)
445 Window control = FindWindow(form, master, null, x, y, false, null, null);
446 bool onBorder = false;
447 Window parent = selected.parent;
448 //if(control && (parent == control || parent == control.parent))
450 int cx = selected.absPosition.x - absPosition.x - clientStart.x;
451 int cy = selected.absPosition.y - absPosition.y - clientStart.y;
452 int cw = selected.size.w;
453 int ch = selected.size.h;
458 if(x >= cx - 7 && x < cx + cw + 6 && y >= cy - 7 && y < cy)
461 if(x >= cx - 7 && x < cx)
467 else if(x >= cx + cw/2 - 3 && x < cx + cw/2 + 3)
473 else if(x >= cx + cw && x < cx + cw + 6)
480 else if(x >= cx - 7 && x < cx + cw + 6 && y >= cy + ch && y < cy + ch + 6)
483 if(x >= cx - 7 && x < cx && y >= cy + ch && y < cy + ch + 6)
489 else if(x >= cx + cw/2 - 3 && x < cx + cw/2 + 3 && y >= cy + ch && y < cy + ch + 6)
495 else if(x >= cx + cw && x < cx + cw + 6 && y >= cy + ch && y < cy + ch + 6)
502 else if(x >= cx - 7 && x < cx && y >= cy - 7 && y < cy + ch + 6)
505 if(y >= cy + ch/2 - 3 && y < cy + ch/2 + 3)
512 else if(x >= cx + cw && x < cx + cw + 6 && y >= cy - 7 && y < cy + ch + 6)
515 if(y >= cy + ch / 2 - 3 && y < cy + ch/2 + 3)
531 Window parent = control.parent;
534 ((control == form) ? (Window)this : form).SetMouseRangeToWindow();
536 ((control == form) ? (Window)this : form).SetMouseRangeToClient();
541 if(selected != control)
542 activeDesigner.SelectObjectFromDesigner(control.object);
545 //activeDesigner.Update(null);
548 xBefore = control.position.x;
549 yBefore = control.position.y;
550 parentBefore = control.parent;
551 this.onBorder = onBorder;
552 wBefore = control.size.w;
553 hBefore = control.size.h;
559 bool OnLeftButtonUp(int x, int y, Modifiers mods)
564 resizeX = resizeY = 0;
569 char * objectClass = activeDesigner.objectClass;
572 Window parent = FindWindow(form, activeDesigner, null, x, y, true, &x, &y);
576 Window control = (Window)eInstance_New(eSystem_FindClass(form._class.module, objectClass));
578 activeDesigner.CodeAddObject(control, &object);
582 x += parent.position.x + parent.clientStart.x;
583 y += parent.position.y + parent.clientStart.y;
584 parent = parent.parent;
587 control.object = object;
589 control.parent = parent;
590 control.master = form;
595 control.position.x = x;
596 control.position.y = y;
597 control.text = object.name;
599 LockControls(control, control);
604 ObjectInfo previous = control.object;
605 while((previous = previous.prev) && ((Window)previous.instance).parent != form);
607 control.parent.children.Move(control, (Window)previous.instance);
610 activeDesigner.SheetAddObject(object);
612 //selected = control;
613 //activeDesigner.Update(null);
621 bool OnLeftDoubleClick(int x, int y, Modifiers mods)
623 Window control = FindWindow(form, activeDesigner, null, x, y, false, &x, &y);
624 if(control && selected == control)
626 activeDesigner.AddDefaultMethod(control, form);
627 return false; // Prevent OnLeftButtonDown to be sent to the activated code editor
632 void ::LockControls(Window window, Window control)
636 if(window == control)
638 ObjectInfo object = window.object;
639 window.OnDestroy = ecere::gui::OnDestroy;
640 window.OnSysKeyDown = ecere::gui::OnSysKey;
641 window.OnSysKeyHit = ecere::gui::OnSysKey;
642 window.OnSysKeyUp = ecere::gui::OnSysKey;
644 if(object != object.oClass)
646 window.OnActivate = Control_OnActivate;
647 window.OnClose = null;
651 window.control = control;
652 for(child = window.firstChild; child; child = child.next)
654 LockControls(child, control);
658 void DrawSelection(Window window, Surface surface)
660 Window result = null, control;
661 for(control = window.lastChild; control; control = control.prev)
663 if(selected == control)
665 Window parent = selected.parent;
668 int w = selected.size.w;
669 int h = selected.size.h;
671 x = selected.absPosition.x - absPosition.x - clientStart.x;
672 y = selected.absPosition.y - absPosition.y - clientStart.y;
674 surface.SetBackground(Color {170, 170, 170});
675 surface.Area(x - 7, y - 7, x + w - 1 + 7, y-1);
676 surface.Area(x - 7, y + h, x + w - 1 + 7, y + h - 1 + 7);
677 surface.Area(x - 7, y - 7, x - 1, y + h - 1 + 7);
678 surface.Area(x + w, y - 7 , x + w - 1 + 7, y + h - 1 + 7);
680 surface.SetBackground(white);
682 surface.Area(x - 6, y - 6, x-1, y-1);
683 surface.Area(x + w/2 - 2, y - 6, x + w/2 + 2, y - 1);
684 surface.Area(x + w + 1, y - 6, x + w-1 + 6, y-1);
686 surface.Area(x - 6, y + h + 1, x-1, y + h - 1 + 6);
687 surface.Area(x + w/2 - 2, y + h + 1, x + w/2 + 2, y + h - 1 + 6);
688 surface.Area(x + w + 1, y + h + 1, x + w-1 + 6, y + h - 1 + 6);
690 surface.Area(x - 6, y + h/2 - 2, x-1, y + h /2 + 2);
691 surface.Area(x + w, y + h/2 - 2, x + w-1 + 6, y + h /2 + 2);
693 surface.SetForeground(black);
695 surface.Rectangle(x - 7, y - 7, x-1, y-1);
696 surface.Rectangle(x + w/2 - 3, y - 7, x + w/2 + 3, y - 1);
697 surface.Rectangle(x + w, y - 7, x + w-1 + 7, y-1);
699 surface.Rectangle(x - 7, y + h, x-1, y + h - 1 + 7);
700 surface.Rectangle(x + w/2 - 3, y + h, x + w/2 + 3, y + h - 1 + 7);
701 surface.Rectangle(x + w, y + h, x + w-1 + 7, y + h - 1 + 7);
703 surface.Rectangle(x - 7, y + h/2 - 3, x-1, y + h /2 + 3);
704 surface.Rectangle(x + w, y + h/2 - 3, x + w-1 + 7, y + h /2 + 3);
706 DrawSelection(control, surface);
711 static bool Control_OnActivate(Window window, bool active, Window previous, bool * goOn, bool direct)
721 static Window GetWindow(Window window, int x, int y, int * rx, int * ry)
723 Window result = null, control;
724 for(control = window.lastChild; control; control = control.prev)
726 int cx = control.position.x;
727 int cy = control.position.y;
728 int cw = control.size.w;
729 int ch = control.size.h;
731 if(x >= cx && x < cx + cw && y >= cy && y < cy + ch)
733 x -= control.position.x + control.clientStart.x;
734 y -= control.position.y + control.clientStart.y;
735 result = GetWindow(control, x, y, rx, ry);
748 static Window FindWindow(Window form, Window window, Window moved, int x, int y, bool asParent, int * dx, int * dy)
750 Window result = null, control;
751 for(control = window.lastChild; control; control = control.prev)
753 if(control != moved && control.control == control && (!asParent || control.name))
755 if(!form || control == form)
757 int cx = control.position.x - (asParent ? 0 : 7);
758 int cy = control.position.y - (asParent ? 0 : 7);
759 int cw = control.size.w + (asParent ? 0 : 14);
760 int ch = control.size.h + (asParent ? 0 : 14);
762 int sx = x - (control.position.x + control.clientStart.x);
763 int sy = y - (control.position.y + control.clientStart.y);
764 if((sx >= 0 && sy >= 0 && sx < control.clientSize.w && sy < control.clientSize.h) ||
765 !(x >= cx && x < cx + cw && y >= cy && y < cy + ch))
766 result = FindWindow(null, control, moved, sx, sy, asParent, dx, dy);
769 else if(x >= cx && x < cx + cw && y >= cy && y < cy + ch)
782 static void OnDestroy(Window window)
784 FormDesigner designer = activeDesigner ? (FormDesigner)activeDesigner.classDesigner : null;
786 if(designer && designer.form)
787 activeDesigner.DeleteObject(window.object);
790 static bool OnSysKey(Window window, Key key, unichar ch)
795 static void DrawGrid(Window window, Surface surface)
798 int w = window.clientSize.w;
799 int h = window.clientSize.h;
800 Color background = window.background;
803 if(background.r > 128 || background.g > 128)
804 surface.SetForeground(black);
806 surface.SetForeground(white);
808 for(y = GridSnap; y < h; y += GridSnap)
809 for(x = GridSnap; x < w; x += GridSnap)
810 surface.PutPixel(x, y);
813 static bool OnKeyDown(Window window, Key key, unichar ch)
815 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
818 if(designer.selected && designer.selected != designer.form)
820 bool confirmation = activeDesigner.ObjectContainsCode(designer.selected.object);
823 confirmation = MessageBox { type = okCancel, master = window.master, text = "Deleting control with code", contents = "Control contains code. Delete anyways?" }.Modal() != ok;
825 // Confirmation if control contains other controls
828 Window child = designer.selected.firstChild;
829 for( ; child; child = child.next)
831 if(child.control == child)
839 confirmation = MessageBox { type = okCancel, master = window.master, text = "Deleting control with children", contents = "Control contains other controls. Delete control and children?"}.Modal() != ok;
844 activeDesigner.ModifyCode();
846 designer.selected.Destroy(0);
847 //activeDesigner.Update(null);
848 designer.Update(null);