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(const char * s, int len, const char * switchToKeep, int lenSwitchToKeep)
14 String string = new char[len+1];
15 if(s[0] == '-' && switchToKeep && switchToKeep[0])
17 if(strstr(s+1, switchToKeep) == s+1)
19 memcpy(string, s+lenSwitchToKeep+1, len-lenSwitchToKeep-1);
20 string[len-lenSwitchToKeep-1] = '\0';
27 memcpy(string, s, len);
33 class StringListBox : EditBox
35 const char * switchToKeep;
38 textHorzScroll = true;
40 property Array<String> strings
62 Array<String> array { };
64 const char * contents = property::contents;
69 for(c = 0; (ch = contents[c]); c++)
71 if(ch == ' ' && !quoted)
75 if((s = MakeString(contents + start, c - start, switchToKeep, lenSwitchToKeep)))
90 if((s = MakeString(contents + start, c - start, switchToKeep, lenSwitchToKeep)))
98 define dialogTitle = $"Project Settings";
99 static Color unfocusedSelectorColor { 70, 96, 166 };
100 class ProjectSettings : Window
103 background = formColor;
104 borderStyle = sizable;
105 minClientSize = { 650, 520 };
109 property Project project
114 projectTab.project = value;
117 buildTab.SelectNode(project.topNode, false);
119 if(project && project.topNode && project.topNode.name && project.topNode.name[0])
122 get { return ::project; }
125 property ProjectNode projectNode
127 set { buildTab.SelectNode(value, false); }
128 get { return currentNode; }
131 void UpdateDialogTitle()
133 //char * s = PrintString("Project Settings - ", project.topNode.fileName);
135 char * projectName = new char[strlen(project.topNode.name) + 1];
136 const char * nodeName = currentNode && currentNode != project.topNode ? currentNode.name : "";
137 const char * config = buildTab.selectedConfigName;
138 const char * platform = buildTab.selectedPlatformName;
139 char * label = new char[strlen(dialogTitle) + 3 + strlen(project.topNode.name) + 3 +
140 strlen(nodeName) + 2 + strlen(config) + 1 + strlen(platform) + 1 + 1];
141 strcpy(label, dialogTitle);
142 strcat(label, " - ");
143 strcpy(projectName, project.topNode.name);
144 StripExtension(projectName);
145 strcat(label, projectName);
146 if(currentNode && currentNode.type != project)
148 strcat(label, " - ");
149 strcat(label, nodeName);
151 if(strlen(config) || strlen(platform))
155 strcat(label, config);
156 if(strlen(config) && strlen(platform))
159 strcat(label, platform);
172 TabControl prjTabControl
174 this, background = formColor, anchor = { left = 8, top = 4, right = 8, bottom = 38 };
176 ProjectTab projectTab { this, tabControl = prjTabControl };
177 BuildTab buildTab { this, tabControl = prjTabControl };
178 WorkspaceTab workspaceTab { this, tabControl = prjTabControl };
182 this, size = { 80, 22 };
183 anchor = { right = 8, bottom = 8 };
184 text = $"Cancel", hotKey = escape, id = DialogResult::cancel;
186 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
188 if(prjTabControl.curTab.modifiedDocument)
190 DialogResult diagRes = MessageBox
192 type = okCancel, master = ide,
193 text = $"Lose Changes?",
194 contents = $"Are you sure you wish to discard changes made to the build options?"
198 if(prjTabControl.curTab == buildTab)
200 buildTab.RevertChanges();
201 buildTab.modifiedDocument = false;
203 if(prjTabControl.curTab == workspaceTab)
205 workspaceTab.modifiedDocument = false;
207 if(prjTabControl.curTab == projectTab)
209 projectTab.modifiedDocument = false;
211 Destroy(DialogResult::cancel);
215 Destroy(DialogResult::cancel);
221 this, size = { 80, 22 };
222 anchor = { right = 96, bottom = 8 };
223 text = $"OK", isDefault = true;
225 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
227 if(prjTabControl.curTab == buildTab && buildTab.modifiedDocument)
229 buildTab.modifiedDocument = false;
231 project.topNode.modified = true;
232 project.MarkChanges(buildTab.backupNode);
233 ide.projectView.modifiedDocument = true;
234 ide.projectView.Update(null);
236 if(prjTabControl.curTab == workspaceTab && workspaceTab.modifiedDocument)
238 workspaceTab.SaveChanges();
239 workspaceTab.modifiedDocument = false;
241 if(prjTabControl.curTab == projectTab && projectTab.modifiedDocument)
243 projectTab.SaveChanges();
244 projectTab.modifiedDocument = false;
246 Destroy(DialogResult::ok);
254 prjTabControl.curTab = buildTab;
256 ((DirectoriesBox)buildTab.compilerTab.includeDirs.editor).baseBrowsePath = project.topNode.path;
257 ((DirectoriesBox)buildTab.linkerTab.libraryDirs.editor).baseBrowsePath = project.topNode.path;
263 #define OPTION(x) ((uint)(uintptr)(&((ProjectOptions)0).x))
265 // TOFIX: USING T INSTEAD OF Z HERE CAUSED US SOME CONFLICTS WITH T IN Array TEMPLATES
267 // the BlendFileConfigPlatformProjectOptions function and the GenericOptionTools class
268 // contain code that is closely matched to the following code
269 // output changing modification should be mirrored in both implementations
270 class OptionBox<class Z> : CommonControl
272 bool mergeValues, configReplaces;
281 property Window editor
287 editor.OnRightButtonDown = OptionBox_OnRightButtonDown;
288 chainKeyDown = (void *)editor.OnKeyDown;
289 editor.OnKeyDown = OptionBox_OnKeyDown;
293 property bool visible { set { editor.visible = value; } get { return editor.visible; } }
294 property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int64)(intptr)this; } }
295 property Point position { set { editor.position = value; } }
296 property Size size { set { editor.size = value; } }
297 property Anchor anchor { set { editor.anchor = value; } }
298 property Key hotKey { set { editor.hotKey = value; } }
299 property const char * text { set { editor.caption = value; Window::caption = value; } }
309 bool NotifySelect(MenuItem selection, Modifiers mods)
311 OptionBox ob = (OptionBox)(intptr)id;
312 if(eClass_IsDerived(ob._class, class(CheckBoxForEnumOptionBox)))
315 for(slave = ob.master.firstSlave; slave; slave = slave.nextSlave)
317 if(eClass_IsDerived(slave._class, class(CheckBoxForEnumOptionBox)) &&
318 ((OptionBox)slave).option == ob.option)
319 ((OptionBox)slave).Unset();
328 bool Window::OptionBox_OnRightButtonDown(int x, int y, Modifiers mods)
330 OptionBox ob = (OptionBox)(intptr)id;
331 GuiApplication app = ((GuiApplication)__thisModule.application);
333 PopupMenu { null, this, menu = ob.clearMenu,
334 position = { absPosition.x + clientStart.x + x - app.desktop.position.x, absPosition.y + clientStart.y + y - app.desktop.position.y } }.Create();
338 bool Window::OptionBox_OnKeyDown(Key key, unichar ch)
340 OptionBox ob = (OptionBox)(intptr)id;
341 if(key == Key { del, ctrl = true } || key == Key { keyPadDelete, ctrl = true })
346 return ob.chainKeyDown ? ((bool(*)(Window, Key, unichar)) ob.chainKeyDown)(this, key, ch) : true;
349 // code: 0 = not set anywhere, 1 = overridden here, 2 = inherited
350 void SetAttribs(int code)
355 for(c = Window::parent.firstChild; c; c = c.next)
357 if(eClass_IsDerived(c._class, class(Label)))
360 if(label.labeledWindow == this)
368 for(c = editor.firstChild; c; c = c.next)
370 if(eClass_IsDerived(c._class, class(Label)))
377 // control.foreground = foreground;
379 if(code == 0 || code == 1)
381 editor.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
382 editor.background = white;
386 Color foreground = 0x0F3F66;
387 int r = foreground.r, g = foreground.g, b = foreground.b;
391 editor.font = { editor.font.faceName, editor.font.size };
393 r = (int)(alpha * r + src.r * (1 - alpha));
394 g = (int)(alpha * g + src.g * (1 - alpha));
395 b = (int)(alpha * b + src.b * (1 - alpha));
397 r = Max(0,Min(255,r));
398 g = Max(0,Min(255,g));
399 b = Max(0,Min(255,b));
401 editor.background = Color { (byte) r, (byte) g, (byte) b };
406 label.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
407 //label.foreground = foreground;
411 virtual void FinalizeLoading();
413 virtual void LoadOption(ProjectOptions options);
414 virtual void RetrieveOption(ProjectOptions options, bool isCfgOrPlt);
415 virtual void UnsetOption(ProjectOptions options)
418 *(Z*)((byte *)options + option) = value;
421 virtual bool OptionSet(ProjectOptions options)
423 // TOFIX: If you get a crash here, it might be because JSON.ec must be after ProjectConfig.ec in the project files
424 // JSON.ec must also be before ProjectSettings.ec in the project files
425 if(*(Z*)((byte *)options + option))
429 // BUG: OptionCheck = OptionSet; // Overrides derived classes OptionCheck ?
431 virtual bool OptionCheck(ProjectOptions options)
433 return OptionSet(options);
436 void MarkBuildTabModified()
438 BuildTab buildTab = (BuildTab)master;
439 while(buildTab && buildTab._class != class(BuildTab))
440 buildTab = (BuildTab)buildTab.master;
441 if(buildTab) buildTab.modifiedDocument = true;
446 const char * platformName = platform ? platform.OnGetString(0,0,0) : null;
447 MarkBuildTabModified();
451 ProjectConfig c = null;
452 if(currentNode.configurations)
454 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
459 PlatformOptions p = null;
462 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
465 if(p.options && OptionSet(p.options))
466 UnsetOption(p.options);
467 if(p.options && p.options.isEmpty)
471 Iterator<PlatformOptions> it { c.platforms };
479 if(!c.platforms.count)
485 if(c.options && OptionSet(c.options))
486 UnsetOption(c.options);
487 if(c.options && c.options.isEmpty)
490 // DON'T DELETE PROJECT CONFIGS HERE!
491 if(!c.options && currentNode != project.topNode)
493 Iterator<ProjectConfig> it { currentNode.configurations };
501 if(!currentNode.configurations.count)
502 currentNode.configurations = null;
509 PlatformOptions p = null;
510 if(currentNode.platforms)
512 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
515 if(p.options && OptionSet(p.options))
516 UnsetOption(p.options);
517 if(p.options && p.options.isEmpty)
521 Iterator<PlatformOptions> it { currentNode.platforms };
529 if(!currentNode.platforms.count)
530 currentNode.platforms = null;
536 if(currentNode.options && OptionSet(currentNode.options))
537 UnsetOption(currentNode.options);
538 if(currentNode.options && currentNode.options.isEmpty)
540 // delete currentNode.options;
541 // Property will free:
542 currentNode.options = null;
548 void FigureOutInherited()
551 const char * platformName = platform ? platform.OnGetString(0,0,0) : null;
552 bool skipped = false;
553 for(node = currentNode; node; node = node.parent)
555 bool configXplatformSet = false;
556 if(config && node.configurations)
558 for(c : node.configurations; !strcmpi(c.name, config.name))
560 if(platform && c.platforms)
562 for(p : c.platforms; !strcmpi(p.name, platformName))
564 if(p.options && OptionSet(p.options))
567 LoadOption(p.options);
569 configXplatformSet = true;
575 if(skipped && c.options && OptionSet(c.options))
577 LoadOption(c.options);
578 if(configReplaces) return;
584 if((!configXplatformSet || !configReplaces) && platform && node.platforms)
586 for(p : node.platforms; !strcmpi(p.name, platformName))
588 if(skipped && p.options && OptionSet(p.options))
589 LoadOption(p.options);
594 if(skipped && node.options && OptionSet(node.options))
595 LoadOption(node.options);
596 else if(skipped && !node.parent)
604 const char * platformName = platform ? platform.OnGetString(0,0,0) : null;
605 MarkBuildTabModified();
608 ProjectConfig c = null;
609 if(!currentNode.configurations) currentNode.configurations = { };
610 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
612 currentNode.configurations.Add(c = ProjectConfig { name = CopyString(config.name) });
615 PlatformOptions p = null;
616 if(!c.platforms) c.platforms = { };
618 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
620 c.platforms.Add(p = PlatformOptions { CopyString(platformName) });
622 if(!p.options) p.options = { };
623 RetrieveOption(p.options, true);
624 if(!mergeValues) SetAttribs(1);
627 if(!c.options) c.options = { };
628 RetrieveOption(c.options, true);
629 if(!mergeValues) SetAttribs(1);
634 PlatformOptions p = null;
635 if(!currentNode.platforms) currentNode.platforms = { };
636 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
638 currentNode.platforms.Add(p = PlatformOptions { CopyString(platformName) });
640 if(!p.options) p.options = { };
641 RetrieveOption(p.options, true);
642 if(!mergeValues) SetAttribs(1);
646 if(!currentNode.options) currentNode.options = { };
647 RetrieveOption(currentNode.options, false);
648 if(!mergeValues) SetAttribs((currentNode.parent || OptionCheck(currentNode.options)) ? 1 : 0);
654 const char * platformName = platform ? platform.OnGetString(0,0,0) : null;
655 bool setAttribs = false;
656 for(node = currentNode; node; node = node.parent)
658 bool configXplatformSet = false;
659 ProjectConfig nodeConfig = null;
660 if(config && node.configurations)
662 for(c : node.configurations; !strcmpi(c.name, config.name))
664 if(platform && c.platforms)
666 for(p : c.platforms; !strcmpi(p.name, platformName))
668 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
670 LoadOption(p.options);
671 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode) ? 1 : 2); }
672 if(!mergeValues) { FinalizeLoading(); return; }
673 configXplatformSet = true;
683 if(platform && node.platforms && (!configXplatformSet || !configReplaces))
685 for(p : node.platforms; !strcmpi(p.name, platformName))
687 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
689 LoadOption(p.options);
690 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config) ? 1 : 2); }
691 if(!mergeValues) { FinalizeLoading(); return; }
697 if(nodeConfig && nodeConfig.options && ((mergeValues && !configReplaces) ? OptionCheck(nodeConfig.options) : OptionSet(nodeConfig.options)))
699 LoadOption(nodeConfig.options);
700 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !platform) ? 1 : 2); }
701 if(!mergeValues || configReplaces) { FinalizeLoading(); return; }
704 if(node.options && (mergeValues ? OptionCheck(node.options) : OptionSet(node.options)))
706 LoadOption(node.options);
707 if(!node.parent && !OptionCheck(node.options))
709 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
713 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config && !platform) ? 1 : 2); }
715 if(!mergeValues) { FinalizeLoading(); return; }
717 else if(!node.parent)
720 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
721 if(!mergeValues) { FinalizeLoading(); return; }
728 class StringOptionBox : OptionBox<String>
732 bool NotifyModified(EditBox editBox)
734 ((OptionBox)(intptr)editBox.id).Retrieve();
738 textHorzScroll = true;
741 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
743 String * string = (String*)((byte *)options + option);
744 if(*string) delete *string;
745 *string = CopyString(((EditBox)editor).contents);
748 void LoadOption(ProjectOptions options)
750 ((EditBox)editor).contents = options ? *(String*)((byte *)options + option) : "";
751 ((EditBox)editor).Deselect();
754 bool OptionCheck(ProjectOptions options)
756 String string = *(String*)((byte *)options + option);
757 return string && string[0];
760 void UnsetOption(ProjectOptions options)
762 delete *(String*)((byte *)options + option);
766 class PathOptionBox : OptionBox<String>
768 bool Window::EditBoxORB(int x, int y, Modifiers mods)
770 Window parent = this.parent;
771 x += clientStart.x + position.x;
772 y += clientStart.y + position.y;
773 return ((OptionBox)this).OptionBox_OnRightButtonDown(parent, x, y, mods);
778 typeExpected = directory, browseDialog = { };
779 editBox.OnRightButtonDown = (void *)EditBoxORB;
781 bool NotifyModified(PathBox pathBox)
783 FixPathOnPathBoxNotifyModified(pathBox);
784 ((OptionBox)(intptr)pathBox.id).Retrieve();
789 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
791 String * string = (String*)((byte *)options + option);
792 String slashPath = ((PathBox)editor).slashPath;
793 if(*string) delete *string;
794 *string = CopyString(slashPath);//(slashPath && slashPath[0]) ? CopyString(slashPath) : null;
797 void LoadOption(ProjectOptions options)
799 ((PathBox)editor).path = options ? *(String*)((byte *)options + option) : "";
800 ((PathBox)editor).Deselect();
803 bool OptionCheck(ProjectOptions options)
805 String string = *(String*)((byte *)options + option);
806 return string && string[0];
809 void UnsetOption(ProjectOptions options)
811 delete *(String*)((byte *)options + option);
815 class MultiStringOptionBox : OptionBox<Array<String>>
820 caseSensitive = true;
822 virtual Array<String> GetStrings();
823 virtual void SetStrings(Array<String> value);
825 Array<String> tempStrings;
827 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
829 Array<String> newStrings = GetStrings();
830 Array<String> * strings = (Array<String>*)((byte *)options + option);
831 if(*strings) { strings->Free(); delete *strings; }
835 Iterator<String> it { newStrings };
837 FigureOutInherited();
845 for(i : tempStrings; i && s && !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
846 if(found && (!configReplaces || platform)) // ADDED || platform here...
856 if(!mergeValues || (configReplaces && isCfgOrPlt && !platform))
857 *strings = newStrings;
860 *strings = (newStrings && newStrings.count) ? newStrings : null;
861 if(newStrings && !newStrings.count) delete newStrings;
867 void LoadOption(ProjectOptions options)
871 Array<String> strings = options ? *(Array<String>*)((byte *)options + option) : null;
879 for(i : tempStrings; i && s && !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
880 if(!found) tempStrings.Add(s);
886 SetStrings(options ? *(Array<String>*)((byte *)options + option) : null);
890 void FinalizeLoading()
894 SetStrings(tempStrings);
899 bool OptionSet(ProjectOptions options)
901 Array<String> strings = *(Array<String>*)((byte *)options + option);
902 if(mergeValues && !configReplaces)
904 return strings && strings.count;
907 return strings != null;
910 bool OptionCheck(ProjectOptions options)
912 Array<String> strings = *(Array<String>*)((byte *)options + option);
913 return strings && strings.count;
916 void UnsetOption(ProjectOptions options)
918 Array<String> * strings = (Array<String>*)((byte *)options + option);
919 if(*strings) { strings->Free(); delete *strings; }
923 class StringArrayOptionBox : MultiStringOptionBox
925 editor = StringListBox
927 bool NotifyModified(EditBox editBox)
929 ((OptionBox)(intptr)editBox.id).Retrieve();
934 // NO VIRTUAL PROPERTIES YET...
935 Array<String> GetStrings() { return ((StringListBox)editor).strings; }
936 void SetStrings(Array<String> value) { ((StringListBox)editor).strings = value; }
938 property const char * switchToKeep { set { ((StringListBox)editor).switchToKeep = value; ((StringListBox)editor).lenSwitchToKeep = strlen(value); } };
941 class StringsArrayOptionBox : MultiStringOptionBox
951 bool NotifyModified(StringsBox stringsBox)
953 ((OptionBox)(intptr)stringsBox.id).Retrieve();
958 Array<String> GetStrings() { return ((StringsBox)editor).strings; }
959 void SetStrings(Array<String> value) { ((StringsBox)editor).strings = value; }
962 bool eString_IsPathRelatedTo(char * path, char * to)
966 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION] = "";
967 char toPart[MAX_FILENAME], toRest[MAX_LOCATION] = "";
968 SplitDirectory(path, pathPart, pathRest);
969 SplitDirectory(to, toPart, toRest);
970 if(!fstrcmp(pathPart, toPart))
972 if(pathRest[0] && toRest[0])
974 SplitDirectory(pathRest, pathPart, pathRest);
975 SplitDirectory(toRest, toPart, toRest);
976 if(!fstrcmp(pathPart, toPart))
984 static void FixPathOnPathBoxNotifyModified(PathBox pathBox)
987 char path[MAX_LOCATION];
988 ValidPathBufCopy(path, pathBox.path);
990 if(len && !(path[0] == '.' && (len == 1 || (len == 2 && path[1] == DIR_SEP) || (len > 1 && path[1] == '.'))))
992 char cwdBackup[MAX_LOCATION];
995 GetWorkingDir(cwdBackup, sizeof(cwdBackup));
996 ChangeWorkingDir(project.topNode.path);
1000 ChangeWorkingDir(cwdBackup);
1001 if(eString_IsPathRelatedTo(path, project.topNode.path))
1002 MakePathRelative(path, project.topNode.path, path);
1007 if(len>1 && path[len-1] == DIR_SEP)
1009 pathBox.path = path;
1012 class DirsArrayOptionBox : MultiStringOptionBox
1015 property const char * switchToKeep { set { switchToKeep = value; lenSwitchToKeep = strlen(value); } };
1017 const char * switchToKeep;
1018 int lenSwitchToKeep;
1020 editor = DirectoriesBox
1023 bool NotifyModified(DirectoriesBox dirsBox)
1025 const char * switchToKeep = ((DirsArrayOptionBox)(intptr)dirsBox.id).switchToKeep;
1026 if(switchToKeep && switchToKeep[0])
1028 bool change = false;
1029 int lenSwitchToKeep = ((DirsArrayOptionBox)(intptr)dirsBox.id).lenSwitchToKeep;
1030 Array<String> dirs { };
1031 Array<String> previousDirs = dirsBox.strings;
1032 for(d : previousDirs)
1035 char * buffer = new char[strlen(d)+64];
1036 char * tokens[1024];
1039 count = Tokenize(buffer, sizeof(tokens)/sizeof(tokens[0]), tokens, (BackSlashEscaping)false);
1040 for(c=0; c<count; c++)
1042 if(tokens[c][0] == '-')
1044 if(strstr(tokens[c]+1, switchToKeep) == tokens[c]+1)
1045 tokens[c] += lenSwitchToKeep+1;
1047 tokens[c][0] = '\0';
1050 dirs.Add(CopyString(tokens[c]));
1055 dirsBox.strings = dirs;
1058 previousDirs.Free();
1059 delete previousDirs;
1061 ((OptionBox)(intptr)dirsBox.id).Retrieve();
1065 bool NotifyPathBoxModified(DirectoriesBox dirsBox, PathBox pathBox)
1067 FixPathOnPathBoxNotifyModified(pathBox);
1072 Array<String> GetStrings() { return ((DirectoriesBox)editor).strings; }
1073 void SetStrings(Array<String> value) { ((DirectoriesBox)editor).strings = value; }
1076 class BoolOptionBox : OptionBox<SetBool>
1082 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1084 ((OptionBox)(intptr)button.id).Retrieve();
1089 bool OptionCheck(ProjectOptions options)
1091 return *(SetBool*)((byte *)options + option) == true;
1094 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1096 bool checked = ((Button)editor).checked;
1097 *(SetBool*)((byte *)options + option) = checked ? true :
1098 ((currentNode.parent || isCfgOrPlt) ? false : unset);
1101 void LoadOption(ProjectOptions options)
1103 ((Button)editor).checked = options && (*(SetBool*)((byte *)options + option) == true);
1107 class CheckBoxForEnumOptionBox : OptionBox
1113 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1115 ((OptionBox)(intptr)button.id).Retrieve();
1118 for(slave = master.firstSlave; slave; slave = slave.nextSlave)
1120 if(eClass_IsDerived(slave._class, class(CheckBoxForEnumOptionBox)) &&
1121 slave != (Window)(intptr)button.id &&
1122 ((OptionBox)slave).option == ((OptionBox)(intptr)button.id).option)
1123 ((OptionBox)slave).Load();
1131 void LoadOption(ProjectOptions options)
1133 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1134 ((Button)editor).checked = value == enumValue;
1137 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1139 Button checkBox = (Button)editor;
1140 if(checkBox.checked)
1141 *(Z*)((byte *)options + option) = enumValue;
1145 class BuildBitDepthOptionBox : CheckBoxForEnumOptionBox<BuildBitDepth> { }
1147 class DropOptionBox : OptionBox
1151 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
1153 ((OptionBox)(intptr)dropBox.id).Retrieve();
1158 void LoadOption(ProjectOptions options)
1160 DropBox dropBox = (DropBox)editor;
1161 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1162 dropBox.currentRow = value ? dropBox.FindRow((int64)value) : dropBox.firstRow;
1165 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1167 DropBox dropBox = (DropBox)editor;
1168 DataRow row = dropBox.currentRow;
1169 Z value = (Z)(row ? row.tag : 0);
1170 *(Z*)((byte *)options + option) = value;
1174 class TargetTypeDB : DropOptionBox<TargetTypes>
1180 row = ((DropBox)editor).AddRow();
1181 row.tag = TargetTypes::executable;
1182 row.SetData(null, $"Executable");
1184 row = ((DropBox)editor).AddRow();
1185 row.tag = TargetTypes::sharedLibrary;
1186 row.SetData(null, $"Shared Library");
1188 row = ((DropBox)editor).AddRow();
1189 row.tag = TargetTypes::staticLibrary;
1190 row.SetData(null, $"Static Library");
1193 bool OptionCheck(ProjectOptions options)
1195 TargetTypes value = *(TargetTypes*)((byte *)options + option);
1196 return value && value != executable;
1200 class OptimizationDB : DropOptionBox<OptimizationStrategy>
1205 row = ((DropBox)editor).AddRow();
1206 row.tag = OptimizationStrategy::none;
1207 row.SetData(null, $"None");
1209 row = ((DropBox)editor).AddRow();
1210 row.tag = OptimizationStrategy::speed;
1211 row.SetData(null, $"For Speed (-O2)");
1213 row = ((DropBox)editor).AddRow();
1214 row.tag = OptimizationStrategy::size;
1215 row.SetData(null, $"For Size (-Os)");
1218 bool OptionCheck(ProjectOptions options)
1220 OptimizationStrategy value = *(OptimizationStrategy*)((byte *)options + option);
1221 return value && value != none;
1225 class WarningsDB : DropOptionBox<WarningsOption>
1230 row = ((DropBox)editor).AddRow();
1231 row.tag = WarningsOption::normal;
1232 row.SetData(null, $"Normal");
1234 row = ((DropBox)editor).AddRow();
1235 row.tag = WarningsOption::none;
1236 row.SetData(null, $"None");
1238 row = ((DropBox)editor).AddRow();
1239 row.tag = WarningsOption::all;
1240 row.SetData(null, $"All");
1243 bool OptionCheck(ProjectOptions options)
1245 WarningsOption value = *(WarningsOption*)((byte *)options + option);
1246 return value && value != none;
1250 void DrawStipple(Surface surface, Size clientSize)
1254 int x2 = clientSize.w - 1;
1255 int y2 = clientSize.h - 1;
1256 if((x2 - x1) & 1) x2--;
1257 if((y2 - y1) & 1) y2--;
1259 surface.LineStipple(0x5555);
1260 surface.Rectangle(x1, y1, x2, y2);
1261 surface.LineStipple(0);
1264 class BuildTab : Tab
1267 background = formColor;
1270 ProjectNode backupNode;
1271 String activeConfigName;
1273 ProjectNode lastSelectedNode;
1275 property const char * selectedConfigName
1281 SelectorButton button = (SelectorButton)configSelector.selectedButton;
1282 if(button && button.id)
1284 ProjectConfig config = (ProjectConfig)(intptr)button.id;
1292 property const char * selectedPlatformName
1298 SelectorButton button = (SelectorButton)platformSelector.selectedButton;
1299 if(button && button.id)
1301 Platform platform = (Platform)button.id;
1302 const char * platformName = platform ? platform.OnGetString(0,0,0) : null; // all these platformName are leaking, no?
1303 return platformName;
1310 Label labelConfigurations
1312 this, anchor = { left = 8, top = 14 }, labeledWindow = configSelector;
1314 void OnRedraw(Surface surface)
1316 Label::OnRedraw(surface);
1317 if(labeledWindow.active) DrawStipple(surface, clientSize);
1320 SelectorBar configSelector
1322 this, text = $"Configurations: ", anchor = { left = 98, top = 8, right = 54 }; size = { 0, 26 };
1324 direction = horizontal, scrollable = true;
1326 bool OnKeyDown(Key key, unichar ch)
1330 ((BuildTab)parent).createConfig.NotifyClicked(parent, ((BuildTab)parent).createConfig, 0, 0, 0);
1335 ((BuildTab)parent).deleteConfig.NotifyClicked(parent, ((BuildTab)parent).deleteConfig, 0, 0, 0);
1338 return SelectorBar::OnKeyDown(key, ch);
1341 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1343 ((BuildTab)master).labelConfigurations.Update(null);
1350 parent = this, bevelOver = true, inactive = true;
1352 anchor = { top = 10, right = 31 };
1353 hotKey = altC, bitmap = BitmapResource { fileName = ":actions/docNew.png", alphaBlend = true };
1355 bool NotifyClicked(Button b, int x, int y, Modifiers mods)
1357 char tmp[MAX_F_STRING];
1358 ProjectConfig config;
1359 EditableSelectorButton button;
1361 FindUniqueConfigName("NewConfig", false, tmp);
1365 makingModified = true;
1366 compilingModified = true;
1367 linkingModified = true;
1368 name = CopyString(tmp);
1371 // objectsDirectory = /*CopyString(*/defaultObjDirExpression/*)*/;
1374 if(!project.topNode.configurations) project.topNode.configurations = { };
1375 project.topNode.configurations.Add(config);
1377 targetType = project.config.options.targetType;
1379 config.options.targetFileName = project.moduleName;
1380 config.options.targetDir.dir = "";
1381 config.options.objectsDirectory = defaultObjDirExpression);
1382 config.options.debug = true;
1383 config.options.optimization = none;
1384 config.options.warnings = all;
1389 configSelector, renameable = true, master = this, text = config.name, id = (int64)(intptr)config;
1390 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1393 configSelector.Select(button);
1394 modifiedDocument = true;
1398 /*Button duplicateConfig
1400 parent = this, bevelOver = true, inactive = true;
1402 anchor = { top = 10, right = 31 };
1403 hotKey = altU, bitmap = BitmapResource { fileName = ":actions/editCopy.png", alphaBlend = true };
1407 parent = this, bevelOver = true, inactive = true;
1409 anchor = { top = 10, right = 8 };
1410 hotKey = altD, bitmap = BitmapResource { fileName = ":actions/delete2.png", alphaBlend = true };
1412 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1416 String title = PrintString($"Delete ", config.name, $" Configuration");
1417 String msg = PrintString($"Are you sure you wish to delete the ", config.name, $" configuration?");
1418 if(MessageBox { type = okCancel, text = title, contents = msg }.Modal() == ok)
1420 //Iterator<Window> it { configSelector.controls };
1421 ProjectConfig configToDelete = config;
1425 SelectorButton button = (SelectorButton)it.data;
1426 if((ProjectConfig)button.id == config)
1428 button.visible = false;
1433 button = (SelectorButton)it.data;
1434 config = (ProjectConfig)button.id;
1435 configSelector.Select(button);
1441 SelectorButton button = configSelector.FindButtonByID((int64)(intptr)configToDelete);
1443 configSelector.RemoveButton(button);
1445 project.topNode.DeleteConfig(configToDelete);
1447 modifiedDocument = true;
1456 Label labelPlatforms
1458 this, anchor = { left = 8, top = 44 }, labeledWindow = platformSelector;
1460 void OnRedraw(Surface surface)
1462 Label::OnRedraw(surface);
1463 if(labeledWindow.active) DrawStipple(surface, clientSize);
1466 SelectorBar platformSelector
1468 this, text = $"Platforms: ", anchor = { left = 64, top = 38, right = 54 }; size = { 0, 26 };
1470 direction = horizontal, scrollable = true;
1472 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1474 ((BuildTab)master).labelPlatforms.Update(null);
1479 TabControl buildTabControl
1481 this, background = formColor, anchor = { left = 8, top = 64, right = 8, bottom = 8 };
1482 curTab = compilerTab;
1484 CompilerTab compilerTab { this, tabControl = buildTabControl };
1485 LinkerTab linkerTab { this, tabControl = buildTabControl };
1486 BuilderTab builderTab { this, tabControl = buildTabControl };
1489 this, font = { font.faceName, font.size, italic = true }, stayOnTop = true,
1490 text = $"(Right click or press Ctrl-Del to revert an option to inherited value)", anchor = { top = 72, right = 16 }
1493 void FindUniqueConfigName(const char * baseName, bool startWithNumber, char * output)
1496 char tmp[MAX_F_STRING];
1498 sprintf(tmp, "%s%d", baseName, num);
1500 strcpy(tmp, baseName);
1503 ProjectConfig config = null;
1504 for(c : project.topNode.configurations)
1505 { // TOFIX: Error when omitting these brackets, c not found
1506 if(c.name && !strcmp(c.name, tmp))
1515 sprintf(tmp, "%s%d", baseName, num);
1520 strcpy(output, tmp);
1523 bool PlatformClicked(Button clickedButton, int x, int y, Modifiers mods)
1525 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1527 platform = (Platform)clickedButton.id;
1529 // Load Settings Into Dialog
1530 compilerTab.LoadSettings();
1531 linkerTab.LoadSettings();
1532 builderTab.LoadSettings();
1535 buildTabControl.Activate();
1537 if(compilerTab.rightPaneHeader.visible)
1538 compilerTab.rightPaneHeader.Update(null);
1539 ((ProjectSettings)master).UpdateDialogTitle();
1546 platformSelector.DestroyChildren();
1547 configSelector.DestroyChildren();
1549 delete activeConfigName;
1552 bool ConfigOnRename(EditableSelectorButton button, char * * oldName, char * * newName)
1557 for(c = 0; (ch = (*newName)[c]); c++)
1559 if(ch == '_' || isalpha(ch) || (isdigit(ch) && d))
1560 (*newName)[d++] = ch;
1566 for(c : project.topNode.configurations; c != config)
1568 if(!strcmpi(c.name, *newName))
1574 if(found || !(*newName)[0])
1576 char tmp[MAX_F_STRING];
1577 char * tmpName = config.name;
1579 FindUniqueConfigName("NewConfig", false, tmp);
1580 config.name = tmpName;
1582 *newName = CopyString(tmp);
1586 if(activeConfigName && !strcmp(activeConfigName, *oldName))
1588 delete activeConfigName;
1589 activeConfigName = CopyString(*newName);
1592 project.topNode.RenameConfig(config.name, *newName);
1594 modifiedDocument = true;
1598 bool ConfigClicked(Button clickedButton, int x, int y, Modifiers mods)
1600 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1602 config = (ProjectConfig)(intptr)clickedButton.id;
1604 // Load Settings Into Dialog
1605 compilerTab.LoadSettings();
1606 linkerTab.LoadSettings();
1607 builderTab.LoadSettings();
1609 deleteConfig.disabled = (clickedButton._class == class(SelectorButton));
1612 buildTabControl.Activate();
1614 compilerTab.fileList.Update(null);
1615 if(compilerTab.rightPaneHeader.visible)
1616 compilerTab.rightPaneHeader.Update(null);
1617 ((ProjectSettings)master).UpdateDialogTitle();
1622 void SelectNode(ProjectNode node, bool ignoreAsLastSelection)
1624 if(node != currentNode)
1626 Window ac = compilerTab.rightPane.activeChild;
1627 bool prevNodeRes = currentNode ? currentNode.isInResources : false;
1630 if(!node) node = project.topNode;
1632 newNodeRes = node.isInResources;
1635 if(!ignoreAsLastSelection)
1636 lastSelectedNode = node;
1638 ((ProjectSettings)master).UpdateDialogTitle();
1639 if(node.type == project)
1641 compilerTab.rightPaneHeader.visible = false;
1645 compilerTab.rightPaneHeader.id = (int64)(intptr)node;
1646 compilerTab.rightPaneHeader.Update(null);
1647 compilerTab.rightPaneHeader.visible = true;
1651 DataRow row = compilerTab.fileList.FindSubRow((int64)(intptr)currentNode);
1654 compilerTab.fileList.currentRow = row;
1655 while((row = row.parent))
1656 row.collapsed = false;
1660 if(prevNodeRes != newNodeRes)
1662 compilerTab.labelObjDir.visible = !newNodeRes;
1663 compilerTab.objDir.visible = !newNodeRes;
1664 compilerTab.excludeFromBuild.visible = !newNodeRes;
1665 compilerTab.labelPreprocessorDefs.visible = !newNodeRes;
1666 compilerTab.preprocessorDefs.visible = !newNodeRes;
1667 compilerTab.labelDefaultNameSpace.visible = !newNodeRes;
1668 compilerTab.defaultNameSpace.visible = !newNodeRes;
1669 compilerTab.strictNameSpaces.visible = !newNodeRes;
1670 compilerTab.memoryGuard.visible = !newNodeRes;
1671 compilerTab.noLineNumbers.visible = !newNodeRes;
1672 compilerTab.debug.visible = !newNodeRes;
1673 compilerTab.labelWarnings.visible = !newNodeRes;
1674 compilerTab.warnings.visible = !newNodeRes;
1675 compilerTab.profiling.visible = !newNodeRes;
1676 compilerTab.labelOptimization.visible = !newNodeRes;
1677 compilerTab.optimization.visible = !newNodeRes;
1678 compilerTab.fastMath.visible = !newNodeRes;
1679 compilerTab.labelIncludeDirs.visible = !newNodeRes;
1680 compilerTab.includeDirs.visible = !newNodeRes;
1683 if(node == project.topNode)
1685 compilerTab.objDir.visible = true;
1686 compilerTab.labelObjDir.visible = true;
1688 compilerTab.excludeFromBuild.visible = false;
1692 compilerTab.objDir.visible = false;
1693 compilerTab.labelObjDir.visible = false;
1695 compilerTab.excludeFromBuild.visible = (node != project.resNode);
1698 // Load Settings Into Dialog
1699 compilerTab.LoadSettings();
1700 linkerTab.LoadSettings();
1701 builderTab.LoadSettings();
1707 if(ac == compilerTab.excludeFromBuild.editor)
1708 ac = compilerTab.objDir.editor;
1709 else if(compilerTab.excludeFromBuild.editor.visible)
1710 ac = compilerTab.excludeFromBuild.editor;
1717 void CreateConfigButtons()
1719 // Create Config Buttons
1722 configSelector, master = this, text = $"Common", id = 0; font = { font.faceName, font.size, true };
1724 NotifyClicked = ConfigClicked;
1729 if(project.topNode.configurations)
1731 for(c : project.topNode.configurations)
1733 EditableSelectorButton button
1735 configSelector, master = this, renameable = true, text = c.name, id = (int64)(intptr)c;
1736 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1745 SelectorButton button;
1747 activeConfigName = project.config ? CopyString(project.config.name) : null;
1749 compilerTab.AddNode(project.topNode, null);
1751 CreateConfigButtons();
1753 platformButton = button =
1755 platformSelector, master = this, text = $"Common", id = 0; font = { font.faceName, font.size, true };
1756 NotifyClicked = PlatformClicked; checked = true;
1761 for(p = (Platform)1; p < Platform::enumSize; p++)
1763 SelectorButton button
1765 platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int64)p;
1766 NotifyClicked = PlatformClicked;
1770 SelectorButton platformButton;
1774 // Backup Current Settings
1775 backupNode = project.topNode.Backup();
1777 buildTabControl.Activate();
1780 Iterator<Window> it { configSelector.controls };
1783 SelectorButton configButton = (SelectorButton)it.data;
1784 ProjectConfig buttonConfig = (ProjectConfig)(intptr)configButton.id;
1785 if(buttonConfig == project.config)
1787 configButton.Activate();
1788 configButton.checked = true;
1789 ConfigClicked(configButton, 0, 0, 0);
1796 platformButton.MakeActive();
1797 platformButton = null;
1806 lastSelectedNode = null;
1808 project.config = null;
1810 /* // THIS IS NOW AUTOMATED WITH A project CHECK IN ProjectNode
1811 project.configurations = project.topNode.configurations;
1812 project.platforms = project.topNode.platforms;
1813 project.options = project.topNode.options;
1816 if(project.topNode.configurations)
1818 for(c : project.topNode.configurations)
1820 if(!strcmpi(c.name, activeConfigName))
1829 List<ProjectConfig> configs = project.topNode.configurations;
1830 if(configs && configs.count)
1831 project.config = configs[0];
1834 ide.UpdateToolBarActiveConfigs(false);
1837 void RevertChanges()
1839 String configName = config ? CopyString(config.name) : null;
1841 // Revert to saved project options
1842 project.topNode.Revert(backupNode);
1844 configSelector.DestroyChildren();
1845 CreateConfigButtons();
1847 // Reselect Configuration
1850 Iterator<Window> it { configSelector.controls };
1853 Button button = (Button)it.data;
1854 ProjectConfig c = (ProjectConfig)(intptr)button.id;
1855 if(c && !strcmp(c.name, configName))
1859 button.checked = true;
1860 ConfigClicked(button, 0,0, 0);
1866 SelectNode(project.topNode, false);
1871 bool OnClose(bool parentClosing)
1873 if(modifiedDocument)
1875 DialogResult diagRes = MessageBox
1877 type = yesNoCancel, master = ide,
1878 text = $"Save changes to project settings?",
1879 contents = $"Would you like to save changes made to the build options?"
1883 if(diagRes == cancel)
1887 project.MarkChanges(backupNode);
1888 project.topNode.modified = true;
1889 ide.projectView.modifiedDocument = true;
1890 ide.UpdateToolBarActiveConfigs(false);
1891 ide.projectView.Update(null);
1893 modifiedDocument = false;
1899 class CompilerTab : Tab
1901 background = formColor;
1904 Window leftPane { this, size = { 180 }, anchor = { left = 0, top = 0, bottom = 0 }, background = formColor };
1906 Label labelFileList { leftPane, this, position = { 8, 8 }, labeledWindow = fileList };
1909 leftPane, this, borderStyle = deep, hasVertScroll = true, hasHorzScroll = true;
1910 // THIS WOULD BE EVEN MORE FUN: multiSelect = true,
1911 fullRowSelect = false, collapseControl = true, treeBranches = true;
1912 alwaysHighLight = true;
1913 selectionColor = unfocusedSelectorColor;
1915 anchor = Anchor { left = 8, top = 24, right = 4, bottom = 8 };
1918 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1920 BuildTab buildTab = (BuildTab)master;
1921 ProjectNode node = (ProjectNode)(intptr)row.tag;
1922 buildTab.SelectNode(node, false);
1926 void OnRedraw(Surface surface)
1928 ide.projectView.drawingInProjectSettingsDialog = true;
1929 ListBox::OnRedraw(surface);
1930 ide.projectView.drawingInProjectSettingsDialog = false;
1933 bool NotifyActivate(Window window, bool active, Window previous)
1937 //subclass(Skin) skinClass = (subclass(Skin))eSystem_FindClass(app, app.skin);
1938 fileList.selectionColor = Color { 10, 36, 106 }; //skinClass.selectionColor; // darkBlue;
1940 else if(fileList.currentRow)
1942 DataRow currentRow = fileList.currentRow;
1943 //int headerSize = ((fileList.style.header) ? fileList.rowHeight : 0);
1944 int height = fileList.clientSize.h + 1;// - fileList.headerSize;
1945 fileList.selectionColor = unfocusedSelectorColor;
1946 if(currentRow && currentRow.index * fileList.rowHeight > fileList.scroll.y + height - fileList.rowHeight)
1947 fileList.SetScrollPosition(fileList.scroll.x, currentRow.index * fileList.rowHeight - height + fileList.rowHeight);
1948 else if(!currentRow || currentRow.index * fileList.rowHeight < fileList.scroll.y)
1949 fileList.SetScrollPosition(fileList.scroll.x, currentRow ? currentRow.index * fileList.rowHeight : 0);
1959 this, anchor = { left = 196, top = 0, right = 0, bottom = 0 }, background = formColor, tabCycle = true;
1962 Window rightPaneHeader
1964 rightPane, this, size = { h = 21 }, anchor = { left = 0, top = 0, right = 0 }, background = Color { 70, 96, 166 };//0x0F3F66;
1965 foreground = white; visible = false;
1967 void OnRedraw(Surface surface)
1971 void (* onDisplay)(void *, void *, void *, int, int, int, void *, uint, uint) = (void *)class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay];
1973 ide.projectView.drawingInProjectSettingsDialogHeader = true;
1975 onDisplay(class(ProjectNode), (void *)(intptr)id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
1976 ide.projectView.drawingInProjectSettingsDialogHeader = false;
1981 PaneSplitter splitter
1983 this, leftPane = leftPane, rightPane = rightPane, split = 188
1986 Label labelObjDir { rightPane, this, position = { 8, 8 }, labeledWindow = objDir };
1987 PathOptionBox objDir
1989 rightPane, this, size = { 250, 22 }, anchor = { left = 8, top = 24, right = 8 };
1990 text = $"Intermediate Objects Directory", hotKey = altJ, option = OPTION(objectsDirectory);
1993 BoolOptionBox excludeFromBuild
1995 rightPane, this, position = { 8, 28 },
1996 text = $"Exclude from Build", visible = false, option = OPTION(excludeFromBuild);
1999 Label labelPreprocessorDefs { rightPane, this, position = { 8, 50 }, labeledWindow = preprocessorDefs };
2000 StringArrayOptionBox preprocessorDefs
2002 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
2003 text = $"Preprocessor Definitions", hotKey = altD, option = OPTION(preprocessorDefinitions);
2006 Label labelDefaultNameSpace { rightPane, this, position = { 8, 92 }, labeledWindow = defaultNameSpace };
2007 StringOptionBox defaultNameSpace
2009 rightPane, this, size = { 160, 22 }, position = { 8, 108 };
2010 text = $"Default Name Space", option = OPTION(defaultNameSpace);
2012 BoolOptionBox strictNameSpaces
2014 rightPane, this, position = { 172, 112 },
2015 text = $"Strict Name Spaces", option = OPTION(strictNameSpaces);
2018 BoolOptionBox fastMath
2020 rightPane, this, position = { 316, 112 },
2021 text = $"Fast Math", option = OPTION(fastMath);
2024 BoolOptionBox memoryGuard
2026 rightPane, this, position = { 8, 154 };
2027 text = $"MemoryGuard", hotKey = altM, option = OPTION(memoryGuard);
2030 Label labelWarnings { rightPane, position = { 116, 138 }, labeledWindow = warnings };
2033 rightPane, this, position = { 116, 154 };
2034 text = $"Warnings", hotKey = altW, option = OPTION(warnings);
2037 Label labelOptimization { rightPane, position = { 220, 138 }, labeledWindow = optimization };
2038 OptimizationDB optimization
2040 rightPane, this, position = { 220, 154 }, size = { 120, 22 };
2041 text = $"Optimization", hotKey = altO, option = OPTION(optimization);
2046 rightPane, this, position = { 8, 188 };
2047 text = $"Debuggable", hotKey = altG, option = OPTION(debug);
2050 BoolOptionBox profiling
2052 rightPane, this, position = { 116, 188 };
2053 text = $"Profiling Data", hotKey = altP, option = OPTION(profile);
2056 BoolOptionBox noLineNumbers
2058 rightPane, this, position = { 220, 188 };
2059 text = $"No Line Numbers", hotKey = altN, option = OPTION(noLineNumbers);
2062 Label labelCompilerOptions { rightPane, this, position = { 8, 208 }, labeledWindow = compilerOptions };
2063 StringArrayOptionBox compilerOptions
2065 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 224, right = 8 };
2066 text = $"Compiler Options", hotKey = altO, option = OPTION(compilerOptions);
2067 configReplaces = true;
2070 Label labelIncludeDirs { includeDirs.editor, labeledWindow = includeDirs, position = { 0, 6 }; };
2071 DirsArrayOptionBox includeDirs
2073 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 250, right = 8, bottom = 8 };
2074 text = $"Additional Include Directories", hotKey = altI, option = OPTION(includeDirs), switchToKeep = "I";
2079 fileList.AddField(DataField { dataType = class(ProjectNode), freeData = false,
2080 userData = null /* Now set in the ProjectNode directly to know we're in ProjectSettings Dialog -- ide.projectView*/ });
2085 BuildTab buildTab = (BuildTab)master;
2086 buildTab.SelectNode(buildTab.lastSelectedNode, true);
2090 void AddNode(ProjectNode node, DataRow addTo)
2092 DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
2094 row.tag = (int64)(intptr)node;
2096 row.SetData(null, node);
2098 if(node.files && node.files.first && node.parent &&
2099 !(!node.parent.parent &&
2100 (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") ||
2101 !strcmpi(node.name, "src") || !strcmpi(node.name, "tools"))))
2102 row.collapsed = true;
2103 else if(node.type == folder)
2104 node.icon = openFolder;
2108 for(child : node.files)
2109 AddNode(child, row);
2116 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2117 if(eClass_IsDerived(ob._class, class(OptionBox)))
2120 if(activeChild && activeChild.active)
2122 Window control = activeChild;
2123 control.Deactivate();
2130 objDir.editor.Activate();
2135 class LinkerTab : Tab
2137 background = formColor;
2140 Label labelTargetName { this, position = { 8, 8 }, labeledWindow = targetName };
2141 StringOptionBox targetName
2143 this, position = { 8, 24 }, size = { 200, 22 };
2144 text = $"Target Name", hotKey = altN, option = OPTION(targetFileName);
2147 Label labelTargetType { this, position = { 216, 8 }, labeledWindow = targetType };
2148 TargetTypeDB targetType
2150 this, position = { 216, 24 }, size = { 120, 22 };
2151 text = $"Target Type", hotKey = altT, option = OPTION(targetType);
2154 Label labelTargetDirectory { this, position = { 344, 8 }, labeledWindow = targetDirectory };
2155 PathOptionBox targetDirectory
2157 this, size = { 270, 22 }, anchor = { left = 344, top = 24, right = 8 };
2158 hotKey = altR, text = $"Target Directory", option = OPTION(targetDirectory);
2161 Label labelLibraries { this, position = { 8, 50 }, labeledWindow = libraries };
2162 StringArrayOptionBox libraries
2164 this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
2165 text = $"Additional Libraries", hotKey = altL, option = OPTION(libraries), switchToKeep = "l";
2166 configReplaces = true;
2169 Label labelLinkerOptions { this, position = { 8, 92 }, labeledWindow = linkerOptions };
2170 StringArrayOptionBox linkerOptions
2172 this, size = { 290, 22 }, anchor = { left = 8, top = 108, right = 8 };
2173 text = $"Linker Options", hotKey = altO, option = OPTION(linkerOptions);
2174 configReplaces = true;
2177 BoolOptionBox console
2179 this, position = { 8, 138 };
2180 text = $"Console Application", hotKey = altC, option = OPTION(console);
2183 BoolOptionBox compress
2185 this, position = { 8, 162 };
2186 text = $"Compress", hotKey = altW, option = OPTION(compress);
2189 Label labelLibraryDirs { libraryDirs.editor, labeledWindow = libraryDirs, position = { 0, 6 }; };
2190 DirsArrayOptionBox libraryDirs
2192 this, size = { 290, 22 }, anchor = { left = 8, top = 182, right = 8, bottom = 8 };
2193 text = $"Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs), switchToKeep = "L";
2198 ((BuildTab)master).SelectNode(project.topNode, true);
2205 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2206 if(eClass_IsDerived(ob._class, class(OptionBox)))
2208 compress.disabled = (config && config.options && config.options.debug == true) || project.topNode.options.debug == true;
2210 if(activeChild && activeChild.active)
2212 Window control = activeChild;
2213 control.Deactivate();
2219 class BuilderTab : Tab
2221 background = formColor;
2224 Label labelPrebuildCommands { prebuildCommands.editor, labeledWindow = prebuildCommands, position = { 0, 6 }; };
2225 StringsArrayOptionBox prebuildCommands
2227 this, size = { 290, 92 }, anchor = { left = 8, top = 8, right = 8, bottom = 200 };
2228 text = $"Pre-build Commands", hotKey = altE, option = OPTION(prebuildCommands);
2231 Label labelPostbuildCommands { postbuildCommands.editor, labeledWindow = postbuildCommands, position = { 0, 6 }; };
2232 StringsArrayOptionBox postbuildCommands
2234 this, size = { 290, 92 }, anchor = { left = 8, top = 100, right = 8, bottom = 100 };
2235 text = $"Post-build Commands", hotKey = altT, option = OPTION(postbuildCommands);
2238 Label labelInstallCommands { installCommands.editor, labeledWindow = installCommands, position = { 0, 6 }; };
2239 StringsArrayOptionBox installCommands
2241 this, size = { 290, 92 }, anchor = { left = 8, top = 200, right = 8, bottom = 8 };
2242 text = $"Install Commands", hotKey = altT, option = OPTION(installCommands);
2248 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2249 if(eClass_IsDerived(ob._class, class(OptionBox)))
2252 if(activeChild && activeChild.active)
2254 Window control = activeChild;
2255 control.Deactivate();
2260 void OnResize(int width, int height)
2262 int h = (height - 8 * 4) / 3;
2263 prebuildCommands.anchor = { left = 8, top = 8, right = 8, bottom = h * 2 + 8 * 3 };
2264 postbuildCommands.anchor = { left = 8, top = h + 8 * 2, right = 8, bottom = h + 8 * 2 };
2265 installCommands.anchor = { left = 8, top = h * 2 + 8 * 3, right = 8, bottom = 8 };