2 import "WorkspaceSettings"
3 import "ProjectTabSettings"
5 // import "SelectorBar"
7 static ProjectConfig config;
8 static Platform platform;
9 static ProjectNode currentNode;
10 static Project project;
12 static String MakeString(char * s, int len, char * switchToDrop, int lenSwitchToDrop)
14 String string = new char[len+1];
15 if(switchToDrop && switchToDrop[0] && strstr(s, switchToDrop) == s)
17 memcpy(string, s+lenSwitchToDrop, len-lenSwitchToDrop);
18 string[len-lenSwitchToDrop] = '\0';
22 memcpy(string, s, len);
28 class StringListBox : EditBox
33 textHorzScroll = true;
35 property Array<String> strings
54 Array<String> array { };
56 char * contents = property::contents;
60 for(c = 0; (ch = contents[c]); c++)
62 if(ch == ' ' && !quoted)
65 array.Add(MakeString(contents + start, c - start, switchToDrop, lenSwitchToDrop));
77 array.Add(MakeString(contents + start, c - start, switchToDrop, lenSwitchToDrop));
83 define dialogTitle = $"Project Settings";
84 static Color unfocusedSelectorColor { 70, 96, 166 };
85 class ProjectSettings : Window
88 background = formColor;
89 borderStyle = sizable;
90 minClientSize = { 650, 520 };
95 property Project project
100 projectTab.project = value;
103 buildTab.SelectNode(project.topNode, false);
105 if(project && project.topNode && project.topNode.name && project.topNode.name[0])
108 get { return ::project; }
111 property ProjectNode projectNode
113 set { buildTab.SelectNode(value, false); }
114 get { return currentNode; }
117 void UpdateDialogTitle()
119 //char * s = PrintString("Project Settings - ", project.topNode.fileName);
121 char * projectName = new char[strlen(project.topNode.name) + 1];
122 char * nodeName = currentNode && currentNode != project.topNode ? currentNode.name : "";
123 char * config = buildTab.selectedConfigName;
124 char * platform = buildTab.selectedPlatformName;
125 char * label = new char[strlen(dialogTitle) + 3 + strlen(project.topNode.name) + 3 +
126 strlen(nodeName) + 2 + strlen(config) + 1 + strlen(platform) + 1 + 1];
127 strcpy(label, dialogTitle);
128 strcat(label, " - ");
129 strcpy(projectName, project.topNode.name);
130 StripExtension(projectName);
131 strcat(label, projectName);
132 if(currentNode && currentNode.type != project)
134 strcat(label, " - ");
135 strcat(label, nodeName);
137 if(strlen(config) || strlen(platform))
141 strcat(label, config);
142 if(strlen(config) && strlen(platform))
145 strcat(label, platform);
158 TabControl prjTabControl
160 this, background = formColor, anchor = { left = 8, top = 4, right = 8, bottom = 38 };
162 ProjectTab projectTab { this, tabControl = prjTabControl };
163 BuildTab buildTab { this, tabControl = prjTabControl };
164 WorkspaceTab workspaceTab { this, tabControl = prjTabControl };
168 this, size = { 80, 22 };
169 anchor = { right = 8, bottom = 8 };
170 text = $"Cancel", hotKey = escape, id = DialogResult::cancel;
172 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
174 if(prjTabControl.curTab.modifiedDocument)
176 DialogResult diagRes = MessageBox
178 type = okCancel, master = ide,
179 text = $"Lose Changes?",
180 contents = $"Are you sure you wish to discard changes made to the build options?"
184 if(prjTabControl.curTab == buildTab)
186 buildTab.RevertChanges();
187 buildTab.modifiedDocument = false;
189 if(prjTabControl.curTab == workspaceTab)
191 workspaceTab.modifiedDocument = false;
193 if(prjTabControl.curTab == projectTab)
195 projectTab.modifiedDocument = false;
197 Destroy(DialogResult::cancel);
201 Destroy(DialogResult::cancel);
207 this, size = { 80, 22 };
208 anchor = { right = 96, bottom = 8 };
209 text = $"OK", isDefault = true;
211 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
213 if(prjTabControl.curTab == buildTab && buildTab.modifiedDocument)
215 buildTab.modifiedDocument = false;
217 project.topNode.modified = true;
218 project.MarkChanges(buildTab.backupNode);
219 ide.projectView.modifiedDocument = true;
220 ide.projectView.Update(null);
222 if(prjTabControl.curTab == workspaceTab && workspaceTab.modifiedDocument)
224 workspaceTab.SaveChanges();
225 workspaceTab.modifiedDocument = false;
227 if(prjTabControl.curTab == projectTab && projectTab.modifiedDocument)
229 projectTab.SaveChanges();
230 projectTab.modifiedDocument = false;
232 Destroy(DialogResult::ok);
240 prjTabControl.curTab = buildTab;
242 ((DirectoriesBox)buildTab.compilerTab.includeDirs.editor).baseBrowsePath = project.topNode.path;
243 ((DirectoriesBox)buildTab.linkerTab.libraryDirs.editor).baseBrowsePath = project.topNode.path;
249 #define OPTION(x) ((uint)(&((ProjectOptions)0).x))
251 // TOFIX: USING T INSTEAD OF Z HERE CAUSED US SOME CONFLICTS WITH T IN Array TEMPLATES
253 // the BlendFileConfigPlatformProjectOptions function and the GenericOptionTools class
254 // contain code that is closely matched to the following code
255 // output changing modification should be mirrored in both implementations
256 class OptionBox<class Z> : CommonControl
258 bool mergeValues, configReplaces;
267 property Window editor
273 editor.OnRightButtonDown = OptionBox_OnRightButtonDown;
274 chainKeyDown = (void *)editor.OnKeyDown;
275 editor.OnKeyDown = OptionBox_OnKeyDown;
279 property bool visible { set { editor.visible = value; } get { return editor.visible; } }
280 property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int64)this; } }
281 property Point position { set { editor.position = value; } }
282 property Size size { set { editor.size = value; } }
283 property Anchor anchor { set { editor.anchor = value; } }
284 property Key hotKey { set { editor.hotKey = value; } }
285 property char * text { set { editor.text = value; Window::text = value; } }
295 bool NotifySelect(MenuItem selection, Modifiers mods)
297 OptionBox ob = (OptionBox)id;
298 if(eClass_IsDerived(ob._class, class(CheckBoxForEnumOptionBox)))
301 for(slave = ob.master.firstSlave; slave; slave = slave.nextSlave)
303 if(eClass_IsDerived(slave._class, class(CheckBoxForEnumOptionBox)) &&
304 ((OptionBox)slave).option == ob.option)
305 ((OptionBox)slave).Unset();
314 bool Window::OptionBox_OnRightButtonDown(int x, int y, Modifiers mods)
316 OptionBox ob = (OptionBox)id;
317 GuiApplication app = ((GuiApplication)__thisModule.application);
319 PopupMenu { null, this, menu = ob.clearMenu,
320 position = { absPosition.x + clientStart.x + x - app.desktop.position.x, absPosition.y + clientStart.y + y - app.desktop.position.y } }.Create();
324 bool Window::OptionBox_OnKeyDown(Key key, unichar ch)
326 OptionBox ob = (OptionBox)id;
327 if(key == Key { del, ctrl = true } || key == Key { keyPadDelete, ctrl = true })
332 return (((bool(*)(Window, Key, unichar)) ob.chainKeyDown)(this, key, ch);
335 // code: 0 = not set anywhere, 1 = overridden here, 2 = inherited
336 void SetAttribs(int code)
341 for(c = Window::parent.firstChild; c; c = c.next)
343 if(eClass_IsDerived(c._class, class(Label)))
346 if(label.labeledWindow == this)
354 for(c = editor.firstChild; c; c = c.next)
356 if(eClass_IsDerived(c._class, class(Label)))
363 // control.foreground = foreground;
365 if(code == 0 || code == 1)
367 editor.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
368 editor.background = white;
372 Color foreground = 0x0F3F66;
373 int r = foreground.r, g = foreground.g, b = foreground.b;
377 editor.font = { editor.font.faceName, editor.font.size };
379 r = (int)(alpha * r + src.r * (1 - alpha));
380 g = (int)(alpha * g + src.g * (1 - alpha));
381 b = (int)(alpha * b + src.b * (1 - alpha));
383 r = Max(0,Min(255,r));
384 g = Max(0,Min(255,g));
385 b = Max(0,Min(255,b));
387 editor.background = Color { (byte) r, (byte) g, (byte) b };
392 label.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
393 //label.foreground = foreground;
397 virtual void FinalizeLoading();
399 virtual void LoadOption(ProjectOptions options);
400 virtual void RetrieveOption(ProjectOptions options, bool isCfgOrPlt);
401 virtual void UnsetOption(ProjectOptions options)
404 *(Z*)((byte *)options + option) = value;
407 virtual bool OptionSet(ProjectOptions options)
409 // TOFIX: If you get a crash here, it might be because JSON.ec must be after ProjectConfig.ec in the project files
410 // JSON.ec must also be before ProjectSettings.ec in the project files
411 if(*(Z*)((byte *)options + option))
415 // BUG: OptionCheck = OptionSet; // Overrides derived classes OptionCheck ?
417 virtual bool OptionCheck(ProjectOptions options)
419 return OptionSet(options);
422 void MarkBuildTabModified()
424 BuildTab buildTab = (BuildTab)master;
425 while(buildTab && buildTab._class != class(BuildTab))
426 buildTab = (BuildTab)buildTab.master;
427 if(buildTab) buildTab.modifiedDocument = true;
432 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
433 MarkBuildTabModified();
437 ProjectConfig c = null;
438 if(currentNode.configurations)
440 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
445 PlatformOptions p = null;
448 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
451 if(p.options && OptionSet(p.options))
452 UnsetOption(p.options);
453 if(p.options && p.options.isEmpty)
457 Iterator<PlatformOptions> it { c.platforms };
465 if(!c.platforms.count)
471 if(c.options && OptionSet(c.options))
472 UnsetOption(c.options);
473 if(c.options && c.options.isEmpty)
476 // DON'T DELETE PROJECT CONFIGS HERE!
477 if(!c.options && currentNode != project.topNode)
479 Iterator<ProjectConfig> it { currentNode.configurations };
487 if(!currentNode.configurations.count)
488 currentNode.configurations = null;
495 PlatformOptions p = null;
496 if(currentNode.platforms)
498 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
501 if(p.options && OptionSet(p.options))
502 UnsetOption(p.options);
503 if(p.options && p.options.isEmpty)
507 Iterator<PlatformOptions> it { currentNode.platforms };
515 if(!currentNode.platforms.count)
516 currentNode.platforms = null;
522 if(currentNode.options && OptionSet(currentNode.options))
523 UnsetOption(currentNode.options);
524 if(currentNode.options && currentNode.options.isEmpty)
526 // delete currentNode.options;
527 // Property will free:
528 currentNode.options = null;
534 void FigureOutInherited()
537 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
538 bool skipped = false;
539 for(node = currentNode; node; node = node.parent)
541 bool configXplatformSet = false;
542 if(config && node.configurations)
544 for(c : node.configurations; !strcmpi(c.name, config.name))
546 if(platform && c.platforms)
548 for(p : c.platforms; !strcmpi(p.name, platformName))
550 if(p.options && OptionSet(p.options))
553 LoadOption(p.options);
555 configXplatformSet = true;
561 if(skipped && c.options && OptionSet(c.options))
563 LoadOption(c.options);
564 if(configReplaces) return;
570 if((!configXplatformSet || !configReplaces) && platform && node.platforms)
572 for(p : node.platforms; !strcmpi(p.name, platformName))
574 if(skipped && p.options && OptionSet(p.options))
575 LoadOption(p.options);
580 if(skipped && node.options && OptionSet(node.options))
581 LoadOption(node.options);
582 else if(skipped && !node.parent)
590 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
591 MarkBuildTabModified();
594 ProjectConfig c = null;
595 if(!currentNode.configurations) currentNode.configurations = { };
596 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
598 currentNode.configurations.Add(c = ProjectConfig { name = CopyString(config.name) });
601 PlatformOptions p = null;
602 if(!c.platforms) c.platforms = { };
604 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
606 c.platforms.Add(p = PlatformOptions { CopyString(platformName) });
608 if(!p.options) p.options = { };
609 RetrieveOption(p.options, true);
610 if(!mergeValues) SetAttribs(1);
613 if(!c.options) c.options = { };
614 RetrieveOption(c.options, true);
615 if(!mergeValues) SetAttribs(1);
620 PlatformOptions p = null;
621 if(!currentNode.platforms) currentNode.platforms = { };
622 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
624 currentNode.platforms.Add(p = PlatformOptions { CopyString(platformName) });
626 if(!p.options) p.options = { };
627 RetrieveOption(p.options, true);
628 if(!mergeValues) SetAttribs(1);
632 if(!currentNode.options) currentNode.options = { };
633 RetrieveOption(currentNode.options, false);
634 if(!mergeValues) SetAttribs((currentNode.parent || OptionCheck(currentNode.options)) ? 1 : 0);
640 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
641 bool setAttribs = false;
642 for(node = currentNode; node; node = node.parent)
644 bool configXplatformSet = false;
645 ProjectConfig nodeConfig = null;
646 if(config && node.configurations)
648 for(c : node.configurations; !strcmpi(c.name, config.name))
650 if(platform && c.platforms)
652 for(p : c.platforms; !strcmpi(p.name, platformName))
654 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
656 LoadOption(p.options);
657 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode) ? 1 : 2); }
658 if(!mergeValues) { FinalizeLoading(); return; }
659 configXplatformSet = true;
669 if(platform && node.platforms && (!configXplatformSet || !configReplaces))
671 for(p : node.platforms; !strcmpi(p.name, platformName))
673 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
675 LoadOption(p.options);
676 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config) ? 1 : 2); }
677 if(!mergeValues) { FinalizeLoading(); return; }
683 if(nodeConfig && nodeConfig.options && ((mergeValues && !configReplaces) ? OptionCheck(nodeConfig.options) : OptionSet(nodeConfig.options)))
685 LoadOption(nodeConfig.options);
686 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !platform) ? 1 : 2); }
687 if(!mergeValues || configReplaces) { FinalizeLoading(); return; }
690 if(node.options && (mergeValues ? OptionCheck(node.options) : OptionSet(node.options)))
692 LoadOption(node.options);
693 if(!node.parent && !OptionCheck(node.options))
695 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
699 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config && !platform) ? 1 : 2); }
701 if(!mergeValues) { FinalizeLoading(); return; }
703 else if(!node.parent)
706 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
707 if(!mergeValues) { FinalizeLoading(); return; }
714 class StringOptionBox : OptionBox<String>
718 bool NotifyModified(EditBox editBox)
720 ((OptionBox)editBox.id).Retrieve();
724 textHorzScroll = true;
727 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
729 String * string = (String*)((byte *)options + option);
730 if(*string) delete *string;
731 *string = CopyString(((EditBox)editor).contents);
734 void LoadOption(ProjectOptions options)
736 ((EditBox)editor).contents = options ? *(String*)((byte *)options + option) : "";
737 ((EditBox)editor).Deselect();
740 bool OptionCheck(ProjectOptions options)
742 String string = *(String*)((byte *)options + option);
743 return string && string[0];
746 void UnsetOption(ProjectOptions options)
748 delete *(String*)((byte *)options + option);
752 class PathOptionBox : OptionBox<String>
754 bool Window::EditBoxORB(int x, int y, Modifiers mods)
756 Window parent = this.parent;
757 x += clientStart.x + position.x;
758 y += clientStart.y + position.y;
759 return ((OptionBox)this).OptionBox_OnRightButtonDown(parent, x, y, mods);
764 typeExpected = directory, browseDialog = { };
765 editBox.OnRightButtonDown = (void *)EditBoxORB;
767 bool NotifyModified(PathBox pathBox)
769 FixPathOnPathBoxNotifyModified(pathBox);
770 ((OptionBox)pathBox.id).Retrieve();
775 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
777 String * string = (String*)((byte *)options + option);
778 String slashPath = ((PathBox)editor).slashPath;
779 if(*string) delete *string;
780 *string = CopyString(slashPath);//(slashPath && slashPath[0]) ? CopyString(slashPath) : null;
783 void LoadOption(ProjectOptions options)
785 ((PathBox)editor).path = options ? *(String*)((byte *)options + option) : "";
786 ((PathBox)editor).Deselect();
789 bool OptionCheck(ProjectOptions options)
791 String string = *(String*)((byte *)options + option);
792 return string && string[0];
795 void UnsetOption(ProjectOptions options)
797 delete *(String*)((byte *)options + option);
801 class MultiStringOptionBox : OptionBox<Array<String>>
806 caseSensitive = true;
808 virtual Array<String> GetStrings();
809 virtual void SetStrings(Array<String> value);
811 Array<String> tempStrings;
813 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
815 Array<String> newStrings = GetStrings();
816 Array<String> * strings = (Array<String>*)((byte *)options + option);
817 if(*strings) { strings->Free(); delete *strings; }
821 Iterator<String> it { newStrings };
823 FigureOutInherited();
827 Array<String> ts = tempStrings;
832 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
833 if(found && (!configReplaces || platform)) // ADDED || platform here...
843 if(!mergeValues || (configReplaces && isCfgOrPlt && !platform))
844 *strings = newStrings;
847 *strings = (newStrings && newStrings.count) ? newStrings : null;
848 if(newStrings && !newStrings.count) delete newStrings;
854 void LoadOption(ProjectOptions options)
858 Array<String> strings = options ? *((Array<String>*)((byte *)options + option) : null;
866 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
867 if(!found) tempStrings.Add(s);
873 SetStrings(options ? *(Array<String>*)((byte *)options + option) : null);
877 void FinalizeLoading()
881 SetStrings(tempStrings);
886 bool OptionSet(ProjectOptions options)
888 Array<String> strings = *(Array<String>*)((byte *)options + option);
889 if(mergeValues && !configReplaces)
891 return strings && strings.count;
894 return strings != null;
897 bool OptionCheck(ProjectOptions options)
899 Array<String> strings = *(Array<String>*)((byte *)options + option);
900 return strings && strings.count;
903 void UnsetOption(ProjectOptions options)
905 Array<String> * strings = (Array<String>*)((byte *)options + option);
906 if(*strings) { strings->Free(); delete *strings; }
910 class StringArrayOptionBox : MultiStringOptionBox
912 editor = StringListBox
914 bool NotifyModified(EditBox editBox)
916 ((OptionBox)editBox.id).Retrieve();
921 // NO VIRTUAL PROPERTIES YET...
922 Array<String> GetStrings() { return ((StringListBox)editor).strings; }
923 void SetStrings(Array<String> value) { ((StringListBox)editor).strings = value; }
925 property char * switchToDrop { set { ((StringListBox)editor).switchToDrop = value; ((StringListBox)editor).lenSwitchToDrop = strlen(value); } };
928 class StringsArrayOptionBox : MultiStringOptionBox
938 bool NotifyModified(StringsBox stringsBox)
940 ((OptionBox)stringsBox.id).Retrieve();
945 Array<String> GetStrings() { return ((StringsBox)editor).strings; }
946 void SetStrings(Array<String> value) { ((StringsBox)editor).strings = value; }
949 bool eString_IsPathRelatedTo(char * path, char * to)
953 char rest[MAX_FILENAME];
954 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION] = "";
955 char toPart[MAX_FILENAME], toRest[MAX_LOCATION] = "";
956 SplitDirectory(path, pathPart, pathRest);
957 SplitDirectory(to, toPart, toRest);
958 if(!fstrcmp(pathPart, toPart))
960 if(pathRest[0] && toRest[0])
962 SplitDirectory(pathRest, pathPart, pathRest);
963 SplitDirectory(toRest, toPart, toRest);
964 if(!fstrcmp(pathPart, toPart))
972 static void FixPathOnPathBoxNotifyModified(PathBox pathBox)
975 char path[MAX_LOCATION];
976 ValidPathBufCopy(path, pathBox.path);
978 if(len && !(path[0] == '.' && (len == 1 || (len == 2 && path[1] == DIR_SEP) || (len > 1 && path[1] == '.'))))
980 char cwdBackup[MAX_LOCATION];
983 GetWorkingDir(cwdBackup, sizeof(cwdBackup));
984 ChangeWorkingDir(project.topNode.path);
988 ChangeWorkingDir(cwdBackup);
989 if(eString_IsPathRelatedTo(path, project.topNode.path))
990 MakePathRelative(path, project.topNode.path, path);
995 if(len>1 && path[len-1] == DIR_SEP)
1000 class DirsArrayOptionBox : MultiStringOptionBox
1003 property char * switchToDrop { set { switchToDrop = value; lenSwitchToDrop = strlen(value); } };
1005 char * switchToDrop;
1006 int lenSwitchToDrop;
1008 editor = DirectoriesBox
1010 bool NotifyModified(DirectoriesBox dirsBox)
1012 char * switchToDrop = ((DirsArrayOptionBox)dirsBox.id).switchToDrop;
1013 if(switchToDrop && switchToDrop[0])
1015 bool change = false;
1016 int lenSwitchToDrop = ((DirsArrayOptionBox)dirsBox.id).lenSwitchToDrop;
1017 Array<String> dirs { };
1018 Array<String> previousDirs = dirsBox.strings;
1019 for(d : previousDirs)
1022 char * buffer = new char[strlen(d)+64];
1023 char * tokens[1024];
1026 count = Tokenize(buffer, sizeof(tokens)/sizeof(tokens[0]), tokens, (BackSlashEscaping)false);
1027 for(c=0; c<count; c++)
1029 if(strstr(tokens[c], switchToDrop) == tokens[c])
1031 tokens[c] += lenSwitchToDrop;
1034 dirs.Add(CopyString(tokens[c]));
1039 dirsBox.strings = dirs;
1042 previousDirs.Free();
1043 delete previousDirs;
1045 ((OptionBox)dirsBox.id).Retrieve();
1049 bool NotifyPathBoxModified(DirectoriesBox dirsBox, PathBox pathBox)
1051 FixPathOnPathBoxNotifyModified(pathBox);
1056 Array<String> GetStrings() { return ((DirectoriesBox)editor).strings; }
1057 void SetStrings(Array<String> value) { ((DirectoriesBox)editor).strings = value; }
1060 class BoolOptionBox : OptionBox<SetBool>
1066 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1068 ((OptionBox)button.id).Retrieve();
1073 bool OptionCheck(ProjectOptions options)
1075 return *(SetBool*)((byte *)options + option) == true;
1078 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1080 bool checked = ((Button)editor).checked;
1081 *(SetBool*)((byte *)options + option) = checked ? true :
1082 ((currentNode.parent || isCfgOrPlt) ? false : unset);
1085 void LoadOption(ProjectOptions options)
1087 ((Button)editor).checked = options && (*(SetBool*)((byte *)options + option) == true);
1091 class CheckBoxForEnumOptionBox : OptionBox
1097 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1099 ((OptionBox)button.id).Retrieve();
1102 for(slave = master.firstSlave; slave; slave = slave.nextSlave)
1104 if(eClass_IsDerived(slave._class, class(CheckBoxForEnumOptionBox)) &&
1105 slave != (Window)button.id &&
1106 ((OptionBox)slave).option == ((OptionBox)button.id).option)
1107 ((OptionBox)slave).Load();
1115 void LoadOption(ProjectOptions options)
1117 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1118 ((Button)editor).checked = value == enumValue;
1121 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1123 Button checkBox = (Button)editor;
1124 if(checkBox.checked)
1125 *(Z*)((byte *)options + option) = enumValue;
1129 class BuildBitDepthOptionBox : CheckBoxForEnumOptionBox<BuildBitDepth> { }
1131 class DropOptionBox : OptionBox
1135 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
1137 ((OptionBox)dropBox.id).Retrieve();
1142 void LoadOption(ProjectOptions options)
1144 DropBox dropBox = (DropBox)editor;
1145 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1146 dropBox.currentRow = value ? dropBox.FindRow((int64)value) : dropBox.firstRow;
1149 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1151 DropBox dropBox = (DropBox)editor;
1152 DataRow row = dropBox.currentRow;
1153 Z value = (Z)(row ? row.tag : 0);
1154 *(Z*)((byte *)options + option) = value;
1158 class TargetTypeDB : DropOptionBox<TargetTypes>
1164 row = ((DropBox)editor).AddRow();
1165 row.tag = TargetTypes::executable;
1166 row.SetData(null, $"Executable");
1168 row = ((DropBox)editor).AddRow();
1169 row.tag = TargetTypes::sharedLibrary;
1170 row.SetData(null, $"Shared Library");
1172 row = ((DropBox)editor).AddRow();
1173 row.tag = TargetTypes::staticLibrary;
1174 row.SetData(null, $"Static Library");
1177 bool OptionCheck(ProjectOptions options)
1179 TargetTypes value = *(TargetTypes*)((byte *)options + option);
1180 return value && value != executable;
1184 class OptimizationDB : DropOptionBox<OptimizationStrategy>
1189 row = ((DropBox)editor).AddRow();
1190 row.tag = OptimizationStrategy::none;
1191 row.SetData(null, $"None");
1193 row = ((DropBox)editor).AddRow();
1194 row.tag = OptimizationStrategy::speed;
1195 row.SetData(null, $"For Speed (-O2)");
1197 row = ((DropBox)editor).AddRow();
1198 row.tag = OptimizationStrategy::size;
1199 row.SetData(null, $"For Size (-Os)");
1202 bool OptionCheck(ProjectOptions options)
1204 OptimizationStrategy value = *(OptimizationStrategy*)((byte *)options + option);
1205 return value && value != none;
1209 class WarningsDB : DropOptionBox<WarningsOption>
1214 row = ((DropBox)editor).AddRow();
1215 row.tag = WarningsOption::normal;
1216 row.SetData(null, $"Normal");
1218 row = ((DropBox)editor).AddRow();
1219 row.tag = WarningsOption::none;
1220 row.SetData(null, $"None");
1222 row = ((DropBox)editor).AddRow();
1223 row.tag = WarningsOption::all;
1224 row.SetData(null, $"All");
1227 bool OptionCheck(ProjectOptions options)
1229 WarningsOption value = *(WarningsOption*)((byte *)options + option);
1230 return value && value != none;
1234 void DrawStipple(Surface surface, Size clientSize)
1238 int x2 = clientSize.w - 1;
1239 int y2 = clientSize.h - 1;
1240 if((x2 - x1) & 1) x2--;
1241 if((y2 - y1) & 1) y2--;
1243 surface.LineStipple(0x5555);
1244 surface.Rectangle(x1, y1, x2, y2);
1245 surface.LineStipple(0);
1248 class BuildTab : Tab
1251 background = formColor;
1254 ProjectNode backupNode;
1255 String activeConfigName;
1257 ProjectNode lastSelectedNode;
1259 property char * selectedConfigName
1265 SelectorButton button = (SelectorButton)configSelector.selectedButton;
1266 if(button && button.id)
1268 ProjectConfig config = (ProjectConfig)button.id;
1276 property char * selectedPlatformName
1282 SelectorButton button = (SelectorButton)platformSelector.selectedButton;
1283 if(button && button.id)
1285 Platform platform = (Platform)button.id;
1286 char * platformName = platform ? platform.OnGetString(0,0,0) : null; // all these platformName are leaking, no?
1287 return platformName;
1294 Label labelConfigurations
1296 this, anchor = { left = 8, top = 14 }, labeledWindow = configSelector;
1298 void OnRedraw(Surface surface)
1300 Label::OnRedraw(surface);
1301 if(labeledWindow.active) DrawStipple(surface, clientSize);
1304 SelectorBar configSelector
1306 this, text = $"Configurations: ", anchor = { left = 98, top = 8, right = 54 }; size = { 0, 26 };
1308 direction = horizontal, scrollable = true;
1310 bool OnKeyDown(Key key, unichar ch)
1314 ((BuildTab)parent).createConfig.NotifyClicked(parent, ((BuildTab)parent).createConfig, 0, 0, 0);
1319 ((BuildTab)parent).deleteConfig.NotifyClicked(parent, ((BuildTab)parent).deleteConfig, 0, 0, 0);
1322 return SelectorBar::OnKeyDown(key, ch);
1325 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1327 ((BuildTab)master).labelConfigurations.Update(null);
1334 parent = this, bevelOver = true, inactive = true;
1336 anchor = { top = 10, right = 31 };
1337 hotKey = altC, bitmap = BitmapResource { fileName = ":actions/docNew.png", alphaBlend = true };
1339 bool NotifyClicked(Button b, int x, int y, Modifiers mods)
1341 char tmp[MAX_F_STRING];
1342 ProjectConfig config;
1343 EditableSelectorButton button;
1345 FindUniqueConfigName("NewConfig", false, tmp);
1349 makingModified = true;
1350 compilingModified = true;
1351 linkingModified = true;
1352 name = CopyString(tmp);
1355 // objectsDirectory = /*CopyString(*/defaultObjDirExpression/*)*/;
1358 if(!project.topNode.configurations) project.topNode.configurations = { };
1359 project.topNode.configurations.Add(config);
1361 targetType = project.config.options.targetType;
1363 config.options.targetFileName = project.moduleName;
1364 config.options.targetDir.dir = "";
1365 config.options.objectsDirectory = defaultObjDirExpression);
1366 config.options.debug = true;
1367 config.options.optimization = none;
1368 config.options.warnings = all;
1373 configSelector, renameable = true, master = this, text = config.name, id = (int64)config;
1374 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1377 configSelector.Select(button);
1378 modifiedDocument = true;
1382 /*Button duplicateConfig
1384 parent = this, bevelOver = true, inactive = true;
1386 anchor = { top = 10, right = 31 };
1387 hotKey = altU, bitmap = BitmapResource { fileName = ":actions/editCopy.png", alphaBlend = true };
1391 parent = this, bevelOver = true, inactive = true;
1393 anchor = { top = 10, right = 8 };
1394 hotKey = altD, bitmap = BitmapResource { fileName = ":actions/delete2.png", alphaBlend = true };
1396 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1400 String title = PrintString($"Delete ", config.name, $" Configuration");
1401 String msg = PrintString($"Are you sure you wish to delete the ", config.name, $" configuration?");
1402 if(MessageBox { type = okCancel, text = title, contents = msg }.Modal() == ok)
1404 Iterator<Window> it { configSelector.controls };
1405 ProjectConfig configToDelete = config;
1409 SelectorButton button = (SelectorButton)it.data;
1410 if((ProjectConfig)button.id == config)
1412 button.visible = false;
1417 button = (SelectorButton)it.data;
1418 config = (ProjectConfig)button.id;
1419 configSelector.Select(button);
1425 SelectorButton button = configSelector.FindButtonByID((int64)configToDelete);
1427 configSelector.RemoveButton(button);
1429 project.topNode.DeleteConfig(configToDelete);
1431 modifiedDocument = true;
1440 Label labelPlatforms
1442 this, anchor = { left = 8, top = 44 }, labeledWindow = platformSelector;
1444 void OnRedraw(Surface surface)
1446 Label::OnRedraw(surface);
1447 if(labeledWindow.active) DrawStipple(surface, clientSize);
1450 SelectorBar platformSelector
1452 this, text = $"Platforms: ", anchor = { left = 64, top = 38, right = 54 }; size = { 0, 26 };
1454 direction = horizontal, scrollable = true;
1456 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1458 ((BuildTab)master).labelPlatforms.Update(null);
1463 TabControl buildTabControl
1465 this, background = formColor, anchor = { left = 8, top = 64, right = 8, bottom = 8 };
1466 curTab = compilerTab;
1468 CompilerTab compilerTab { this, tabControl = buildTabControl };
1469 LinkerTab linkerTab { this, tabControl = buildTabControl };
1470 BuilderTab builderTab { this, tabControl = buildTabControl };
1473 this, font = { font.faceName, font.size, italic = true }, stayOnTop = true,
1474 text = $"(Right click or press Ctrl-Del to revert an option to inherited value)", anchor = { top = 72, right = 16 }
1477 void FindUniqueConfigName(char * baseName, bool startWithNumber, char * output)
1480 char tmp[MAX_F_STRING];
1482 sprintf(tmp, "%s%d", baseName, num);
1484 strcpy(tmp, baseName);
1487 ProjectConfig config = null;
1488 for(c : project.topNode.configurations)
1489 { // TOFIX: Error when omitting these brackets, c not found
1490 if(c.name && !strcmp(c.name, tmp))
1499 sprintf(tmp, "%s%d", baseName, num);
1504 strcpy(output, tmp);
1507 bool PlatformClicked(Button clickedButton, int x, int y, Modifiers mods)
1509 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1511 platform = (Platform)clickedButton.id;
1513 // Load Settings Into Dialog
1514 compilerTab.LoadSettings();
1515 linkerTab.LoadSettings();
1516 builderTab.LoadSettings();
1519 buildTabControl.Activate();
1521 if(compilerTab.rightPaneHeader.visible)
1522 compilerTab.rightPaneHeader.Update(null);
1523 ((ProjectSettings)master).UpdateDialogTitle();
1530 platformSelector.DestroyChildren();
1531 configSelector.DestroyChildren();
1533 delete activeConfigName;
1536 bool ConfigOnRename(EditableSelectorButton button, char * * oldName, char * * newName)
1541 for(c = 0; (ch = (*newName)[c]); c++)
1543 if(ch == '_' || isalpha(ch) || (isdigit(ch) && d))
1544 (*newName)[d++] = ch;
1550 for(c : project.topNode.configurations; c != config)
1552 if(!strcmpi(c.name, *newName))
1558 if(found || !(*newName)[0])
1560 char tmp[MAX_F_STRING];
1561 char * tmpName = config.name;
1563 FindUniqueConfigName("NewConfig", false, tmp);
1564 config.name = tmpName;
1566 *newName = CopyString(tmp);
1570 if(activeConfigName && !strcmp(activeConfigName, *oldName))
1572 delete activeConfigName;
1573 activeConfigName = CopyString(*newName);
1576 project.topNode.RenameConfig(config.name, *newName);
1578 modifiedDocument = true;
1582 bool ConfigClicked(Button clickedButton, int x, int y, Modifiers mods)
1584 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1586 config = (ProjectConfig)clickedButton.id;
1588 // Load Settings Into Dialog
1589 compilerTab.LoadSettings();
1590 linkerTab.LoadSettings();
1591 builderTab.LoadSettings();
1593 deleteConfig.disabled = (clickedButton._class == class(SelectorButton));
1596 buildTabControl.Activate();
1598 compilerTab.fileList.Update(null);
1599 if(compilerTab.rightPaneHeader.visible)
1600 compilerTab.rightPaneHeader.Update(null);
1601 ((ProjectSettings)master).UpdateDialogTitle();
1606 void SelectNode(ProjectNode node, bool ignoreAsLastSelection)
1608 if(node != currentNode)
1610 Window ac = compilerTab.rightPane.activeChild;
1611 bool prevNodeRes = currentNode ? currentNode.isInResources : false;
1614 if(!node) node = project.topNode;
1616 newNodeRes = node.isInResources;
1619 if(!ignoreAsLastSelection)
1620 lastSelectedNode = node;
1622 ((ProjectSettings)master).UpdateDialogTitle();
1623 if(node.type == project)
1625 compilerTab.rightPaneHeader.visible = false;
1629 compilerTab.rightPaneHeader.id = (int64)node;
1630 compilerTab.rightPaneHeader.Update(null);
1631 compilerTab.rightPaneHeader.visible = true;
1635 DataRow row = compilerTab.fileList.FindSubRow((int64)currentNode);
1638 compilerTab.fileList.currentRow = row;
1639 while((row = row.parent))
1640 row.collapsed = false;
1644 if(prevNodeRes != newNodeRes)
1646 compilerTab.labelObjDir.visible = !newNodeRes;
1647 compilerTab.objDir.visible = !newNodeRes;
1648 compilerTab.excludeFromBuild.visible = !newNodeRes;
1649 compilerTab.labelPreprocessorDefs.visible = !newNodeRes;
1650 compilerTab.preprocessorDefs.visible = !newNodeRes;
1651 compilerTab.labelDefaultNameSpace.visible = !newNodeRes;
1652 compilerTab.defaultNameSpace.visible = !newNodeRes;
1653 compilerTab.strictNameSpaces.visible = !newNodeRes;
1654 compilerTab.memoryGuard.visible = !newNodeRes;
1655 compilerTab.noLineNumbers.visible = !newNodeRes;
1656 compilerTab.debug.visible = !newNodeRes;
1657 compilerTab.labelWarnings.visible = !newNodeRes;
1658 compilerTab.warnings.visible = !newNodeRes;
1659 compilerTab.profiling.visible = !newNodeRes;
1660 compilerTab.labelOptimization.visible = !newNodeRes;
1661 compilerTab.optimization.visible = !newNodeRes;
1662 compilerTab.fastMath.visible = !newNodeRes;
1663 compilerTab.labelIncludeDirs.visible = !newNodeRes;
1664 compilerTab.includeDirs.visible = !newNodeRes;
1667 if(node == project.topNode)
1669 compilerTab.objDir.visible = true;
1670 compilerTab.labelObjDir.visible = true;
1672 compilerTab.excludeFromBuild.visible = false;
1676 compilerTab.objDir.visible = false;
1677 compilerTab.labelObjDir.visible = false;
1679 compilerTab.excludeFromBuild.visible = (node != project.resNode);
1682 // Load Settings Into Dialog
1683 compilerTab.LoadSettings();
1684 linkerTab.LoadSettings();
1685 builderTab.LoadSettings();
1691 if(ac == compilerTab.excludeFromBuild.editor)
1692 ac = compilerTab.objDir.editor;
1693 else if(compilerTab.excludeFromBuild.editor.visible)
1694 ac = compilerTab.excludeFromBuild.editor;
1701 void CreateConfigButtons()
1703 SelectorButton commonButton;
1705 // Create Config Buttons
1706 commonButton = SelectorButton
1708 configSelector, master = this, text = $"Common", id = (int64)null; font = { font.faceName, font.size, true };
1710 NotifyClicked = ConfigClicked;
1715 if(project.topNode.configurations)
1717 for(c : project.topNode.configurations)
1719 EditableSelectorButton button
1721 configSelector, master = this, renameable = true, text = c.name, id = (int64)c;
1722 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1731 SelectorButton button;
1733 activeConfigName = project.config ? CopyString(project.config.name) : null;
1735 compilerTab.AddNode(project.topNode, null);
1737 CreateConfigButtons();
1739 platformButton = button =
1741 platformSelector, master = this, text = $"Common", id = 0; font = { font.faceName, font.size, true };
1742 NotifyClicked = PlatformClicked; checked = true;
1747 for(p = (Platform)1; p < Platform::enumSize; p++)
1749 SelectorButton button
1751 platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int64)p;
1752 NotifyClicked = PlatformClicked;
1756 SelectorButton platformButton;
1760 // Backup Current Settings
1761 backupNode = project.topNode.Backup();
1763 buildTabControl.Activate();
1766 Iterator<Window> it { configSelector.controls };
1769 SelectorButton configButton = (SelectorButton)it.data;
1770 ProjectConfig buttonConfig = (ProjectConfig)configButton.id;
1771 if(buttonConfig == project.config)
1773 configButton.Activate();
1774 configButton.checked = true;
1775 ConfigClicked(configButton, 0, 0, (Modifiers)null);
1782 platformButton.MakeActive();
1783 platformButton = null;
1792 lastSelectedNode = null;
1794 project.config = null;
1796 /* // THIS IS NOW AUTOMATED WITH A project CHECK IN ProjectNode
1797 project.configurations = project.topNode.configurations;
1798 project.platforms = project.topNode.platforms;
1799 project.options = project.topNode.options;
1802 if(project.topNode.configurations)
1804 for(c : project.topNode.configurations)
1806 if(!strcmpi(c.name, activeConfigName))
1815 List<ProjectConfig> configs = project.topNode.configurations;
1816 if(configs && configs.count)
1817 project.config = configs[0];
1820 ide.UpdateToolBarActiveConfigs(false);
1823 void RevertChanges()
1825 String configName = config ? CopyString(config.name) : null;
1827 // Revert to saved project options
1828 project.topNode.Revert(backupNode);
1830 configSelector.DestroyChildren();
1831 CreateConfigButtons();
1833 // Reselect Configuration
1836 Iterator<Window> it { configSelector.controls };
1839 Button button = (Button)it.data;
1840 ProjectConfig c = (ProjectConfig)button.id;
1841 if(c && !strcmp(c.name, configName))
1845 button.checked = true;
1846 ConfigClicked(button, 0,0, 0);
1852 SelectNode(project.topNode, false);
1857 bool OnClose(bool parentClosing)
1859 if(modifiedDocument)
1861 DialogResult diagRes = MessageBox
1863 type = yesNoCancel, master = ide,
1864 text = $"Save changes to project settings?",
1865 contents = $"Would you like to save changes made to the build options?"
1869 if(diagRes == cancel)
1873 project.MarkChanges(backupNode);
1874 project.topNode.modified = true;
1875 ide.projectView.modifiedDocument = true;
1876 ide.UpdateToolBarActiveConfigs(false);
1877 ide.projectView.Update(null);
1879 modifiedDocument = false;
1885 class CompilerTab : Tab
1887 background = formColor;
1890 Window leftPane { this, size = { 180 }, anchor = { left = 0, top = 0, bottom = 0 }, background = formColor };
1892 Label labelFileList { leftPane, this, position = { 8, 8 }, labeledWindow = fileList };
1895 leftPane, this, borderStyle = deep, hasVertScroll = true, hasHorzScroll = true;
1896 // THIS WOULD BE EVEN MORE FUN: multiSelect = true,
1897 fullRowSelect = false, collapseControl = true, treeBranches = true;
1898 alwaysHighLight = true;
1899 selectionColor = unfocusedSelectorColor;
1901 anchor = Anchor { left = 8, top = 24, right = 4, bottom = 8 };
1904 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1906 BuildTab buildTab = (BuildTab)master;
1907 ProjectNode node = (ProjectNode)row.tag;
1908 buildTab.SelectNode(node, false);
1912 void OnRedraw(Surface surface)
1914 ide.projectView.drawingInProjectSettingsDialog = true;
1915 ListBox::OnRedraw(surface);
1916 ide.projectView.drawingInProjectSettingsDialog = false;
1919 bool NotifyActivate(Window window, bool active, Window previous)
1923 //subclass(Skin) skinClass = (subclass(Skin))eSystem_FindClass(app, app.skin);
1924 fileList.selectionColor = Color { 10, 36, 106 }; //skinClass.selectionColor; // darkBlue;
1926 else if(fileList.currentRow)
1928 DataRow currentRow = fileList.currentRow;
1929 //int headerSize = ((fileList.style.header) ? fileList.rowHeight : 0);
1930 int height = fileList.clientSize.h + 1;// - fileList.headerSize;
1931 fileList.selectionColor = unfocusedSelectorColor;
1932 if(currentRow && currentRow.index * fileList.rowHeight > fileList.scroll.y + height - fileList.rowHeight)
1933 fileList.SetScrollPosition(fileList.scroll.x, currentRow.index * fileList.rowHeight - height + fileList.rowHeight);
1934 else if(!currentRow || currentRow.index * fileList.rowHeight < fileList.scroll.y)
1935 fileList.SetScrollPosition(fileList.scroll.x, currentRow ? currentRow.index * fileList.rowHeight : 0);
1945 this, anchor = { left = 196, top = 0, right = 0, bottom = 0 }, background = formColor, tabCycle = true;
1948 Window rightPaneHeader
1950 rightPane, this, size = { h = 21 }, anchor = { left = 0, top = 0, right = 0 }, background = Color { 70, 96, 166 };//0x0F3F66;
1951 foreground = white; visible = false;
1953 void OnRedraw(Surface surface)
1957 ide.projectView.drawingInProjectSettingsDialogHeader = true;
1958 ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay])(class(ProjectNode),
1959 (void *)id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
1960 ide.projectView.drawingInProjectSettingsDialogHeader = false;
1965 PaneSplitter splitter
1967 this, leftPane = leftPane, rightPane = rightPane, split = 188
1970 Label labelObjDir { rightPane, this, position = { 8, 8 }, labeledWindow = objDir };
1971 PathOptionBox objDir
1973 rightPane, this, size = { 250, 22 }, anchor = { left = 8, top = 24, right = 8 };
1974 text = $"Intermediate Objects Directory", hotKey = altJ, option = OPTION(objectsDirectory);
1977 BoolOptionBox excludeFromBuild
1979 rightPane, this, position = { 8, 28 },
1980 text = $"Exclude from Build", visible = false, option = OPTION(excludeFromBuild);
1983 Label labelPreprocessorDefs { rightPane, this, position = { 8, 50 }, labeledWindow = preprocessorDefs };
1984 StringArrayOptionBox preprocessorDefs
1986 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
1987 text = $"Preprocessor Definitions", hotKey = altD, option = OPTION(preprocessorDefinitions);
1990 Label labelDefaultNameSpace { rightPane, this, position = { 8, 92 }, labeledWindow = defaultNameSpace };
1991 StringOptionBox defaultNameSpace
1993 rightPane, this, size = { 160, 22 }, position = { 8, 108 };
1994 text = $"Default Name Space", option = OPTION(defaultNameSpace);
1996 BoolOptionBox strictNameSpaces
1998 rightPane, this, position = { 172, 112 },
1999 text = $"Strict Name Spaces", option = OPTION(strictNameSpaces);
2002 BoolOptionBox fastMath
2004 rightPane, this, position = { 316, 112 },
2005 text = $"Fast Math", option = OPTION(fastMath);
2008 BoolOptionBox memoryGuard
2010 rightPane, this, position = { 8, 154 };
2011 text = $"MemoryGuard", hotKey = altM, option = OPTION(memoryGuard);
2014 Label labelWarnings { rightPane, position = { 116, 138 }, labeledWindow = warnings };
2017 rightPane, this, position = { 116, 154 };
2018 text = $"Warnings", hotKey = altW, option = OPTION(warnings);
2021 Label labelOptimization { rightPane, position = { 220, 138 }, labeledWindow = optimization };
2022 OptimizationDB optimization
2024 rightPane, this, position = { 220, 154 }, size = { 120, 22 };
2025 text = $"Optimization", hotKey = altO, option = OPTION(optimization);
2030 rightPane, this, position = { 8, 188 };
2031 text = $"Debuggable", hotKey = altG, option = OPTION(debug);
2034 BoolOptionBox profiling
2036 rightPane, this, position = { 116, 188 };
2037 text = $"Profiling Data", hotKey = altP, option = OPTION(profile);
2040 BoolOptionBox noLineNumbers
2042 rightPane, this, position = { 220, 188 };
2043 text = $"No Line Numbers", hotKey = altN, option = OPTION(noLineNumbers);
2046 Label labelCompilerOptions { rightPane, this, position = { 8, 208 }, labeledWindow = compilerOptions };
2047 StringArrayOptionBox compilerOptions
2049 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 224, right = 8 };
2050 text = $"Compiler Options", hotKey = altO, option = OPTION(compilerOptions);
2051 configReplaces = true;
2054 Label labelIncludeDirs { includeDirs.editor, labeledWindow = includeDirs, position = { 0, 6 }; };
2055 DirsArrayOptionBox includeDirs
2057 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 250, right = 8, bottom = 8 };
2058 text = $"Additional Include Directories", hotKey = altI, option = OPTION(includeDirs), switchToDrop = "-I";
2063 fileList.AddField(DataField { dataType = class(ProjectNode), freeData = false,
2064 userData = null /* Now set in the ProjectNode directly to know we're in ProjectSettings Dialog -- ide.projectView*/ });
2069 BuildTab buildTab = (BuildTab)master;
2070 buildTab.SelectNode(buildTab.lastSelectedNode, true);
2074 void AddNode(ProjectNode node, DataRow addTo)
2076 DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
2078 row.tag = (int64)node;
2080 row.SetData(null, node);
2082 if(node.files && node.files.first && node.parent &&
2083 !(!node.parent.parent &&
2084 (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") ||
2085 !strcmpi(node.name, "src") || !strcmpi(node.name, "tools"))))
2086 row.collapsed = true;
2087 else if(node.type == folder)
2088 node.icon = openFolder;
2092 for(child : node.files)
2093 AddNode(child, row);
2100 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2101 if(eClass_IsDerived(ob._class, class(OptionBox)))
2104 if(activeChild && activeChild.active)
2106 Window control = activeChild;
2107 control.Deactivate();
2114 objDir.editor.Activate();
2119 class LinkerTab : Tab
2121 background = formColor;
2124 Label labelTargetName { this, position = { 8, 8 }, labeledWindow = targetName };
2125 StringOptionBox targetName
2127 this, position = { 8, 24 }, size = { 200, 22 };
2128 text = $"Target Name", hotKey = altN, option = OPTION(targetFileName);
2131 Label labelTargetType { this, position = { 216, 8 }, labeledWindow = targetType };
2132 TargetTypeDB targetType
2134 this, position = { 216, 24 }, size = { 120, 22 };
2135 text = $"Target Type", hotKey = altT, option = OPTION(targetType);
2138 Label labelTargetDirectory { this, position = { 344, 8 }, labeledWindow = targetDirectory };
2139 PathOptionBox targetDirectory
2141 this, size = { 270, 22 }, anchor = { left = 344, top = 24, right = 8 };
2142 hotKey = altR, text = $"Target Directory", option = OPTION(targetDirectory);
2145 Label labelLibraries { this, position = { 8, 50 }, labeledWindow = libraries };
2146 StringArrayOptionBox libraries
2148 this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
2149 text = $"Additional Libraries", hotKey = altL, option = OPTION(libraries), switchToDrop = "-l";
2150 configReplaces = true;
2153 Label labelLinkerOptions { this, position = { 8, 92 }, labeledWindow = linkerOptions };
2154 StringArrayOptionBox linkerOptions
2156 this, size = { 290, 22 }, anchor = { left = 8, top = 108, right = 8 };
2157 text = $"Linker Options", hotKey = altO, option = OPTION(linkerOptions);
2158 configReplaces = true;
2161 BoolOptionBox console
2163 this, position = { 8, 138 };
2164 text = $"Console Application", hotKey = altC, option = OPTION(console);
2167 BoolOptionBox compress
2169 this, position = { 8, 162 };
2170 text = $"Compress", hotKey = altW, option = OPTION(compress);
2173 Label labelLibraryDirs { libraryDirs.editor, labeledWindow = libraryDirs, position = { 0, 6 }; };
2174 DirsArrayOptionBox libraryDirs
2176 this, size = { 290, 22 }, anchor = { left = 8, top = 182, right = 8, bottom = 8 };
2177 text = $"Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs), switchToDrop = "-L";
2182 ((BuildTab)master).SelectNode(project.topNode, true);
2189 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2190 if(eClass_IsDerived(ob._class, class(OptionBox)))
2192 compress.disabled = (config && config.options && config.options.debug == true) || project.topNode.options.debug == true;
2194 if(activeChild && activeChild.active)
2196 Window control = activeChild;
2197 control.Deactivate();
2203 class BuilderTab : Tab
2205 background = formColor;
2208 Label labelPrebuildCommands { prebuildCommands.editor, labeledWindow = prebuildCommands, position = { 0, 6 }; };
2209 StringsArrayOptionBox prebuildCommands
2211 this, size = { 290, 100 }, anchor = { left = 8, top = 8, right = 8, bottom = 0.5 };
2212 text = $"Pre-build Commands", hotKey = altE, option = OPTION(prebuildCommands);
2215 Label labelPostbuildCommands { postbuildCommands.editor, labeledWindow = postbuildCommands, position = { 0, 6 }; };
2216 StringsArrayOptionBox postbuildCommands
2218 this, size = { 290 }, anchor = { left = 8, top = 0.5, right = 8, bottom = 8 };
2219 text = $"Post-build Commands", hotKey = altT, option = OPTION(postbuildCommands);
2224 bool disabled = strlen(((BuildTab)master).selectedPlatformName) > 0;
2226 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2227 if(eClass_IsDerived(ob._class, class(OptionBox)))
2230 if(activeChild && activeChild.active)
2232 Window control = activeChild;
2233 control.Deactivate();