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)
14 String string = new char[len+1];
15 memcpy(string, s, len);
20 class StringListBox : EditBox
22 textHorzScroll = true;
24 property Array<String> strings
43 Array<String> array { };
45 char * contents = property::contents;
49 for(c = 0; (ch = contents[c]); c++)
51 if(ch == ' ' && !quoted)
54 array.Add(MakeString(contents + start, c - start));
66 array.Add(MakeString(contents + start, c - start));
72 define dialogTitle = $"Project Settings";
73 static Color unfocusedSelectorColor { 70, 96, 166 };
74 class ProjectSettings : Window
77 background = formColor;
78 borderStyle = sizable;
79 minClientSize = { 650, 520 };
84 property Project project
89 projectTab.project = value;
92 buildTab.SelectNode(project.topNode, false);
94 if(project && project.topNode && project.topNode.name && project.topNode.name[0])
97 get { return ::project; }
100 property ProjectNode projectNode
102 set { buildTab.SelectNode(value, false); }
103 get { return currentNode; }
106 void UpdateDialogTitle()
108 //char * s = PrintString("Project Settings - ", project.topNode.fileName);
110 char * projectName = new char[strlen(project.topNode.name) + 1];
111 char * nodeName = currentNode && currentNode != project.topNode ? currentNode.name : "";
112 char * config = buildTab.selectedConfigName;
113 char * platform = buildTab.selectedPlatformName;
114 char * label = new char[strlen(dialogTitle) + 3 + strlen(project.topNode.name) + 3 +
115 strlen(nodeName) + 2 + strlen(config) + 1 + strlen(platform) + 1 + 1];
116 strcpy(label, dialogTitle);
117 strcat(label, " - ");
118 strcpy(projectName, project.topNode.name);
119 StripExtension(projectName);
120 strcat(label, projectName);
121 if(currentNode && currentNode.type != project)
123 strcat(label, " - ");
124 strcat(label, nodeName);
126 if(strlen(config) || strlen(platform))
130 strcat(label, config);
131 if(strlen(config) && strlen(platform))
134 strcat(label, platform);
147 TabControl prjTabControl
149 this, background = formColor, anchor = { left = 8, top = 4, right = 8, bottom = 38 };
151 ProjectTab projectTab { this, tabControl = prjTabControl };
152 BuildTab buildTab { this, tabControl = prjTabControl };
153 WorkspaceTab workspaceTab { this, tabControl = prjTabControl };
157 this, size = { 80, 22 };
158 anchor = { right = 8, bottom = 8 };
159 text = $"Cancel", hotKey = escape, id = DialogResult::cancel;
161 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
163 if(prjTabControl.curTab.modifiedDocument)
165 DialogResult diagRes = MessageBox
167 type = okCancel, master = ide,
168 text = $"Lose Changes?",
169 contents = $"Are you sure you wish to discard changes made to the build options?"
173 if(prjTabControl.curTab == buildTab)
175 buildTab.RevertChanges();
176 buildTab.modifiedDocument = false;
178 if(prjTabControl.curTab == workspaceTab)
180 workspaceTab.modifiedDocument = false;
182 if(prjTabControl.curTab == projectTab)
184 projectTab.modifiedDocument = false;
186 Destroy(DialogResult::cancel);
190 Destroy(DialogResult::cancel);
196 this, size = { 80, 22 };
197 anchor = { right = 96, bottom = 8 };
198 text = $"OK", isDefault = true;
200 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
202 if(prjTabControl.curTab == buildTab && buildTab.modifiedDocument)
204 buildTab.modifiedDocument = false;
206 project.topNode.modified = true;
207 project.MarkChanges(buildTab.backupNode);
208 ide.projectView.modifiedDocument = true;
209 ide.projectView.Update(null);
211 if(prjTabControl.curTab == workspaceTab && workspaceTab.modifiedDocument)
213 workspaceTab.SaveChanges();
214 workspaceTab.modifiedDocument = false;
216 if(prjTabControl.curTab == projectTab && projectTab.modifiedDocument)
218 projectTab.SaveChanges();
219 projectTab.modifiedDocument = false;
221 Destroy(DialogResult::ok);
229 prjTabControl.curTab = buildTab;
234 #define OPTION(x) ((uint)(&((ProjectOptions)0).x))
236 // TOFIX: USING T INSTEAD OF Z HERE CAUSED US SOME CONFLICTS WITH T IN Array TEMPLATES
238 // the BlendFileConfigPlatformProjectOptions function and the GenericOptionTools class
239 // contain code that is closely matched to the following code
240 // output changing modification should be mirrored in both implementations
241 class OptionBox<class Z> : CommonControl
243 bool mergeValues, configReplaces;
252 property Window editor
258 editor.OnRightButtonDown = OptionBox_OnRightButtonDown;
259 chainKeyDown = (void *)editor.OnKeyDown;
260 editor.OnKeyDown = OptionBox_OnKeyDown;
264 property bool visible { set { editor.visible = value; } get { return editor.visible; } }
265 property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int64)this; } }
266 property Point position { set { editor.position = value; } }
267 property Size size { set { editor.size = value; } }
268 property Anchor anchor { set { editor.anchor = value; } }
269 property Key hotKey { set { editor.hotKey = value; } }
270 property char * text { set { editor.text = value; Window::text = value; } }
280 bool NotifySelect(MenuItem selection, Modifiers mods)
282 OptionBox ob = (OptionBox)id;
283 if(eClass_IsDerived(ob._class, class(CheckBoxForEnumOptionBox)))
286 for(slave = ob.master.firstSlave; slave; slave = slave.nextSlave)
288 if(eClass_IsDerived(slave._class, class(CheckBoxForEnumOptionBox)) &&
289 ((OptionBox)slave).option == ob.option)
290 ((OptionBox)slave).Unset();
299 bool Window::OptionBox_OnRightButtonDown(int x, int y, Modifiers mods)
301 OptionBox ob = (OptionBox)id;
302 GuiApplication app = ((GuiApplication)__thisModule.application);
304 PopupMenu { null, this, menu = ob.clearMenu,
305 position = { absPosition.x + clientStart.x + x - app.desktop.position.x, absPosition.y + clientStart.y + y - app.desktop.position.y } }.Create();
309 bool Window::OptionBox_OnKeyDown(Key key, unichar ch)
311 OptionBox ob = (OptionBox)id;
312 if(key == Key { del, ctrl = true } || key == Key { keyPadDelete, ctrl = true })
317 return (((bool(*)(Window, Key, unichar)) ob.chainKeyDown)(this, key, ch);
320 // code: 0 = not set anywhere, 1 = overridden here, 2 = inherited
321 void SetAttribs(int code)
326 for(c = Window::parent.firstChild; c; c = c.next)
328 if(eClass_IsDerived(c._class, class(Label)))
331 if(label.labeledWindow == this)
339 for(c = editor.firstChild; c; c = c.next)
341 if(eClass_IsDerived(c._class, class(Label)))
348 // control.foreground = foreground;
350 if(code == 0 || code == 1)
352 editor.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
353 editor.background = white;
357 Color foreground = 0x0F3F66;
358 int r = foreground.r, g = foreground.g, b = foreground.b;
362 editor.font = { editor.font.faceName, editor.font.size };
364 r = (int)(alpha * r + src.r * (1 - alpha));
365 g = (int)(alpha * g + src.g * (1 - alpha));
366 b = (int)(alpha * b + src.b * (1 - alpha));
368 r = Max(0,Min(255,r));
369 g = Max(0,Min(255,g));
370 b = Max(0,Min(255,b));
372 editor.background = Color { (byte) r, (byte) g, (byte) b };
377 label.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
378 //label.foreground = foreground;
382 virtual void FinalizeLoading();
384 virtual void LoadOption(ProjectOptions options);
385 virtual void RetrieveOption(ProjectOptions options, bool isCfgOrPlt);
386 virtual void UnsetOption(ProjectOptions options)
389 *(Z*)((byte *)options + option) = value;
392 virtual bool OptionSet(ProjectOptions options)
394 // TOFIX: If you get a crash here, it might be because JSON.ec must be after ProjectConfig.ec in the project files
395 // JSON.ec must also be before ProjectSettings.ec in the project files
396 if(*(Z*)((byte *)options + option))
400 // BUG: OptionCheck = OptionSet; // Overrides derived classes OptionCheck ?
402 virtual bool OptionCheck(ProjectOptions options)
404 return OptionSet(options);
407 void MarkBuildTabModified()
409 BuildTab buildTab = (BuildTab)master;
410 while(buildTab && buildTab._class != class(BuildTab))
411 buildTab = (BuildTab)buildTab.master;
412 if(buildTab) buildTab.modifiedDocument = true;
417 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
418 MarkBuildTabModified();
422 ProjectConfig c = null;
423 if(currentNode.configurations)
425 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
430 PlatformOptions p = null;
433 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
436 if(p.options && OptionSet(p.options))
437 UnsetOption(p.options);
438 if(p.options && p.options.isEmpty)
442 Iterator<PlatformOptions> it { c.platforms };
450 if(!c.platforms.count)
456 if(c.options && OptionSet(c.options))
457 UnsetOption(c.options);
458 if(c.options && c.options.isEmpty)
461 // DON'T DELETE PROJECT CONFIGS HERE!
462 if(!c.options && currentNode != project.topNode)
464 Iterator<ProjectConfig> it { currentNode.configurations };
472 if(!currentNode.configurations.count)
473 currentNode.configurations = null;
480 PlatformOptions p = null;
481 if(currentNode.platforms)
483 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
486 if(p.options && OptionSet(p.options))
487 UnsetOption(p.options);
488 if(p.options && p.options.isEmpty)
492 Iterator<PlatformOptions> it { currentNode.platforms };
500 if(!currentNode.platforms.count)
501 currentNode.platforms = null;
507 if(currentNode.options && OptionSet(currentNode.options))
508 UnsetOption(currentNode.options);
509 if(currentNode.options && currentNode.options.isEmpty)
511 // delete currentNode.options;
512 // Property will free:
513 currentNode.options = null;
519 void FigureOutInherited()
522 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
523 bool skipped = false;
524 for(node = currentNode; node; node = node.parent)
526 bool configXplatformSet = false;
527 if(config && node.configurations)
529 for(c : node.configurations; !strcmpi(c.name, config.name))
531 if(platform && c.platforms)
533 for(p : c.platforms; !strcmpi(p.name, platformName))
535 if(p.options && OptionSet(p.options))
538 LoadOption(p.options);
540 configXplatformSet = true;
546 if(skipped && c.options && OptionSet(c.options))
548 LoadOption(c.options);
549 if(configReplaces) return;
555 if((!configXplatformSet || !configReplaces) && platform && node.platforms)
557 for(p : node.platforms; !strcmpi(p.name, platformName))
559 if(skipped && p.options && OptionSet(p.options))
560 LoadOption(p.options);
565 if(skipped && node.options && OptionSet(node.options))
566 LoadOption(node.options);
567 else if(skipped && !node.parent)
575 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
576 MarkBuildTabModified();
579 ProjectConfig c = null;
580 if(!currentNode.configurations) currentNode.configurations = { };
581 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
583 currentNode.configurations.Add(c = ProjectConfig { name = CopyString(config.name) });
586 PlatformOptions p = null;
587 if(!c.platforms) c.platforms = { };
589 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
591 c.platforms.Add(p = PlatformOptions { CopyString(platformName) });
593 if(!p.options) p.options = { };
594 RetrieveOption(p.options, true);
595 if(!mergeValues) SetAttribs(1);
598 if(!c.options) c.options = { };
599 RetrieveOption(c.options, true);
600 if(!mergeValues) SetAttribs(1);
605 PlatformOptions p = null;
606 if(!currentNode.platforms) currentNode.platforms = { };
607 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
609 currentNode.platforms.Add(p = PlatformOptions { CopyString(platformName) });
611 if(!p.options) p.options = { };
612 RetrieveOption(p.options, true);
613 if(!mergeValues) SetAttribs(1);
617 if(!currentNode.options) currentNode.options = { };
618 RetrieveOption(currentNode.options, false);
619 if(!mergeValues) SetAttribs((currentNode.parent || OptionCheck(currentNode.options)) ? 1 : 0);
625 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
626 bool setAttribs = false;
627 for(node = currentNode; node; node = node.parent)
629 bool configXplatformSet = false;
630 ProjectConfig nodeConfig = null;
631 if(config && node.configurations)
633 for(c : node.configurations; !strcmpi(c.name, config.name))
635 if(platform && c.platforms)
637 for(p : c.platforms; !strcmpi(p.name, platformName))
639 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
641 LoadOption(p.options);
642 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode) ? 1 : 2); }
643 if(!mergeValues) { FinalizeLoading(); return; }
644 configXplatformSet = true;
654 if(platform && node.platforms && (!configXplatformSet || !configReplaces))
656 for(p : node.platforms; !strcmpi(p.name, platformName))
658 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
660 LoadOption(p.options);
661 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config) ? 1 : 2); }
662 if(!mergeValues) { FinalizeLoading(); return; }
668 if(nodeConfig && nodeConfig.options && ((mergeValues && !configReplaces) ? OptionCheck(nodeConfig.options) : OptionSet(nodeConfig.options)))
670 LoadOption(nodeConfig.options);
671 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !platform) ? 1 : 2); }
672 if(!mergeValues || configReplaces) { FinalizeLoading(); return; }
675 if(node.options && (mergeValues ? OptionCheck(node.options) : OptionSet(node.options)))
677 LoadOption(node.options);
678 if(!node.parent && !OptionCheck(node.options))
680 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
684 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config && !platform) ? 1 : 2); }
686 if(!mergeValues) { FinalizeLoading(); return; }
688 else if(!node.parent)
691 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
692 if(!mergeValues) { FinalizeLoading(); return; }
699 class StringOptionBox : OptionBox<String>
703 bool NotifyModified(EditBox editBox)
705 ((OptionBox)editBox.id).Retrieve();
709 textHorzScroll = true;
712 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
714 String * string = (String*)((byte *)options + option);
715 if(*string) delete *string;
716 *string = CopyString(((EditBox)editor).contents);
719 void LoadOption(ProjectOptions options)
721 ((EditBox)editor).contents = options ? *(String*)((byte *)options + option) : "";
722 ((EditBox)editor).Deselect();
725 bool OptionCheck(ProjectOptions options)
727 String string = *(String*)((byte *)options + option);
728 return string && string[0];
731 void UnsetOption(ProjectOptions options)
733 delete *(String*)((byte *)options + option);
737 class PathOptionBox : OptionBox<String>
739 bool Window::EditBoxORB(int x, int y, Modifiers mods)
741 Window parent = this.parent;
742 x += clientStart.x + position.x;
743 y += clientStart.y + position.y;
744 return ((OptionBox)this).OptionBox_OnRightButtonDown(parent, x, y, mods);
749 typeExpected = directory, browseDialog = { };
750 editBox.OnRightButtonDown = (void *)EditBoxORB;
752 bool NotifyModified(PathBox pathBox)
754 ((OptionBox)pathBox.id).Retrieve();
759 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
761 String * string = (String*)((byte *)options + option);
762 String slashPath = ((PathBox)editor).slashPath;
763 if(*string) delete *string;
764 *string = CopyString(slashPath);//(slashPath && slashPath[0]) ? CopyString(slashPath) : null;
767 void LoadOption(ProjectOptions options)
769 ((PathBox)editor).path = options ? *(String*)((byte *)options + option) : "";
770 ((PathBox)editor).Deselect();
773 bool OptionCheck(ProjectOptions options)
775 String string = *(String*)((byte *)options + option);
776 return string && string[0];
779 void UnsetOption(ProjectOptions options)
781 delete *(String*)((byte *)options + option);
785 class MultiStringOptionBox : OptionBox<Array<String>>
790 caseSensitive = true;
792 virtual Array<String> GetStrings();
793 virtual void SetStrings(Array<String> value);
795 Array<String> tempStrings;
797 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
799 Array<String> newStrings = GetStrings();
800 Array<String> * strings = (Array<String>*)((byte *)options + option);
801 if(*strings) { strings->Free(); delete *strings; }
805 Iterator<String> it { newStrings };
807 FigureOutInherited();
811 Array<String> ts = tempStrings;
816 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
817 if(found && (!configReplaces || platform)) // ADDED || platform here...
827 if(!mergeValues || (configReplaces && isCfgOrPlt && !platform))
828 *strings = newStrings;
831 *strings = (newStrings && newStrings.count) ? newStrings : null;
832 if(newStrings && !newStrings.count) delete newStrings;
838 void LoadOption(ProjectOptions options)
842 Array<String> strings = options ? *((Array<String>*)((byte *)options + option) : null;
850 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
851 if(!found) tempStrings.Add(s);
857 SetStrings(options ? *(Array<String>*)((byte *)options + option) : null);
861 void FinalizeLoading()
865 SetStrings(tempStrings);
870 bool OptionSet(ProjectOptions options)
872 Array<String> strings = *(Array<String>*)((byte *)options + option);
873 if(mergeValues && !configReplaces)
875 return strings && strings.count;
878 return strings != null;
881 bool OptionCheck(ProjectOptions options)
883 Array<String> strings = *(Array<String>*)((byte *)options + option);
884 return strings && strings.count;
887 void UnsetOption(ProjectOptions options)
889 Array<String> * strings = (Array<String>*)((byte *)options + option);
890 if(*strings) { strings->Free(); delete *strings; }
894 class StringArrayOptionBox : MultiStringOptionBox
896 editor = StringListBox
898 bool NotifyModified(EditBox editBox)
900 ((OptionBox)editBox.id).Retrieve();
905 // NO VIRTUAL PROPERTIES YET...
906 Array<String> GetStrings() { return ((StringListBox)editor).strings; }
907 void SetStrings(Array<String> value) { ((StringListBox)editor).strings = value; }
910 class StringsArrayOptionBox : MultiStringOptionBox
920 bool NotifyModified(StringsBox stringsBox)
922 ((OptionBox)stringsBox.id).Retrieve();
927 Array<String> GetStrings() { return ((StringsBox)editor).strings; }
928 void SetStrings(Array<String> value) { ((StringsBox)editor).strings = value; }
931 class DirsArrayOptionBox : MultiStringOptionBox
933 editor = DirectoriesBox
935 bool NotifyModified(DirectoriesBox dirsBox)
937 ((OptionBox)dirsBox.id).Retrieve();
941 bool OnChangedDir(char * * directory)
943 char fixedDirectory[MAX_LOCATION] = "";
944 if(PathCat(fixedDirectory, *directory))
946 char cwdBackup[MAX_LOCATION];
949 GetWorkingDir(cwdBackup, sizeof(cwdBackup));
950 ChangeWorkingDir(project.topNode.path);
952 FileFixCase(fixedDirectory);
954 ChangeWorkingDir(cwdBackup);
956 *directory = CopyString(fixedDirectory);
962 bool OnPrepareBrowseDir(char * * directory)
964 char dir[MAX_LOCATION];
967 GetSystemPathBuffer(dir, project.topNode.path);
969 PathCat(dir, *directory);
972 strcpy(dir, *directory);
977 *directory = CopyString(dir);
979 // GCC 4.4 bug: ----- path becomes *directory
980 //strcpy(dir, path ? path : "");
984 bool OnBrowsedDir(char * * directory)
988 char path[MAX_LOCATION];
989 MakePathRelative(*directory, project.topNode.path, path);
991 *directory = CopyString(path);
997 Array<String> GetStrings() { return ((DirectoriesBox)editor).strings; }
998 void SetStrings(Array<String> value) { ((DirectoriesBox)editor).strings = value; }
1001 class BoolOptionBox : OptionBox<SetBool>
1007 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1009 ((OptionBox)button.id).Retrieve();
1014 bool OptionCheck(ProjectOptions options)
1016 return *(SetBool*)((byte *)options + option) == true;
1019 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1021 bool checked = ((Button)editor).checked;
1022 *(SetBool*)((byte *)options + option) = checked ? true :
1023 ((currentNode.parent || isCfgOrPlt) ? false : unset);
1026 void LoadOption(ProjectOptions options)
1028 ((Button)editor).checked = options && (*(SetBool*)((byte *)options + option) == true);
1032 class CheckBoxForEnumOptionBox : OptionBox
1038 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1040 ((OptionBox)button.id).Retrieve();
1043 for(slave = master.firstSlave; slave; slave = slave.nextSlave)
1045 if(eClass_IsDerived(slave._class, class(CheckBoxForEnumOptionBox)) &&
1046 slave != (Window)button.id &&
1047 ((OptionBox)slave).option == ((OptionBox)button.id).option)
1048 ((OptionBox)slave).Load();
1056 void LoadOption(ProjectOptions options)
1058 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1059 ((Button)editor).checked = value == enumValue;
1062 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1064 Button checkBox = (Button)editor;
1065 if(checkBox.checked)
1066 *(Z*)((byte *)options + option) = enumValue;
1070 class BuildBitDepthOptionBox : CheckBoxForEnumOptionBox<BuildBitDepth> { }
1072 class DropOptionBox : OptionBox
1076 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
1078 ((OptionBox)dropBox.id).Retrieve();
1083 void LoadOption(ProjectOptions options)
1085 DropBox dropBox = (DropBox)editor;
1086 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1087 dropBox.currentRow = value ? dropBox.FindRow((int64)value) : dropBox.firstRow;
1090 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1092 DropBox dropBox = (DropBox)editor;
1093 DataRow row = dropBox.currentRow;
1094 Z value = (Z)(row ? row.tag : 0);
1095 *(Z*)((byte *)options + option) = value;
1099 class TargetTypeDB : DropOptionBox<TargetTypes>
1105 row = ((DropBox)editor).AddRow();
1106 row.tag = TargetTypes::executable;
1107 row.SetData(null, $"Executable");
1109 row = ((DropBox)editor).AddRow();
1110 row.tag = TargetTypes::sharedLibrary;
1111 row.SetData(null, $"Shared Library");
1113 row = ((DropBox)editor).AddRow();
1114 row.tag = TargetTypes::staticLibrary;
1115 row.SetData(null, $"Static Library");
1118 bool OptionCheck(ProjectOptions options)
1120 TargetTypes value = *(TargetTypes*)((byte *)options + option);
1121 return value && value != executable;
1125 class OptimizationDB : DropOptionBox<OptimizationStrategy>
1130 row = ((DropBox)editor).AddRow();
1131 row.tag = OptimizationStrategy::none;
1132 row.SetData(null, $"None");
1134 row = ((DropBox)editor).AddRow();
1135 row.tag = OptimizationStrategy::speed;
1136 row.SetData(null, $"For Speed (-O2)");
1138 row = ((DropBox)editor).AddRow();
1139 row.tag = OptimizationStrategy::size;
1140 row.SetData(null, $"For Size (-Os)");
1143 bool OptionCheck(ProjectOptions options)
1145 OptimizationStrategy value = *(OptimizationStrategy*)((byte *)options + option);
1146 return value && value != none;
1150 class WarningsDB : DropOptionBox<WarningsOption>
1155 row = ((DropBox)editor).AddRow();
1156 row.tag = WarningsOption::normal;
1157 row.SetData(null, $"Normal");
1159 row = ((DropBox)editor).AddRow();
1160 row.tag = WarningsOption::none;
1161 row.SetData(null, $"None");
1163 row = ((DropBox)editor).AddRow();
1164 row.tag = WarningsOption::all;
1165 row.SetData(null, $"All");
1168 bool OptionCheck(ProjectOptions options)
1170 WarningsOption value = *(WarningsOption*)((byte *)options + option);
1171 return value && value != none;
1175 void DrawStipple(Surface surface, Size clientSize)
1179 int x2 = clientSize.w - 1;
1180 int y2 = clientSize.h - 1;
1181 if((x2 - x1) & 1) x2--;
1182 if((y2 - y1) & 1) y2--;
1184 surface.LineStipple(0x5555);
1185 surface.Rectangle(x1, y1, x2, y2);
1186 surface.LineStipple(0);
1189 class BuildTab : Tab
1192 background = formColor;
1195 ProjectNode backupNode;
1196 String activeConfigName;
1198 ProjectNode lastSelectedNode;
1200 property char * selectedConfigName
1206 SelectorButton button = (SelectorButton)configSelector.selectedButton;
1207 if(button && button.id)
1209 ProjectConfig config = (ProjectConfig)button.id;
1217 property char * selectedPlatformName
1223 SelectorButton button = (SelectorButton)platformSelector.selectedButton;
1224 if(button && button.id)
1226 Platform platform = (Platform)button.id;
1227 char * platformName = platform ? platform.OnGetString(0,0,0) : null; // all these platformName are leaking, no?
1228 return platformName;
1235 Label labelConfigurations
1237 this, anchor = { left = 8, top = 14 }, labeledWindow = configSelector;
1239 void OnRedraw(Surface surface)
1241 Label::OnRedraw(surface);
1242 if(labeledWindow.active) DrawStipple(surface, clientSize);
1245 SelectorBar configSelector
1247 this, text = $"Configurations: ", anchor = { left = 98, top = 8, right = 54 }; size = { 0, 26 };
1249 direction = horizontal, scrollable = true;
1251 bool OnKeyDown(Key key, unichar ch)
1255 ((BuildTab)parent).createConfig.NotifyClicked(parent, ((BuildTab)parent).createConfig, 0, 0, 0);
1260 ((BuildTab)parent).deleteConfig.NotifyClicked(parent, ((BuildTab)parent).deleteConfig, 0, 0, 0);
1263 return SelectorBar::OnKeyDown(key, ch);
1266 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1268 ((BuildTab)master).labelConfigurations.Update(null);
1275 parent = this, bevelOver = true, inactive = true;
1277 anchor = { top = 10, right = 31 };
1278 hotKey = altC, bitmap = BitmapResource { fileName = ":actions/docNew.png", alphaBlend = true };
1280 bool NotifyClicked(Button b, int x, int y, Modifiers mods)
1282 char tmp[MAX_F_STRING];
1283 ProjectConfig config;
1284 EditableSelectorButton button;
1286 FindUniqueConfigName("NewConfig", false, tmp);
1290 makingModified = true;
1291 compilingModified = true;
1292 linkingModified = true;
1293 name = CopyString(tmp);
1296 // objectsDirectory = /*CopyString(*/defaultObjDirExpression/*)*/;
1299 if(!project.topNode.configurations) project.topNode.configurations = { };
1300 project.topNode.configurations.Add(config);
1302 targetType = project.config.options.targetType;
1304 config.options.targetFileName = project.moduleName;
1305 config.options.targetDir.dir = "";
1306 config.options.objectsDirectory = defaultObjDirExpression);
1307 config.options.debug = true;
1308 config.options.optimization = none;
1309 config.options.warnings = all;
1314 configSelector, renameable = true, master = this, text = config.name, id = (int64)config;
1315 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1318 configSelector.Select(button);
1319 modifiedDocument = true;
1323 /*Button duplicateConfig
1325 parent = this, bevelOver = true, inactive = true;
1327 anchor = { top = 10, right = 31 };
1328 hotKey = altU, bitmap = BitmapResource { fileName = ":actions/editCopy.png", alphaBlend = true };
1332 parent = this, bevelOver = true, inactive = true;
1334 anchor = { top = 10, right = 8 };
1335 hotKey = altD, bitmap = BitmapResource { fileName = ":actions/delete2.png", alphaBlend = true };
1337 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1341 String title = PrintString($"Delete ", config.name, $" Configuration");
1342 String msg = PrintString($"Are you sure you wish to delete the ", config.name, $" configuration?");
1343 if(MessageBox { type = okCancel, text = title, contents = msg }.Modal() == ok)
1345 Iterator<Window> it { configSelector.controls };
1346 ProjectConfig configToDelete = config;
1350 SelectorButton button = (SelectorButton)it.data;
1351 if((ProjectConfig)button.id == config)
1353 button.visible = false;
1358 button = (SelectorButton)it.data;
1359 config = (ProjectConfig)button.id;
1360 configSelector.Select(button);
1366 SelectorButton button = configSelector.FindButtonByID((int64)configToDelete);
1368 configSelector.RemoveButton(button);
1370 project.topNode.DeleteConfig(configToDelete);
1372 modifiedDocument = true;
1381 Label labelPlatforms
1383 this, anchor = { left = 8, top = 44 }, labeledWindow = platformSelector;
1385 void OnRedraw(Surface surface)
1387 Label::OnRedraw(surface);
1388 if(labeledWindow.active) DrawStipple(surface, clientSize);
1391 SelectorBar platformSelector
1393 this, text = $"Platforms: ", anchor = { left = 64, top = 38, right = 54 }; size = { 0, 26 };
1395 direction = horizontal, scrollable = true;
1397 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1399 ((BuildTab)master).labelPlatforms.Update(null);
1404 TabControl buildTabControl
1406 this, background = formColor, anchor = { left = 8, top = 64, right = 8, bottom = 8 };
1407 curTab = compilerTab;
1409 CompilerTab compilerTab { this, tabControl = buildTabControl };
1410 LinkerTab linkerTab { this, tabControl = buildTabControl };
1411 BuilderTab builderTab { this, tabControl = buildTabControl };
1414 this, font = { font.faceName, font.size, italic = true }, stayOnTop = true,
1415 text = $"(Right click or press Ctrl-Del to revert an option to inherited value)", anchor = { top = 72, right = 16 }
1418 void FindUniqueConfigName(char * baseName, bool startWithNumber, char * output)
1421 char tmp[MAX_F_STRING];
1423 sprintf(tmp, "%s%d", baseName, num);
1425 strcpy(tmp, baseName);
1428 ProjectConfig config = null;
1429 for(c : project.topNode.configurations)
1430 { // TOFIX: Error when omitting these brackets, c not found
1431 if(c.name && !strcmp(c.name, tmp))
1440 sprintf(tmp, "%s%d", baseName, num);
1445 strcpy(output, tmp);
1448 bool PlatformClicked(Button clickedButton, int x, int y, Modifiers mods)
1450 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1452 platform = (Platform)clickedButton.id;
1454 // Load Settings Into Dialog
1455 compilerTab.LoadSettings();
1456 linkerTab.LoadSettings();
1457 builderTab.LoadSettings();
1460 buildTabControl.Activate();
1462 if(compilerTab.rightPaneHeader.visible)
1463 compilerTab.rightPaneHeader.Update(null);
1464 ((ProjectSettings)master).UpdateDialogTitle();
1471 platformSelector.DestroyChildren();
1472 configSelector.DestroyChildren();
1474 delete activeConfigName;
1477 bool ConfigOnRename(EditableSelectorButton button, char * * oldName, char * * newName)
1482 for(c = 0; (ch = (*newName)[c]); c++)
1484 if(ch == '_' || isalpha(ch) || (isdigit(ch) && d))
1485 (*newName)[d++] = ch;
1491 for(c : project.topNode.configurations; c != config)
1493 if(!strcmpi(c.name, *newName))
1499 if(found || !(*newName)[0])
1501 char tmp[MAX_F_STRING];
1502 char * tmpName = config.name;
1504 FindUniqueConfigName("NewConfig", false, tmp);
1505 config.name = tmpName;
1507 *newName = CopyString(tmp);
1511 if(activeConfigName && !strcmp(activeConfigName, *oldName))
1513 delete activeConfigName;
1514 activeConfigName = CopyString(*newName);
1517 project.topNode.RenameConfig(config.name, *newName);
1519 modifiedDocument = true;
1523 bool ConfigClicked(Button clickedButton, int x, int y, Modifiers mods)
1525 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1527 config = (ProjectConfig)clickedButton.id;
1529 // Load Settings Into Dialog
1530 compilerTab.LoadSettings();
1531 linkerTab.LoadSettings();
1532 builderTab.LoadSettings();
1534 deleteConfig.disabled = (clickedButton._class == class(SelectorButton));
1537 buildTabControl.Activate();
1539 compilerTab.fileList.Update(null);
1540 if(compilerTab.rightPaneHeader.visible)
1541 compilerTab.rightPaneHeader.Update(null);
1542 ((ProjectSettings)master).UpdateDialogTitle();
1547 void SelectNode(ProjectNode node, bool ignoreAsLastSelection)
1549 if(node != currentNode)
1551 Window ac = compilerTab.rightPane.activeChild;
1552 bool prevNodeRes = currentNode ? currentNode.isInResources : false;
1555 if(!node) node = project.topNode;
1557 newNodeRes = node.isInResources;
1560 if(!ignoreAsLastSelection)
1561 lastSelectedNode = node;
1563 ((ProjectSettings)master).UpdateDialogTitle();
1564 if(node.type == project)
1566 compilerTab.rightPaneHeader.visible = false;
1570 compilerTab.rightPaneHeader.id = (int64)node;
1571 compilerTab.rightPaneHeader.Update(null);
1572 compilerTab.rightPaneHeader.visible = true;
1576 DataRow row = compilerTab.fileList.FindSubRow((int64)currentNode);
1579 compilerTab.fileList.currentRow = row;
1580 while((row = row.parent))
1581 row.collapsed = false;
1585 if(prevNodeRes != newNodeRes)
1587 compilerTab.labelObjDir.visible = !newNodeRes;
1588 compilerTab.objDir.visible = !newNodeRes;
1589 compilerTab.excludeFromBuild.visible = !newNodeRes;
1590 compilerTab.labelPreprocessorDefs.visible = !newNodeRes;
1591 compilerTab.preprocessorDefs.visible = !newNodeRes;
1592 compilerTab.labelDefaultNameSpace.visible = !newNodeRes;
1593 compilerTab.defaultNameSpace.visible = !newNodeRes;
1594 compilerTab.strictNameSpaces.visible = !newNodeRes;
1595 compilerTab.memoryGuard.visible = !newNodeRes;
1596 compilerTab.noLineNumbers.visible = !newNodeRes;
1597 compilerTab.debug.visible = !newNodeRes;
1598 compilerTab.labelWarnings.visible = !newNodeRes;
1599 compilerTab.warnings.visible = !newNodeRes;
1600 compilerTab.profiling.visible = !newNodeRes;
1601 compilerTab.labelOptimization.visible = !newNodeRes;
1602 compilerTab.optimization.visible = !newNodeRes;
1603 compilerTab.fastMath.visible = !newNodeRes;
1604 compilerTab.labelIncludeDirs.visible = !newNodeRes;
1605 compilerTab.includeDirs.visible = !newNodeRes;
1608 if(node == project.topNode)
1610 compilerTab.objDir.visible = true;
1611 compilerTab.labelObjDir.visible = true;
1613 compilerTab.excludeFromBuild.visible = false;
1617 compilerTab.objDir.visible = false;
1618 compilerTab.labelObjDir.visible = false;
1620 compilerTab.excludeFromBuild.visible = (node != project.resNode);
1623 // Load Settings Into Dialog
1624 compilerTab.LoadSettings();
1625 linkerTab.LoadSettings();
1626 builderTab.LoadSettings();
1632 if(ac == compilerTab.excludeFromBuild.editor)
1633 ac = compilerTab.objDir.editor;
1634 else if(compilerTab.excludeFromBuild.editor.visible)
1635 ac = compilerTab.excludeFromBuild.editor;
1642 void CreateConfigButtons()
1644 SelectorButton commonButton;
1646 // Create Config Buttons
1647 commonButton = SelectorButton
1649 configSelector, master = this, text = $"Common", id = (int64)null; font = { font.faceName, font.size, true };
1651 NotifyClicked = ConfigClicked;
1656 if(project.topNode.configurations)
1658 for(c : project.topNode.configurations)
1660 EditableSelectorButton button
1662 configSelector, master = this, renameable = true, text = c.name, id = (int64)c;
1663 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1672 SelectorButton button;
1674 activeConfigName = project.config ? CopyString(project.config.name) : null;
1676 compilerTab.AddNode(project.topNode, null);
1678 CreateConfigButtons();
1680 platformButton = button =
1682 platformSelector, master = this, text = $"Common", id = 0; font = { font.faceName, font.size, true };
1683 NotifyClicked = PlatformClicked; checked = true;
1688 for(p = (Platform)1; p < Platform::enumSize; p++)
1690 SelectorButton button
1692 platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int64)p;
1693 NotifyClicked = PlatformClicked;
1697 SelectorButton platformButton;
1701 // Backup Current Settings
1702 backupNode = project.topNode.Backup();
1704 buildTabControl.Activate();
1707 Iterator<Window> it { configSelector.controls };
1710 SelectorButton configButton = (SelectorButton)it.data;
1711 ProjectConfig buttonConfig = (ProjectConfig)configButton.id;
1712 if(buttonConfig == project.config)
1714 configButton.Activate();
1715 configButton.checked = true;
1716 ConfigClicked(configButton, 0, 0, (Modifiers)null);
1723 platformButton.MakeActive();
1724 platformButton = null;
1733 lastSelectedNode = null;
1735 project.config = null;
1737 /* // THIS IS NOW AUTOMATED WITH A project CHECK IN ProjectNode
1738 project.configurations = project.topNode.configurations;
1739 project.platforms = project.topNode.platforms;
1740 project.options = project.topNode.options;
1743 if(project.topNode.configurations)
1745 for(c : project.topNode.configurations)
1747 if(!strcmpi(c.name, activeConfigName))
1756 List<ProjectConfig> configs = project.topNode.configurations;
1757 if(configs && configs.count)
1758 project.config = configs[0];
1761 ide.UpdateToolBarActiveConfigs(false);
1764 void RevertChanges()
1766 String configName = config ? CopyString(config.name) : null;
1768 // Revert to saved project options
1769 project.topNode.Revert(backupNode);
1771 configSelector.DestroyChildren();
1772 CreateConfigButtons();
1774 // Reselect Configuration
1777 Iterator<Window> it { configSelector.controls };
1780 Button button = (Button)it.data;
1781 ProjectConfig c = (ProjectConfig)button.id;
1782 if(c && !strcmp(c.name, configName))
1786 button.checked = true;
1787 ConfigClicked(button, 0,0, 0);
1793 SelectNode(project.topNode, false);
1798 bool OnClose(bool parentClosing)
1800 if(modifiedDocument)
1802 DialogResult diagRes = MessageBox
1804 type = yesNoCancel, master = ide,
1805 text = $"Save changes to project settings?",
1806 contents = $"Would you like to save changes made to the build options?"
1810 if(diagRes == cancel)
1814 project.MarkChanges(backupNode);
1815 project.topNode.modified = true;
1816 ide.projectView.modifiedDocument = true;
1817 ide.UpdateToolBarActiveConfigs(false);
1818 ide.projectView.Update(null);
1820 modifiedDocument = false;
1826 class CompilerTab : Tab
1828 background = formColor;
1831 Window leftPane { this, size = { 180 }, anchor = { left = 0, top = 0, bottom = 0 }, background = formColor };
1833 Label labelFileList { leftPane, this, position = { 8, 8 }, labeledWindow = fileList };
1836 leftPane, this, borderStyle = deep, hasVertScroll = true, hasHorzScroll = true;
1837 // THIS WOULD BE EVEN MORE FUN: multiSelect = true,
1838 fullRowSelect = false, collapseControl = true, treeBranches = true;
1839 alwaysHighLight = true;
1840 selectionColor = unfocusedSelectorColor;
1842 anchor = Anchor { left = 8, top = 24, right = 4, bottom = 8 };
1845 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1847 BuildTab buildTab = (BuildTab)master;
1848 ProjectNode node = (ProjectNode)row.tag;
1849 buildTab.SelectNode(node, false);
1853 void OnRedraw(Surface surface)
1855 ide.projectView.drawingInProjectSettingsDialog = true;
1856 ListBox::OnRedraw(surface);
1857 ide.projectView.drawingInProjectSettingsDialog = false;
1860 bool NotifyActivate(Window window, bool active, Window previous)
1864 //subclass(Skin) skinClass = (subclass(Skin))eSystem_FindClass(app, app.skin);
1865 fileList.selectionColor = Color { 10, 36, 106 }; //skinClass.selectionColor; // darkBlue;
1867 else if(fileList.currentRow)
1869 DataRow currentRow = fileList.currentRow;
1870 //int headerSize = ((fileList.style.header) ? fileList.rowHeight : 0);
1871 int height = fileList.clientSize.h + 1;// - fileList.headerSize;
1872 fileList.selectionColor = unfocusedSelectorColor;
1873 if(currentRow && currentRow.index * fileList.rowHeight > fileList.scroll.y + height - fileList.rowHeight)
1874 fileList.SetScrollPosition(fileList.scroll.x, currentRow.index * fileList.rowHeight - height + fileList.rowHeight);
1875 else if(!currentRow || currentRow.index * fileList.rowHeight < fileList.scroll.y)
1876 fileList.SetScrollPosition(fileList.scroll.x, currentRow ? currentRow.index * fileList.rowHeight : 0);
1886 this, anchor = { left = 196, top = 0, right = 0, bottom = 0 }, background = formColor, tabCycle = true;
1889 Window rightPaneHeader
1891 rightPane, this, size = { h = 21 }, anchor = { left = 0, top = 0, right = 0 }, background = Color { 70, 96, 166 };//0x0F3F66;
1892 foreground = white; visible = false;
1894 void OnRedraw(Surface surface)
1898 ide.projectView.drawingInProjectSettingsDialogHeader = true;
1899 ((void (*)(void *, void *, void *, int, int, int, void *, uint, uint))(void *)class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay])(class(ProjectNode),
1900 (void *)id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
1901 ide.projectView.drawingInProjectSettingsDialogHeader = false;
1906 PaneSplitter splitter
1908 this, leftPane = leftPane, rightPane = rightPane, split = 188
1911 Label labelObjDir { rightPane, this, position = { 8, 8 }, labeledWindow = objDir };
1912 PathOptionBox objDir
1914 rightPane, this, size = { 250, 22 }, anchor = { left = 8, top = 24, right = 8 };
1915 text = $"Intermediate Objects Directory", hotKey = altJ, option = OPTION(objectsDirectory);
1918 BoolOptionBox excludeFromBuild
1920 rightPane, this, position = { 8, 28 },
1921 text = $"Exclude from Build", visible = false, option = OPTION(excludeFromBuild);
1924 Label labelPreprocessorDefs { rightPane, this, position = { 8, 50 }, labeledWindow = preprocessorDefs };
1925 StringArrayOptionBox preprocessorDefs
1927 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
1928 text = $"Preprocessor Definitions", hotKey = altD, option = OPTION(preprocessorDefinitions);
1931 Label labelDefaultNameSpace { rightPane, this, position = { 8, 92 }, labeledWindow = defaultNameSpace };
1932 StringOptionBox defaultNameSpace
1934 rightPane, this, size = { 160, 22 }, position = { 8, 108 };
1935 text = $"Default Name Space", option = OPTION(defaultNameSpace);
1937 BoolOptionBox strictNameSpaces
1939 rightPane, this, position = { 172, 112 },
1940 text = $"Strict Name Spaces", option = OPTION(strictNameSpaces);
1943 BoolOptionBox fastMath
1945 rightPane, this, position = { 316, 112 },
1946 text = $"Fast Math", option = OPTION(fastMath);
1949 BoolOptionBox memoryGuard
1951 rightPane, this, position = { 8, 154 };
1952 text = $"MemoryGuard", hotKey = altM, option = OPTION(memoryGuard);
1955 Label labelWarnings { rightPane, position = { 116, 138 }, labeledWindow = warnings };
1958 rightPane, this, position = { 116, 154 };
1959 text = $"Warnings", hotKey = altW, option = OPTION(warnings);
1962 Label labelOptimization { rightPane, position = { 220, 138 }, labeledWindow = optimization };
1963 OptimizationDB optimization
1965 rightPane, this, position = { 220, 154 }, size = { 120, 22 };
1966 text = $"Optimization", hotKey = altO, option = OPTION(optimization);
1971 rightPane, this, position = { 8, 188 };
1972 text = $"Debuggable", hotKey = altG, option = OPTION(debug);
1975 BoolOptionBox profiling
1977 rightPane, this, position = { 116, 188 };
1978 text = $"Profiling Data", hotKey = altP, option = OPTION(profile);
1981 BoolOptionBox noLineNumbers
1983 rightPane, this, position = { 220, 188 };
1984 text = $"No Line Numbers", hotKey = altN, option = OPTION(noLineNumbers);
1987 Label labelCompilerOptions { rightPane, this, position = { 8, 208 }, labeledWindow = compilerOptions };
1988 StringArrayOptionBox compilerOptions
1990 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 224, right = 8 };
1991 text = $"Compiler Options", hotKey = altO, option = OPTION(compilerOptions);
1992 configReplaces = true;
1995 Label labelIncludeDirs { includeDirs.editor, labeledWindow = includeDirs, position = { 0, 6 }; };
1996 DirsArrayOptionBox includeDirs
1998 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 250, right = 8, bottom = 8 };
1999 text = $"Additional Include Directories", hotKey = altI, option = OPTION(includeDirs);
2004 fileList.AddField(DataField { dataType = class(ProjectNode), freeData = false,
2005 userData = null /* Now set in the ProjectNode directly to know we're in ProjectSettings Dialog -- ide.projectView*/ });
2010 BuildTab buildTab = (BuildTab)master;
2011 buildTab.SelectNode(buildTab.lastSelectedNode, true);
2015 void AddNode(ProjectNode node, DataRow addTo)
2017 DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
2019 row.tag = (int64)node;
2021 row.SetData(null, node);
2023 if(node.files && node.files.first && node.parent &&
2024 !(!node.parent.parent &&
2025 (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") ||
2026 !strcmpi(node.name, "src") || !strcmpi(node.name, "tools"))))
2027 row.collapsed = true;
2028 else if(node.type == folder)
2029 node.icon = openFolder;
2033 for(child : node.files)
2034 AddNode(child, row);
2041 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2042 if(eClass_IsDerived(ob._class, class(OptionBox)))
2045 if(activeChild && activeChild.active)
2047 Window control = activeChild;
2048 control.Deactivate();
2055 objDir.editor.Activate();
2060 class LinkerTab : Tab
2062 background = formColor;
2065 Label labelTargetName { this, position = { 8, 8 }, labeledWindow = targetName };
2066 StringOptionBox targetName
2068 this, position = { 8, 24 }, size = { 200, 22 };
2069 text = $"Target Name", hotKey = altN, option = OPTION(targetFileName);
2072 Label labelTargetType { this, position = { 216, 8 }, labeledWindow = targetType };
2073 TargetTypeDB targetType
2075 this, position = { 216, 24 }, size = { 120, 22 };
2076 text = $"Target Type", hotKey = altT, option = OPTION(targetType);
2079 Label labelTargetDirectory { this, position = { 344, 8 }, labeledWindow = targetDirectory };
2080 PathOptionBox targetDirectory
2082 this, size = { 270, 22 }, anchor = { left = 344, top = 24, right = 8 };
2083 hotKey = altR, text = $"Target Directory", option = OPTION(targetDirectory);
2086 Label labelLibraries { this, position = { 8, 50 }, labeledWindow = libraries };
2087 StringArrayOptionBox libraries
2089 this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
2090 text = $"Additional Libraries", hotKey = altL, option = OPTION(libraries);
2091 configReplaces = true;
2094 Label labelLinkerOptions { this, position = { 8, 92 }, labeledWindow = linkerOptions };
2095 StringArrayOptionBox linkerOptions
2097 this, size = { 290, 22 }, anchor = { left = 8, top = 108, right = 8 };
2098 text = $"Linker Options", hotKey = altO, option = OPTION(linkerOptions);
2099 configReplaces = true;
2102 BoolOptionBox console
2104 this, position = { 8, 138 };
2105 text = $"Console Application", hotKey = altC, option = OPTION(console);
2108 BoolOptionBox compress
2110 this, position = { 8, 162 };
2111 text = $"Compress", hotKey = altW, option = OPTION(compress);
2114 Label labelLibraryDirs { libraryDirs.editor, labeledWindow = libraryDirs, position = { 0, 6 }; };
2115 DirsArrayOptionBox libraryDirs
2117 this, size = { 290, 22 }, anchor = { left = 8, top = 182, right = 8, bottom = 8 };
2118 text = $"Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs);
2123 ((BuildTab)master).SelectNode(project.topNode, true);
2130 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2131 if(eClass_IsDerived(ob._class, class(OptionBox)))
2133 compress.disabled = (config && config.options && config.options.debug == true) || project.topNode.options.debug == true;
2135 if(activeChild && activeChild.active)
2137 Window control = activeChild;
2138 control.Deactivate();
2144 class BuilderTab : Tab
2146 background = formColor;
2149 Label labelPrebuildCommands { prebuildCommands.editor, labeledWindow = prebuildCommands, position = { 0, 6 }; };
2150 StringsArrayOptionBox prebuildCommands
2152 this, size = { 290, 100 }, anchor = { left = 8, top = 8, right = 8, bottom = 0.5 };
2153 text = $"Pre-build Commands", hotKey = altE, option = OPTION(prebuildCommands);
2156 Label labelPostbuildCommands { postbuildCommands.editor, labeledWindow = postbuildCommands, position = { 0, 6 }; };
2157 StringsArrayOptionBox postbuildCommands
2159 this, size = { 290 }, anchor = { left = 8, top = 0.5, right = 8, bottom = 8 };
2160 text = $"Post-build Commands", hotKey = altT, option = OPTION(postbuildCommands);
2165 bool disabled = strlen(((BuildTab)master).selectedPlatformName) > 0;
2167 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2168 if(eClass_IsDerived(ob._class, class(OptionBox)))
2171 if(activeChild && activeChild.active)
2173 Window control = activeChild;
2174 control.Deactivate();