5 static void UnusedFunction()
14 a.OnEdit(null,null,0,0,0,0,0);
15 a.OnDisplay(null,0,0,0,0,0,0);
19 extern int __ecereVMethodID_class_OnEdit;
20 extern int __ecereVMethodID_class_OnDisplay;
21 extern int __ecereVMethodID_class_OnGetString;
22 extern int __ecereVMethodID_class_OnFree;
23 extern int __ecereVMethodID_class_OnCompare;
24 extern int __ecereVMethodID_class_OnCopy;
25 extern int __ecereVMethodID_class_OnSaveEdit;
27 //#define SHOW_METHODS
30 // *** THESE METHODS SHOULD BE IMPROVED UPON AND USED TO SET PROPERTIES FROM NOW ON ***
31 // (Other locations where this will be useful: JSON (DataValue version?), CodeEditor, ...)
32 // This takes in a value according to the any_object rules
34 void SetPropValue(Property prop, void * object, any_object value)
36 Class type = prop.dataTypeClass;
38 type = prop.dataTypeClass = eSystem_FindClass(prop._class.module, prop.dataTypeString);
40 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
42 prop.Set(object, value);
44 // TOFIX: How to swiftly handle classes with base data type?
45 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
47 ((void (*)(void *, double))(void *)prop.Set)(object, *(double *)value);
49 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
51 ((void (*)(void *, float))(void *)prop.Set)(object, *(float *)value);
53 else if(type.typeSize == sizeof(int64))// || !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
55 ((void (*)(void *, int64))(void *)prop.Set)(object, *(int64 *)value);
57 else if(type.typeSize == sizeof(int))// || !strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
59 ((void (*)(void *, int))(void *)prop.Set)(object, *(int *)value);
61 else if(type.typeSize == sizeof(short int)) // || !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || !strcmp(type.dataTypeString, "int16"))
63 ((void (*)(void *, short))(void *)prop.Set)(object, *(short *)value);
65 else if(type.typeSize == sizeof(byte))// || !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
67 ((void (*)(void *, byte))(void *)prop.Set)(object, *(byte *)value);
71 ((void (*)(void *, void *))(void *)prop.Set)(object, value);
75 any_object GetPropValue(Property prop, Instance object)
79 Class type = prop.dataTypeClass;
82 type = prop.dataTypeClass = eSystem_FindClass(prop._class.module, prop.dataTypeString);
85 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
87 return ((void*(*)())(void *)prop.Get)(object);
89 // TOFIX: How to swiftly handle classes with base data type?
90 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
92 double d = ((double(*)())(void *)prop.Get)(object);
95 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
97 float f =((float(*)())(void *)prop.Get)(object);
100 else if(type.typeSize == sizeof(int64))// || !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
102 return ((int64(*)())(void *)prop.Get)(object);
104 else if(type.typeSize == sizeof(int))// || !strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
106 return ((int(*)())(void *)prop.Get)(object);
108 else if(type.typeSize == sizeof(short int)) // || !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || !strcmp(type.dataTypeString, "int16"))
110 return ((short(*)())(void *)prop.Get)(object);
112 else if(type.typeSize == sizeof(byte))// || !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
114 return ((byte(*)())(void *)prop.Get)(object);
118 return prop.Get(object);
125 void CopyProperty(Property prop, Instance dest, Instance src)
127 Class type = prop.dataTypeClass;
129 type = prop.dataTypeClass = eSystem_FindClass(prop._class.module, prop.dataTypeString);
131 if(type.type == structClass)
133 void * propData = new0 byte[type.structSize];
134 prop.Get(src, propData);
135 prop.Set(dest, propData);
138 else if(type.type == normalClass || type.type == noHeadClass)
140 // TOCHECK: Why was there a return here?
141 /*return */prop.Set(dest, ((void*(*)())(void *)prop.Get)(src));
143 // TOFIX: How to swiftly handle classes with base data type?
144 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
146 ((void (*)(void *, double))(void *)prop.Set)(dest, ((double(*)())(void *)prop.Get)(src));
148 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
150 ((void (*)(void *, float))(void *)prop.Set)(dest, ((float(*)())(void *)prop.Get)(src));
152 else if(type.typeSize == sizeof(int64))// || !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
154 ((void (*)(void *, int64))(void *)prop.Set)(dest, ((int64(*)())(void *)prop.Get)(src));
156 else if(type.typeSize == sizeof(int))// || !strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
158 ((void (*)(void *, int))(void *)prop.Set)(dest, ((int(*)())(void *)prop.Get)(src));
160 else if(type.typeSize == sizeof(short int)) // || !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || !strcmp(type.dataTypeString, "int16"))
162 ((void (*)(void *, short))(void *)prop.Set)(dest, ((short(*)())(void *)prop.Get)(src));
164 else if(type.typeSize == sizeof(byte))// || !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
166 ((void (*)(void *, byte))(void *)prop.Set)(dest, ((byte(*)())(void *)prop.Get)(src));
170 prop.Set(dest, prop.Get(src));
174 void GetProperty(Property prop, Instance object, DataValue value)
178 Class type = prop.dataTypeClass;
181 type = prop.dataTypeClass = eSystem_FindClass(prop._class.module, prop.dataTypeString);
183 if(prop._class.module.application == __thisModule &&
184 prop.dataTypeClass.module.application == ((Designer)GetActiveDesigner()).codeEditor.privateModule)
189 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
191 value.p = ((void*(*)())(void *)prop.Get)(object);
193 // TOFIX: How to swiftly handle classes with base data type?
194 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
196 value.d = ((double(*)())(void *)prop.Get)(object);
198 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
200 value.f = ((float(*)())(void *)prop.Get)(object);
202 else if(type.typeSize == sizeof(int64))// || !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
204 value.i64 = ((int64(*)())(void *)prop.Get)(object);
206 else if(type.typeSize == sizeof(int))// || !strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
208 value.i = ((int(*)())(void *)prop.Get)(object);
210 else if(type.typeSize == sizeof(short int)) // || !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || !strcmp(type.dataTypeString, "int16"))
212 value.s = ((short(*)())(void *)prop.Get)(object);
214 else if(type.typeSize == sizeof(byte))// || !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
216 value.uc = ((byte(*)())(void *)prop.Get)(object);
220 value.i = prop.Get(object);
227 void SetProperty(Property prop, Instance object, DataValue value)
231 Class type = prop.dataTypeClass;
233 type = prop.dataTypeClass = eSystem_FindClass(prop._class.module, prop.dataTypeString);
235 if(type.type == normalClass || type.type == noHeadClass || type.type == structClass)
237 prop.Set(object, value);
239 // TOFIX: How to swiftly handle classes with base data type?
240 else if(type == class(double) || !strcmp(type.dataTypeString, "double"))
242 ((void (*)(void *, double))(void *)prop.Set)(object, value.d);
244 else if(type == class(float) || !strcmp(type.dataTypeString, "float"))
246 ((void (*)(void *, float))(void *)prop.Set)(object, value.f);
248 else if(type.typeSize == sizeof(int64))// || !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64"))
250 ((void (*)(void *, int64))(void *)prop.Set)(object, value.i64);
252 else if(type.typeSize == sizeof(int))// || !strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || !strcmp(type.dataTypeString, "uint"))
254 ((void (*)(void *, int))(void *)prop.Set)(object, value.i);
256 else if(type.typeSize == sizeof(short int)) // || !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") || !strcmp(type.dataTypeString, "int16"))
258 ((void (*)(void *, short))(void *)prop.Set)(object, value.s);
260 else if(type.typeSize == sizeof(byte))// || !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
262 ((void (*)(void *, byte))(void *)prop.Set)(object, value.uc);
266 ((void (*)(void *, int))(void *)prop.Set)(object, value.i);
274 borderStyle = sizable;
278 anchor = { left = 0, top = 0, bottom = 0 };
279 background = activeBorder;
283 dropBox.AddField(dropField);
284 properties.AddField(propertyName);
285 properties.AddField(propertyValue);
286 methods.AddField(methodName);
291 categories.Free(null);
297 anchor = { left = 0, top = 0, right = 0 };
299 bool NotifySelect(DropBox control, DataRow row, Modifiers keyFlags)
301 ObjectInfo selected = (ObjectInfo)(row ? row.tag : null);
302 ToolBox toolBox = ((IDE)parent).toolBox;
304 if(codeEditor && selected)
305 codeEditor.SelectObject(selected);
307 // TODO: Get containing class of object
308 toolBox.selectedClass = selected ? selected.oClass : null;
310 object = selected ? selected.instance : null;
313 ListProperties(true);
317 row = methods.currentRow;
319 strcpy(selectedMethod, ((CodeObject)row.GetData(methodName)).name);
323 if(selected && selected.instance && codeEditor)
327 int rowHeight = methods.rowHeight;
329 propertyValue.userData = (void *)selected.instance;
331 // Fill up the methods
335 for(_class = selected.instance._class; _class && _class.type != systemClass; _class = _class.base)
338 for(id = _class.base ? _class.base.vTblSize : 0; id<_class.vTblSize; id++)
341 for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
343 if(method.type == virtualMethod && method.vid == id)
346 method.dataType = ProcessTypeString(method.dataTypeString, false);
348 type = method.dataType.thisClass ? typeEvent : typeMethod;
350 DataRow row = methods.AddRow();
351 CodeObject codeObject
353 eventsUp = (selected.oClass == selected) ? false : true;
357 overriden = codeEditor.FindMethod(method.name, &codeObject.function, null);
359 if(!codeObject.overriden || codeObject.overriden == 2)
360 codeEditor.FindCompatibleMethods(method, codeObject.compatible);
362 row.SetData(methodName, codeObject);
364 if(!strcmp(method.name, selectedMethod))
365 methods.currentRow = row;
373 methods.Sort(methodName, 1);
376 for(row = methods.firstRow; row; row = row.next)
378 CodeObject codeObject = row.GetData(methodName);
379 CreateButtons(codeObject, row.index * rowHeight, rowHeight, row);
386 DataField dropField { dataType = class(CodeObject) };
390 this, inactive = true, text = $"Properties", bevelOver = true, isRadio = true;
392 anchor = { left = 0, bottom = 3, right = 0.5 };
395 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
397 text = $"Properties";
398 button.font = { $"Tahoma", 8.25f, bold = true };
401 methods.visible = false;
402 methBtn.Activate(); // Ensure proper cycling (until tab order?)
403 properties.visible = true;
405 alphabetical.disabled = false;
406 categorized.disabled = false;
408 properties.Activate();
410 // ((IDE)master).SheetSelected(Properties);
417 this, inactive = true, bevelOver = true;
422 anchor = { bottom = 3, left = 0.5, right = 0 };
424 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
427 button.font = { $"Tahoma", 8.25f, bold = true };
430 properties.visible = false;
431 methBtn.Activate(); // Ensure proper cycling (until tab order?)
432 methods.visible = true;
434 alphabetical.disabled = true;
435 categorized.disabled = true;
439 // ((IDE)master).SheetSelected(Methods);
446 MenuPlacement editMenu { menu, text = $"Edit" };
447 Menu viewMenu { menu, text = $"View" };
452 this, anchor = { left = 0, right = 0, top = 50, bottom = 25 };
453 hasVertScroll = true, alwaysEdit = true, collapseControl = true, resizable = true;
454 background = viewsBackground;
455 foreground = viewsText;
457 bool NotifySelect(ListBox control, DataRow row, Modifiers keyFlags)
462 strcpy(selectedProp, (char *)row.GetData(propertyName));
463 selectedScroll = properties.scroll.y;
464 selectedScroll -= row.index * properties.rowHeight;
470 prop = ((PropertyInfo)row.GetData(propertyValue)).prop;
479 DataField propertyName { dataType = class(char *), width = 130 };
480 DataField propertyValue { dataType = class(PropertyInfo), width = 0, editable = true };
485 this, anchor = { left = 0, right = 0, top = 50, bottom = 25 };
486 hasVertScroll = true;
487 background = viewsBackground;
488 foreground = viewsText;
489 // alwaysEdit = true;
492 bool NotifyDoubleClick(ListBox control, int x, int y, Modifiers mods)
494 CodeObject object = control.GetData(methodName);
496 codeEditor.AddMethod(object.method);
500 bool NotifyRightClick(ListBox control, int x, int y, Modifiers mods)
502 CodeObject object = control.GetData(methodName);
506 if(object.overriden == 0)
508 MenuItem { menu, $"Override", o, enter, bold = true, NotifySelect = OverrideMethodSelected };
509 if(object.compatible.count)
511 Menu attachMenu { menu, $"Attach", a };
513 for(compatible = object.compatible.first; compatible; compatible = compatible.next)
515 ClassFunction function = compatible.data;
516 MenuItem { attachMenu, function.declarator.symbol.string, id = (int)function, NotifySelect = AttachMethodSelected };
520 else if(object.overriden == 1)
522 MenuItem { menu, $"Go to", g, enter, bold = true, NotifySelect = GotoMethodSelected };
523 MenuItem { menu, $"Detach", d, d, NotifySelect = DetachMethodSelected };
524 MenuItem { menu, $"Delete", del, del, NotifySelect = DeleteMethodSelected };
526 else if(object.overriden == 2)
528 MenuItem { menu, $"Go to", g, enter, bold = true, NotifySelect = GotoMethodSelected };
529 MenuItem { menu, $"Detach", d, d, NotifySelect = DetachMethodSelected };
530 if(object.compatible.count > 1)
532 Menu attachMenu { menu, $"Reattach", r };
534 for(compatible = object.compatible.first; compatible; compatible = compatible.next)
536 ClassFunction function = compatible.data;
537 if(function != object.function)
539 MenuItem { attachMenu, function.declarator.symbol.string, id = (int)function, NotifySelect = ReattachMethodSelected };
545 attachMethod = object.method;
546 popupMenu = PopupMenu { menu = menu, master = this, position =
548 x + control.absPosition.x - app.desktop.absPosition.x,
549 y + control.absPosition.y - app.desktop.absPosition.y
552 // popupMenu.Capture();
556 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
560 CodeObject object = row.GetData(methodName);
561 switch((SmartKey)key)
564 if(!object.overriden)
565 listBox.NotifyDoubleClick(this, listBox, 0,0, 0);
567 codeEditor.GoToMethod(object.method.name);
571 object.deleteBtn.NotifyClicked(this, object.deleteBtn, 0,0,0);
572 else if(object.detachBtn)
573 object.detachBtn.NotifyClicked(this, object.detachBtn, 0,0,0);
577 object.attachBtn.NotifyPushed(this, object.attachBtn, 0,0,0);
581 object.detachBtn.NotifyClicked(this, object.detachBtn, 0,0,0);
589 DataField methodName { dataType = class(CodeObject) };
592 methBtn.font = { $"Tahoma", 8.25, bold = true };
593 methBtn.checked = true;
594 properties.visible = false;
597 propBtn.font = { $"Tahoma", 8.25f, bold = true };
598 propBtn.checked = true;
599 methods.visible = false;
600 text = $"Properties";
605 this, bevelOver = true, inactive = true, position = { 25, 25 }, size = { 24, 24 };
606 bitmap = { "<:ecere>elements/orderAscending.png" };
609 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
611 if(!alphabetical.checked)
613 alphabetical.checked = true;
614 categorized.checked = false;
616 ListProperties(true);
624 this, bevelOver = true, checked = true, inactive = true, position = { 0, 25 }, size = { 24, 24 };
625 bitmap = { "<:ecere>elements/orderCategorized.png" };
628 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
630 if(!categorized.checked)
632 categorized.checked = true;
633 alphabetical.checked = false;
635 ListProperties(true);
641 property CodeEditor codeEditor
645 if(codeEditor != value)
650 dropField.userData = codeEditor;
651 methodName.userData = codeEditor;
654 codeEditor.EnumerateObjects(this);
663 property SheetType sheetSelected
667 if(methBtn.checked != (value == SheetType::methods))
672 return methBtn.checked ? methods : properties;
676 bool OnClose(bool parentClosing)
686 bool OnKeyDown(Key key, unichar ch)
692 else if(key == escape)
694 Window activeClient = ide.activeClient;
696 activeClient.Activate();
698 ide.RepositionWindows(true);
703 bool OnKeyHit(Key key, unichar ch)
705 return properties.OnKeyHit(key, ch);
708 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
710 if(active && codeEditor)
711 codeEditor.EnsureUpToDate();
715 void ListProperties(bool clear)
717 DataRow row = dropBox.currentRow;
718 ObjectInfo selected = row ? (ObjectInfo)row.tag : null;
721 bool categorized = this.categorized.checked;
722 bool currentRow = false;
723 char selectedProp[1024];
728 DataRow row = properties.currentRow;
731 DataRow propRow = row;
733 while(propRow && propRow.parent && !propRow.parent.isHeader)
734 propRow = row.parent;
736 propName = propRow.GetData(propertyName);
737 strcpy(this.selectedProp, propName);
738 selectedScroll = properties.scroll.y;
739 selectedScroll -= propRow.index * properties.rowHeight;
741 currentRow = this.selectedProp[0] ? true : false;
743 for(cat = categories.first; cat; cat = cat.next)
745 cat.collapsed = cat.row.collapsed;
749 // Preserve selected property (PropertySheetSelect will null it)
750 strcpy(selectedProp, this.selectedProp);
752 strcpy(this.selectedProp, selectedProp);
754 if(selected && selected.instance && codeEditor)
756 Instance test = eInstance_New(selected.instance._class);
760 // Put it in the same desktop window...
761 if(selected.classDefinition)
762 codeEditor.designer.PrepareTestObject(test);
764 // Fill up the properties
765 while(_class != selected.instance._class)
767 BitMember bitMember = null;
768 Class lastClass = _class;
771 for(_class = selected.instance._class; _class.base != lastClass && _class.base.type != systemClass && _class.inheritanceAccess != privateAccess; _class = _class.base);
773 for(propIt = _class.membersAndProperties.first; propIt; propIt = propIt.next)
775 if(propIt.isProperty)
777 Property prop = eClass_FindProperty(selected.instance._class, propIt.name, GetPrivateModule());
779 if(prop && prop.Set && prop.Get && prop.compiled)
781 bool disabled = Code_IsPropertyDisabled(selected, prop.name);
783 Class dataType = prop.dataTypeClass;
785 dataType = prop.dataTypeClass = eSystem_FindClass(codeEditor.privateModule, prop.dataTypeString);
787 if(!strcmp(_class.name, "DesignerBase"))
789 bold = !disabled && Code_IsPropertyModified(test, selected, prop);
794 PropertyInfo info { prop, disabled, bold ? codeEditor.boldFont : codeEditor.normalFont };
795 char * name = prop.category ? prop.category : $"Misc";
796 Category category = categories.FindName(name, false);
798 // Hide properties like this for now..
799 if(name && !strcmp(name, "Private"))
807 category = Category { name = name };
808 categories.AddName(category);
810 if(!category.row && categorized)
812 PropertyInfo catInfo { null, false, null, name };
813 category.row = properties.AddRow();
814 category.row.SetData(propertyName, name );
815 category.row.SetData(propertyValue, catInfo);
816 category.row.isHeader = true;
817 category.row.collapsed = category.collapsed;
822 row = categorized ? category.row.FindRow((int)prop) : properties.FindRow((int)prop);
824 row = categorized ? category.row.AddRow() : properties.AddRow();
828 row = categorized ? category.row.FindRow((int)prop) : properties.FindRow((int)prop);
830 row.SetData(propertyName, prop.name);
831 row.SetData(propertyValue, info);
833 if(clear && !strcmp(prop.name, this.selectedProp))
834 properties.currentRow = row;
836 if(!dataType.noExpansion && (dataType.type == structClass || dataType.type == normalClass || dataType.type == noHeadClass || dataType.type == bitClass))
841 row.collapsed = true;
843 for(member = dataType.membersAndProperties.first; member; member = member.next)
845 if(member.isProperty)
847 Property subProp = (Property)member;
848 if(!subProp.conversion && subProp.Get && subProp.Set)
851 PropertyInfo info { prop, disabled, bold ? codeEditor.boldFont : codeEditor.normalFont, null, null, subProp };
855 subRow = row.AddRow();
856 subRow.tag = (int)subProp;
859 subRow = row.FindRow((int)subProp);
861 subRow.SetData(propertyName, subProp.name);
862 subRow.SetData(propertyValue, info);
868 PropertyInfo info { prop, disabled, bold ? codeEditor.boldFont : codeEditor.normalFont, null, member, null };
871 subRow = row.AddRow();
872 subRow.tag = (int)member;
875 subRow = row.FindRow((int)member);
877 subRow.SetData(propertyName, member.name);
878 subRow.SetData(propertyValue, info);
882 DataMember subMember;
883 for(subMember = member.members.first; subMember; subMember = subMember.next)
886 PropertyInfo info { prop, disabled, bold ? codeEditor.boldFont : codeEditor.normalFont, null, subMember, null, member.offset };
889 subRow = row.AddRow();
890 subRow.tag = (int)subMember;
893 subRow = row.FindRow((int)subMember);
895 subRow.SetData(propertyName, subMember.name);
896 subRow.SetData(propertyValue, info);
907 // Sort alphabetically for now...
910 // properties.Sort(null, 1);
911 properties.Sort(propertyValue, 1);
912 if(!properties.currentRow)
916 for(_class = selected.instance._class; _class; _class = _class.base)
919 for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
921 if(prop.isProperty && prop.Set && prop.Get && prop.compiled)
923 if(_class.defaultProperty && !strcmp(prop.name, _class.defaultProperty))
926 char * name = prop.category ? prop.category : $"Misc";
927 Category category = categories.FindName(name, false);
928 row = category ? (categorized ? category.row.FindRow((int)prop) : properties.FindRow((int)prop)) : null;
929 properties.currentRow = row;
938 properties.currentRow = properties.firstRow;
943 DataRow row = properties.currentRow;
944 properties.scroll.y = selectedScroll + row.index * properties.rowHeight;
950 void AddObject(ObjectInfo object, char * name, CodeObjectType type, bool select)
952 DataRow after = null;
954 CodeObject codeObject;
955 char * bitmap = null;
956 bool foundClass = false;
958 for(row = dropBox.firstRow; row; row = row.next)
960 CodeObject codeObject = row.GetData(null);
961 if(codeObject.object.oClass == object.oClass)
968 row = (DataRow)dropBox.AddRowAfter(after);
970 row.tag = (int)object;
977 indent = (type == typeClass) ? 0 : 1;
980 if(type != typeClass)
981 bitmap = (char *)eClass_GetProperty(object.instance._class, "icon");
984 codeObject.bitmap = { bitmap };
985 AddResource(codeObject.bitmap);
988 row.SetData(null, codeObject);
992 this.object = object ? object.instance : null;
993 propertyValue.userData = object ? (void *)object.instance : null;
994 dropBox.SelectRow(row);
998 void DeleteObject(ObjectInfo object)
1000 DataRow row = dropBox.FindRow((int)object);
1003 CodeObject codeObject = row.GetData(null);
1005 if(codeObject.bitmap)
1006 RemoveResource(codeObject.bitmap);
1007 dropBox.DeleteRow(row);
1011 void SelectObject(ObjectInfo object)
1015 DataRow row = dropBox.FindRow((int)object);
1016 this.object = object ? object.instance : null;
1017 propertyValue.userData = object ? (void *)object.instance : null;
1018 dropBox.SelectRow(row);
1022 void RenameObject(ObjectInfo object, char * name)
1024 DataRow row = dropBox.FindRow((int)object);
1025 CodeObject codeObject = row.GetData(null);
1026 // Isn't this useless? Shouldn't it be after?
1027 codeObject.name = name;
1028 // row.SetData(null, codeObject); // Is this necessary?
1031 void DataBox::EditSetData(any_object setValue, bool closingDropDown)
1033 ((Sheet)master.master).SetData(setValue, this);
1036 void SetData(any_object setValue, DataBox dataBox)
1038 //PropertyInfo propertyPtr = row.GetData(null);
1039 PropertyInfo propertyPtr = properties.GetData(null);
1040 Property prop = propertyPtr ? propertyPtr.prop : null;
1041 Instance object = this.object;
1044 Class dataType = prop.dataTypeClass;
1046 dataType = prop.dataTypeClass = eSystem_FindClass(codeEditor.privateModule, prop.dataTypeString);
1047 if(propertyPtr.subMember)
1049 DataMember member = propertyPtr.subMember;
1050 Class subDataType = member.dataTypeClass;
1051 if(!member.dataTypeClass)
1052 subDataType = member.dataTypeClass = eSystem_FindClass(codeEditor.privateModule, member.dataTypeString);
1056 if(!subDataType.dataType)
1057 subDataType.dataType = ProcessTypeString(subDataType.dataTypeString, false);
1059 if(dataType.type == structClass)
1061 data = new0 byte[dataType.structSize];
1062 prop.Get(object, data);
1063 // CopyBytes((byte *)data + member.offset + propertyPtr.extraOffset, &setValue, subDataType.size);
1064 CopyBytes((byte *)data + member.offset + propertyPtr.extraOffset, (void *)setValue, subDataType.dataType.size);
1065 prop.Set(object, data);
1067 else if(dataType.type == normalClass || dataType.type == noHeadClass)
1072 if(dataType.type == bitClass)
1074 BitMember bitMember = (BitMember) member;
1077 DataValue value = { 0 };
1078 value.ui = prop.Get(object);
1079 value.ui &= ~ (uint)bitMember.mask;
1080 value.ui |= *(uint32 *)setValue << bitMember.pos;
1081 prop.Set(object, value.ui);
1086 data = dataType.typeSize ? new0 byte[dataType.typeSize] : null;
1087 prop.Get(object, data);
1088 // CopyBytes((byte *)data + member.offset + propertyPtr.extraOffset, &setValue, subDataType.typeSize);
1089 CopyBytes((byte *)data + member.offset + propertyPtr.extraOffset, (void *)setValue, subDataType.dataType.size);
1090 // TODO: Support non 32 bit datatypes here
1091 prop.Set(object, data);
1095 if(data) dataType._vTbl[__ecereVMethodID_class_OnFree](dataType,&data);
1099 else if(propertyPtr.subProperty)
1101 Property subProperty = propertyPtr.subProperty;
1102 Class subDataType = subProperty.dataTypeClass;
1104 subDataType = subProperty.dataTypeClass = eSystem_FindClass(codeEditor.privateModule, subProperty.dataTypeString);
1109 if(dataType.type == structClass)
1111 data = new0 byte[dataType.structSize];
1112 prop.Get(object, data);
1113 subProperty.Set(data, *(uint32 *)setValue);
1114 prop.Set(object, data);
1116 else if(dataType.type == normalClass || dataType.type == noHeadClass)
1118 Instance current = (Instance)prop.Get(object);
1119 Instance propObject = eInstance_New(dataType);
1120 CopyInstanceData(dataType, propObject, current);
1121 subProperty.Set(propObject, (uint32)setValue);
1122 prop.Set(object, propObject);
1126 data = dataType.typeSize ? new0 byte[dataType.typeSize] : null;
1127 prop.Get(object, data);
1128 subProperty.Set(data, (uint32)setValue);
1129 // TODO: Support not 32 bit data types here
1130 prop.Set(object, data);
1133 if(data) dataType._vTbl[__ecereVMethodID_class_OnFree](dataType,&data);
1139 SetPropValue(prop, object, (uint32)setValue);
1141 Code_FixProperty(propertyPtr.prop, object);
1143 properties.Update(null);
1144 dropBox.Update(null);
1145 codeEditor.designer.Update(null);
1146 codeEditor.Update(null); // patch for redraw bug if on top
1148 ListProperties(false);
1150 dataBox.editor.font = { propertyPtr.font.faceName, propertyPtr.font.size, propertyPtr.font.bold };
1151 codeEditor.ModifyCode();
1155 bool SaveEdit(PropertyInfo propertyPtr, Instance object)
1157 codeEditor.designer.Update(null);
1158 codeEditor.Update(null); // patch for redraw bug if on top
1159 properties.Update(null);
1160 dropBox.Update(null);
1162 Code_FixProperty(propertyPtr.prop, object);
1163 ListProperties(false);
1165 codeEditor.ModifyCode();
1171 if(!propBtn.checked)
1173 propBtn.checked = true;
1174 propBtn.NotifyClicked(this, propBtn, 0,0,0);
1178 methBtn.checked = true;
1179 methBtn.NotifyClicked(this, methBtn, 0,0,0);
1183 bool AttachMethodSelected(MenuItem selection, Modifiers mods)
1185 ClassFunction function = (ClassFunction)selection.id;
1186 codeEditor.AttachMethod(attachMethod, function);
1190 bool ReattachMethodSelected(MenuItem selection, Modifiers mods)
1192 ClassFunction function = (ClassFunction)selection.id;
1193 CodeObject object = methods.GetData(methodName);
1194 codeEditor.ReAttachMethod(attachMethod, function);
1198 bool OverrideMethodSelected(MenuItem selection, Modifiers mods)
1200 ClassFunction function = (ClassFunction)selection.id;
1201 CodeObject object = methods.GetData(methodName);
1203 codeEditor.AddMethod(object.method);
1207 bool GotoMethodSelected(MenuItem selection, Modifiers mods)
1209 ClassFunction function = (ClassFunction)selection.id;
1210 CodeObject object = methods.GetData(methodName);
1212 codeEditor.GoToMethod(object.method.name);
1216 bool DetachMethodSelected(MenuItem selection, Modifiers mods)
1218 ClassFunction function = (ClassFunction)selection.id;
1219 CodeObject object = methods.GetData(methodName);
1221 codeEditor.DetachMethod(object.method, object.function, object.overriden);
1225 bool DeleteMethodSelected(MenuItem selection, Modifiers mods)
1227 ClassFunction function = (ClassFunction)selection.id;
1228 CodeObject object = methods.GetData(methodName);
1230 object.deleteBtn.NotifyClicked(this, object.deleteBtn, 0,0,0);
1234 bool AddMethodClicked(Button button, int x, int y, Modifiers mods)
1236 DataRow row = (DataRow)button.id;
1237 CodeObject object = row.GetData(methodName);
1238 codeEditor.AddMethod(object.method);
1242 void CreateButtons(CodeObject codeObject, int y, int h, DataRow row)
1244 BitmapResource bitmap;
1246 if(codeObject.overriden)
1248 if(codeObject.overriden == 1)
1250 codeObject.deleteBtn = Button
1252 methods, master = this,
1254 bitmap = { ":actions/delete.png", alphaBlend = true },
1255 anchor = { right = 16, top = y },
1259 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1261 CodeObject codeObject = ((DataRow)button.id).GetData(null);
1262 bool confirmation = !Code_IsFunctionEmpty(codeObject.function, codeObject.method, codeEditor.selected);
1267 sprintf(title, $"Delete %s", codeObject.name);
1270 master = parent, type = okCancel, text = title,
1271 contents = $"Method still contains code. Are you sure you want to delete it?"
1273 confirmation = false;
1276 if(!confirmation && codeObject.function.attached.count)
1279 sprintf(title, $"Delete %s", codeObject.name);
1280 confirmation = true;
1283 master = parent, type = okCancel, text = title,
1284 contents = $"Other methods are still attached to this method. Are you sure you want to delete it?"
1286 confirmation = false;
1291 codeEditor.DeleteMethod(codeObject.function);
1296 incref codeObject.deleteBtn;
1297 codeObject.deleteBtn.Create();
1300 if(codeObject.overriden == 2 || !codeObject.function.attached.count)
1302 codeObject.detachBtn = Button
1305 master = methods.master,
1307 bitmap = { ":actions/detach.png" },
1308 anchor = { right = 0, top = y },
1312 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1314 DataRow row = (DataRow)button.id;
1315 CodeObject object = row.GetData(methodName);
1317 codeEditor.DetachMethod(object.method, object.function, object.overriden);
1321 incref codeObject.detachBtn;
1322 codeObject.detachBtn.Create();
1327 if(codeObject.compatible.count)
1329 codeObject.attachBtn = Button
1331 parent = methods, master = methods.master,
1333 bitmap = { ":actions/attach.png" },
1334 anchor = { right = 0, top = y },
1338 bool NotifyPushed(Button button, int x, int y, Modifiers mods)
1341 DataRow row = (DataRow)button.id;
1342 CodeObject object = row.GetData(methodName);
1344 PopupMenu popupMenu;
1348 for(compatible = object.compatible.first; compatible; compatible = compatible.next)
1350 ClassFunction function = compatible.data;
1351 MenuItem { menu, function.declarator.symbol.string, id = (int)function, NotifySelect = AttachMethodSelected };
1353 attachMethod = object.method;
1355 popupMenu = PopupMenu
1357 master = this, menu = menu,
1360 button.absPosition.x - app.desktop.position.x,
1361 button.absPosition.y - app.desktop.position.y + button.size.h
1365 button.ReleaseCapture();
1366 popupMenu.Capture();
1370 incref codeObject.attachBtn;
1371 codeObject.attachBtn.Create();
1376 Method attachMethod;
1377 char selectedMethod[1024];
1378 CodeEditor codeEditor;
1380 char selectedProp[1024];
1384 static int String_OnCompare(char ** string1, char ** string2)
1387 if(*string1 && *string2)
1388 result = strcmpi(*string1, *string2);
1389 else if(!*string1 && *string2)
1391 else if(*string1 && !*string2)
1396 static void CopyInstanceData(Class dataType, Instance propObject, Instance current)
1399 for(_class = dataType; _class && _class.type != systemClass; _class = _class.base)
1402 for(member = _class.membersAndProperties.first; member; member = member.next)
1404 Class memberType = member.dataTypeClass;
1406 memberType = member.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, member.dataTypeString);
1407 if(member.isProperty)
1409 Property subProp = (Property) member;
1410 if(subProp.Get && subProp.Set)
1411 CopyProperty(subProp, propObject, current);
1416 // TOCHECK: I have serious doubts this works in many cases.
1417 memberType._vTbl[__ecereVMethodID_class_OnCopy](memberType, (byte *)propObject + member.offset, (byte *)current + member.offset);
1418 else if(member.memberOffset)
1419 memcpy((byte *)propObject + member.offset, (byte *)current + member.offset, member.memberOffset);
1425 class PropertyInfo : struct
1431 char * categoryName;
1432 DataMember subMember;
1433 Property subProperty;
1436 void OnDisplay(Surface surface, int x, int y, int width, Instance object, Alignment alignment, DataDisplayFlags displayFlags)
1438 Property prop = this.prop;
1440 surface.TextFont(font.font);
1443 surface.SetBackground(Color { 170, 170, 170 });
1444 surface.Area(0,0, x+width-1, y+100);
1446 else if(prop && prop.dataTypeString)
1448 Class dataType = prop.dataTypeClass;
1449 Module module = ((Designer)GetActiveDesigner()).codeEditor.privateModule;
1451 dataType = prop.dataTypeClass = eSystem_FindClass(module, prop.dataTypeString);
1453 if(dataType && prop.Get)
1455 void * dataPtr, * data = null, * subData = null;
1456 DataValue valueData, valueSubData;
1460 if(dataType.type == structClass)
1462 data = new0 byte[dataType.structSize];
1463 prop.Get(object, data);
1468 GetProperty(prop, object, &valueData);
1470 if(dataType.type == normalClass)
1471 dataPtr = valueData.p;
1473 dataPtr = &valueData;
1479 DataMember member = this.subMember;
1480 Class subDataType = member.dataTypeClass;
1482 subDataType = member.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, member.dataTypeString);
1485 if(dataType.type == bitClass)
1487 BitMember bitMember = (BitMember)member;
1488 bitValue = (valueData.i & bitMember.mask) >> bitMember.pos;
1489 dataPtr = &bitValue;
1492 dataPtr = (byte *)dataPtr + member.offset + this.extraOffset;
1494 dataType = subDataType;
1496 else if(this.subProperty)
1498 Property subProperty = this.subProperty;
1499 Class subDataType = subProperty.dataTypeClass;
1501 subDataType = subProperty.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, subProperty.dataTypeString);
1502 if(!subProperty.Get) subDataType = null;
1505 if(subDataType.type == structClass)
1507 subData = new0 byte[subDataType.structSize];
1508 subProperty.Get(dataPtr, subData);
1513 GetProperty(subProperty, dataPtr, &valueSubData);
1514 if(subDataType.type == normalClass)
1515 dataPtr = valueSubData.p;
1517 dataPtr = &valueSubData;
1520 dataType = subDataType;
1524 dataType._vTbl[__ecereVMethodID_class_OnDisplay](dataType, dataPtr, surface, x, y, width, null, alignment, displayFlags);
1532 Window OnEdit(DataBox dataBox, Window obsolete, int x, int y, int w, int h, void * unused)
1534 EditBox editData = null;
1535 Property prop = this.prop;
1537 dataBox.SetData = Sheet::EditSetData;
1538 if(prop && prop.dataTypeString && !this.disabled)
1540 Sheet propertyWindow = (Sheet)dataBox.master.master;
1541 Instance object = propertyWindow.object;
1542 Class dataType = prop.dataTypeClass;
1544 dataType = prop.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, prop.dataTypeString);
1546 if(dataType && prop.Get)
1548 void * dataPtr, * data = null, * subData = null;
1549 DataValue valueData, valueSubData;
1553 if(dataType.type == structClass)
1555 data = new0 byte[dataType.structSize];
1556 prop.Get(object, data);
1561 GetProperty(prop, object, &valueData);
1562 if(dataType.type == normalClass)
1563 dataPtr = valueData.p;
1565 dataPtr = &valueData;
1571 DataMember member = this.subMember;
1572 Class subDataType = member.dataTypeClass;
1574 subDataType = member.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, member.dataTypeString);
1577 if(dataType.type == bitClass)
1579 BitMember bitMember = (BitMember)member;
1580 bitValue = (valueData.i & bitMember.mask) >> bitMember.pos;
1581 dataPtr = &bitValue;
1584 dataPtr = (byte *)dataPtr + member.offset + this.extraOffset;
1586 dataType = subDataType;
1588 else if(this.subProperty)
1590 Property subProperty = this.subProperty;
1591 Class subDataType = subProperty.dataTypeClass;
1593 subDataType = subProperty.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, subProperty.dataTypeString);
1594 if(!subProperty.Get) subDataType = null;
1597 if(subDataType.type == structClass)
1599 subData = new0 byte[subDataType.structSize];
1600 subProperty.Get(dataPtr, subData);
1605 GetProperty(subProperty, dataPtr, &valueSubData);
1606 if(subDataType.type == normalClass)
1607 dataPtr = valueSubData.p;
1609 dataPtr = &valueSubData;
1612 dataType = subDataType;
1616 editData = (void *)dataType._vTbl[__ecereVMethodID_class_OnEdit](dataType, dataPtr, dataBox, obsolete, x, y, w, h, object /*unused*/);
1621 editData.font = { font.faceName, font.size, font.bold };
1627 int OnCompare(PropertyInfo data2)
1629 char * category1 = prop ? prop.category : categoryName;
1630 char * category2 = data2.prop ? data2.prop.category : data2.categoryName;
1633 if(!category1) category1 = $"Misc";
1634 if(!category2) category2 = $"Misc";
1638 // result = String::OnCompare((String)category1, (String)category2);
1639 result = String_OnCompare(&category1, &category2);
1644 if(subMember && !data2.subMember)
1648 else if(!subMember && data2.subMember)
1652 else if(subMember && data2.subMember)
1654 if(subMember.id < data2.subMember.id)
1656 else if(subMember.id > data2.subMember.id)
1661 else if(subProperty && !data2.subProperty)
1665 else if(!subProperty && data2.subProperty)
1669 else if(subProperty && data2.subProperty)
1671 if(subProperty.id < data2.subProperty.id)
1673 else if(subProperty.id > data2.subProperty.id)
1678 else if(prop && !data2.prop)
1680 else if(!prop && data2.prop)
1683 // result = ((String)prop.name).OnCompare(data2.prop.name);
1684 // result = String::OnCompare((String)prop.name, (String)data2.prop.name);
1685 result = String_OnCompare(&prop.name, &data2.prop.name);
1690 bool OnSaveEdit(Window editControl, void * unusedData)
1692 Property prop = this.prop;
1695 Sheet sheet = (Sheet)editControl.master.master.master;
1696 Instance object = sheet.object;
1697 Class mainDataType = prop.dataTypeClass;
1699 bool result = false;
1700 void * dataPtr, * data = null, * subData = null;
1701 void * propObject = null;
1702 DataValue valueData = { 0 }, valueSubData = { 0 };
1706 mainDataType = prop.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, prop.dataTypeString);
1707 dataType = mainDataType;
1709 // Prepare main prop
1710 if(dataType.type == structClass)
1712 data = new0 byte[dataType.structSize];
1713 if(this.subMember || this.subProperty)
1714 prop.Get(object, data);
1718 else if(dataType.type == normalClass || dataType.type == noHeadClass)
1720 dataPtr = &valueData;
1722 if(this.subMember || this.subProperty)
1725 Instance current = (Instance)prop.Get(object);
1726 propObject = valueData.p = eInstance_New(dataType);
1727 CopyInstanceData(dataType, propObject, current);
1733 if(this.subMember || this.subProperty)
1734 GetProperty(prop, object, &valueData);
1736 dataPtr = &valueData;
1737 propObject = &valueData;
1743 DataMember member = this.subMember;
1744 Class subDataType = member.dataTypeClass;
1746 subDataType = member.dataTypeClass = eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, member.dataTypeString);
1749 if(dataType.type == bitClass)
1750 dataPtr = &bitValue;
1752 dataPtr = (byte *)dataPtr + member.offset + this.extraOffset;
1754 dataType = subDataType;
1756 else if(this.subProperty)
1758 Property subProperty = this.subProperty;
1759 Class subDataType = subProperty.dataTypeClass;
1762 subDataType = subProperty.dataTypeClass =
1763 eSystem_FindClass(((Designer)GetActiveDesigner()).codeEditor.privateModule, subProperty.dataTypeString);
1764 if(!subProperty.Get) subDataType = null;
1767 if(subDataType.type == structClass)
1769 subData = new0 byte[subDataType.structSize];
1773 dataPtr = &valueSubData;
1775 dataType = subDataType;
1780 if(dataType._vTbl[__ecereVMethodID_class_OnSaveEdit](dataType, dataPtr, editControl, null))
1782 if(mainDataType.type == bitClass && this.subMember)
1784 BitMember bitMember = (BitMember)this.subMember;
1785 valueData.ui &= ~ (uint)bitMember.mask;
1786 valueData.ui |= bitValue << bitMember.pos;
1788 if(this.subProperty)
1790 if(dataType.type == structClass)
1791 this.subProperty.Set(propObject, subData);
1792 else if(dataType.type == unitClass || dataType.type == enumClass || dataType.type == bitClass)
1794 if(!strcmp(dataType.dataTypeString, "float"))
1795 ((void(*)(void *,float))(void *)this.subProperty.Set)(propObject, valueSubData.f);
1796 else if(!strcmp(dataType.dataTypeString, "double"))
1797 ((void(*)(void *,double))(void *)this.subProperty.Set)(propObject, valueSubData.d);
1798 else if(!strcmp(dataType.dataTypeString, "byte"))
1799 ((void(*)(void *,byte))(void *)this.subProperty.Set)(propObject, valueSubData.uc);
1800 else if(!strcmp(dataType.dataTypeString, "uint16"))
1801 ((void(*)(void *,uint16))(void *)this.subProperty.Set)(propObject, valueSubData.us);
1803 this.subProperty.Set(propObject, valueSubData.ui);
1806 this.subProperty.Set(propObject, valueSubData.ui);
1808 if(mainDataType.type == structClass)
1809 prop.Set(object, data);
1810 else if(mainDataType.type == unitClass || mainDataType.type == enumClass || mainDataType.type == bitClass)
1812 if(!strcmp(mainDataType.dataTypeString, "float"))
1813 ((void(*)(void *,float))(void *)prop.Set)(object, valueData.f);
1814 else if(!strcmp(mainDataType.dataTypeString, "double"))
1815 ((void(*)(void *,double))(void *)prop.Set)(object, valueData.d);
1816 else if(!strcmp(mainDataType.dataTypeString, "byte"))
1817 ((void(*)(void *,byte))(void *)prop.Set)(object, valueData.uc);
1818 else if(!strcmp(mainDataType.dataTypeString, "uint16"))
1819 ((void(*)(void *,uint16))(void *)prop.Set)(object, valueData.us);
1821 prop.Set(object, valueData.ui);
1824 prop.Set(object, valueData.ui);
1828 if(data == dataPtr) dataType._vTbl[__ecereVMethodID_class_OnFree](dataType, &data);
1829 if(subData == dataPtr) dataType._vTbl[__ecereVMethodID_class_OnFree](dataType, &subData);
1835 return sheet.SaveEdit(this, object);
1841 class Category : struct
1843 Category prev, next;