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
34 bool quoted = strchr(item, ' ') != null;
48 Array<String> array { };
50 char * contents = property::contents;
54 for(c = 0; (ch = contents[c]); c++)
56 if(ch == ' ' && !quoted)
59 array.Add(MakeString(contents + start, c - start));
67 array.Add(MakeString(contents + start, c - start));
79 array.Add(MakeString(contents + start, c - start));
85 define dialogTitle = $"Project Settings";
86 static Color unfocusedSelectorColor { 70, 96, 166 };
87 class ProjectSettings : Window
90 background = activeBorder;
91 borderStyle = sizable;
92 minClientSize = { 650, 490 };
97 property Project project
102 projectTab.project = value;
105 buildTab.SelectNode(project.topNode, false);
107 if(project && project.topNode && project.topNode.name && project.topNode.name[0])
110 get { return ::project; }
113 property ProjectNode projectNode
115 set { buildTab.SelectNode(value, false); }
116 get { return currentNode; }
119 void UpdateDialogTitle()
121 //char * s = PrintString("Project Settings - ", project.topNode.fileName);
123 char * projectName = new char[strlen(project.topNode.name) + 1];
124 char * nodeName = currentNode && currentNode != project.topNode ? currentNode.name : "";
125 char * config = buildTab.selectedConfigName;
126 char * platform = buildTab.selectedPlatformName;
127 char * label = new char[strlen(dialogTitle) + 3 + strlen(project.topNode.name) + 3 +
128 strlen(nodeName) + 2 + strlen(config) + 1 + strlen(platform) + 1 + 1];
129 strcpy(label, dialogTitle);
130 strcat(label, " - ");
131 strcpy(projectName, project.topNode.name);
132 StripExtension(projectName);
133 strcat(label, projectName);
134 if(currentNode && currentNode.type != project)
136 strcat(label, " - ");
137 strcat(label, nodeName);
139 if(strlen(config) || strlen(platform))
143 strcat(label, config);
144 if(strlen(config) && strlen(platform))
147 strcat(label, platform);
160 TabControl prjTabControl
162 this, background = activeBorder, anchor = { left = 8, top = 4, right = 8, bottom = 38 };
164 ProjectTab projectTab { this, tabControl = prjTabControl };
165 BuildTab buildTab { this, tabControl = prjTabControl };
166 WorkspaceTab workspaceTab { this, tabControl = prjTabControl };
170 this, size = { 80, 22 };
171 anchor = { right = 8, bottom = 8 };
172 text = $"Cancel", hotKey = escape, id = DialogResult::cancel;
174 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
176 if(prjTabControl.curTab.modifiedDocument)
178 DialogResult diagRes = MessageBox
180 type = okCancel, master = ide,
181 text = $"Lose Changes?",
182 contents = $"Are you sure you wish to discard changes made to the build options?"
186 if(prjTabControl.curTab == buildTab)
188 buildTab.RevertChanges();
189 buildTab.modifiedDocument = false;
191 if(prjTabControl.curTab == workspaceTab)
193 workspaceTab.modifiedDocument = false;
195 if(prjTabControl.curTab == projectTab)
197 projectTab.modifiedDocument = false;
199 Destroy(DialogResult::cancel);
203 Destroy(DialogResult::cancel);
209 this, size = { 80, 22 };
210 anchor = { right = 96, bottom = 8 };
211 text = $"OK", isDefault = true;
213 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
215 if(prjTabControl.curTab == buildTab && buildTab.modifiedDocument)
217 buildTab.modifiedDocument = false;
219 project.topNode.modified = true;
220 project.MarkChanges(buildTab.backupNode);
221 ide.projectView.modifiedDocument = true;
222 ide.projectView.Update(null);
224 if(prjTabControl.curTab == workspaceTab && workspaceTab.modifiedDocument)
226 workspaceTab.SaveChanges();
227 workspaceTab.modifiedDocument = false;
229 if(prjTabControl.curTab == projectTab && projectTab.modifiedDocument)
231 projectTab.SaveChanges();
232 projectTab.modifiedDocument = false;
234 Destroy(DialogResult::ok);
242 prjTabControl.curTab = buildTab;
247 #define OPTION(x) ((uint)(&((ProjectOptions)0).x))
249 // TOFIX: USING T INSTEAD OF Z HERE CAUSED US SOME CONFLICTS WITH T IN Array TEMPLATES
251 class OptionBox<class Z> : CommonControl
253 bool mergeValues, configReplaces;
262 property Window editor
268 editor.OnRightButtonDown = OptionBox_OnRightButtonDown;
269 chainKeyDown = (void *)editor.OnKeyDown;
270 editor.OnKeyDown = OptionBox_OnKeyDown;
274 property bool visible { set { editor.visible = value; } get { return editor.visible; } }
275 property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int)this; } }
276 property Point position { set { editor.position = value; } }
277 property Size size { set { editor.size = value; } }
278 property Anchor anchor { set { editor.anchor = value; } }
279 property Key hotKey { set { editor.hotKey = value; } }
280 property char * text { set { editor.text = value; Window::text = value; } }
290 bool NotifySelect(MenuItem selection, Modifiers mods)
292 OptionBox ob = (OptionBox)id;
298 bool Window::OptionBox_OnRightButtonDown(int x, int y, Modifiers mods)
300 OptionBox ob = (OptionBox)id;
301 GuiApplication app = ((GuiApplication)__thisModule.application);
303 PopupMenu { null, this, menu = ob.clearMenu,
304 position = { absPosition.x + clientStart.x + x - app.desktop.position.x, absPosition.y + clientStart.y + y - app.desktop.position.y } }.Create();
308 bool Window::OptionBox_OnKeyDown(Key key, unichar ch)
310 OptionBox ob = (OptionBox)id;
311 if(key == Key { del, ctrl = true } || key == Key { keyPadDelete, ctrl = true })
316 return (((bool(*)(Window, Key, unichar)) ob.chainKeyDown)(this, key, ch);
319 void SetAttribs(int code)
324 for(c = Window::parent.firstChild; c; c = c.next)
326 if(eClass_IsDerived(c._class, class(Label)))
329 if(label.labeledWindow == this)
337 for(c = editor.firstChild; c; c = c.next)
339 if(eClass_IsDerived(c._class, class(Label)))
346 // control.foreground = foreground;
348 if(code == 0 || code == 1)
350 editor.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
351 editor.background = white;
355 Color foreground = 0x0F3F66;
356 int r = foreground.r, g = foreground.g, b = foreground.b;
360 editor.font = { editor.font.faceName, editor.font.size };
362 r = (int)(alpha * r + src.r * (1 - alpha));
363 g = (int)(alpha * g + src.g * (1 - alpha));
364 b = (int)(alpha * b + src.b * (1 - alpha));
366 r = Max(0,Min(255,r));
367 g = Max(0,Min(255,g));
368 b = Max(0,Min(255,b));
370 editor.background = Color { (byte) r, (byte) g, (byte) b };
375 label.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
376 //label.foreground = foreground;
380 virtual void FinalizeLoading();
382 virtual void LoadOption(ProjectOptions options);
383 virtual void RetrieveOption(ProjectOptions options, bool isCfgOrPlt);
384 virtual void UnsetOption(ProjectOptions options)
387 *(Z*)((byte *)options + option) = value;
390 virtual bool OptionSet(ProjectOptions options)
392 // TOFIX: If you get a crash here, it might be because JSON.ec must be after ProjectConfig.ec in the project files
393 // JSON.ec must also be before ProjectSettings.ec in the project files
394 if(*(Z*)((byte *)options + option))
398 // BUG: OptionCheck = OptionSet; // Overrides derived classes OptionCheck ?
400 virtual bool OptionCheck(ProjectOptions options)
402 return OptionSet(options);
405 void MarkBuildTabModified()
407 BuildTab buildTab = (BuildTab)master;
408 while(buildTab && buildTab._class != class(BuildTab))
409 buildTab = (BuildTab)buildTab.master;
410 if(buildTab) buildTab.modifiedDocument = true;
415 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
416 MarkBuildTabModified();
420 ProjectConfig c = null;
421 if(currentNode.configurations)
423 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
428 PlatformOptions p = null;
431 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
434 if(p.options && OptionSet(p.options))
435 UnsetOption(p.options);
436 if(p.options && p.options.isEmpty)
440 Iterator<PlatformOptions> it { c.platforms };
448 if(!c.platforms.count)
454 if(c.options && OptionSet(c.options))
455 UnsetOption(c.options);
456 if(c.options && c.options.isEmpty)
459 // DON'T DELETE PROJECT CONFIGS HERE!
460 if(!c.options && currentNode != project.topNode)
462 Iterator<ProjectConfig> it { currentNode.configurations };
470 if(!currentNode.configurations.count)
471 currentNode.configurations = null;
478 PlatformOptions p = null;
479 if(currentNode.platforms)
481 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
484 if(p.options && OptionSet(p.options))
485 UnsetOption(p.options);
486 if(p.options && p.options.isEmpty)
490 Iterator<PlatformOptions> it { currentNode.platforms };
498 if(!currentNode.platforms.count)
499 currentNode.platforms = null;
505 if(currentNode.options && OptionSet(currentNode.options))
506 UnsetOption(currentNode.options);
507 if(currentNode.options && currentNode.options.isEmpty)
509 // delete currentNode.options;
510 // Property will free:
511 currentNode.options = null;
517 void FigureOutInherited()
520 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
521 bool skipped = false;
522 for(node = currentNode; node; node = node.parent)
524 if(config && node.configurations)
526 for(c : node.configurations; !strcmpi(c.name, config.name))
528 if(platform && c.platforms)
530 for(p : c.platforms; !strcmpi(p.name, platformName))
532 if(skipped && p.options && OptionSet(p.options))
533 LoadOption(p.options);
539 if(skipped && c.options && OptionSet(c.options))
541 LoadOption(c.options);
542 if(configReplaces) return;
548 if(platform && node.platforms)
550 for(p : node.platforms; !strcmpi(p.name, platformName))
552 if(skipped && p.options && OptionSet(p.options))
553 LoadOption(p.options);
558 if(skipped && node.options && OptionSet(node.options))
559 LoadOption(node.options);
560 else if(skipped && !node.parent)
568 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
569 MarkBuildTabModified();
572 ProjectConfig c = null;
573 if(!currentNode.configurations) currentNode.configurations = { };
574 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
576 currentNode.configurations.Add(c = ProjectConfig { name = CopyString(config.name) });
579 PlatformOptions p = null;
580 if(!c.platforms) c.platforms = { };
582 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
584 c.platforms.Add(p = PlatformOptions { CopyString(platformName) });
586 if(!p.options) p.options = { };
587 RetrieveOption(p.options, true);
588 if(!mergeValues) SetAttribs(1);
591 if(!c.options) c.options = { };
592 RetrieveOption(c.options, true);
593 if(!mergeValues) SetAttribs(1);
598 PlatformOptions p = null;
599 if(!currentNode.platforms) currentNode.platforms = { };
600 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
602 currentNode.platforms.Add(p = PlatformOptions { CopyString(platformName) });
604 if(!p.options) p.options = { };
605 RetrieveOption(p.options, true);
606 if(!mergeValues) SetAttribs(1);
610 if(!currentNode.options) currentNode.options = { };
611 RetrieveOption(currentNode.options, false);
612 if(!mergeValues) SetAttribs((currentNode.parent || OptionCheck(currentNode.options)) ? 1 : 0);
618 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
619 bool setAttribs = false;
620 for(node = currentNode; node; node = node.parent)
622 ProjectConfig nodeConfig = null;
623 if(config && node.configurations)
625 for(c : node.configurations; !strcmpi(c.name, config.name))
627 if(platform && c.platforms)
629 for(p : c.platforms; !strcmpi(p.name, platformName))
631 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
633 LoadOption(p.options);
634 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode) ? 1 : 2); }
635 if(!mergeValues) { FinalizeLoading(); return; }
645 if(platform && node.platforms)
647 for(p : node.platforms; !strcmpi(p.name, platformName))
649 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
651 LoadOption(p.options);
652 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config) ? 1 : 2); }
653 if(!mergeValues) { FinalizeLoading(); return; }
659 if(nodeConfig && nodeConfig.options && ((mergeValues && !configReplaces) ? OptionCheck(nodeConfig.options) : OptionSet(nodeConfig.options)))
661 LoadOption(nodeConfig.options);
662 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !platform) ? 1 : 2); }
663 if(!mergeValues || configReplaces) { FinalizeLoading(); return; }
666 if(node.options && (mergeValues ? OptionCheck(node.options) : OptionSet(node.options)))
668 LoadOption(node.options);
669 if(!node.parent && !OptionCheck(node.options))
671 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
675 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config && !platform) ? 1 : 2); }
677 if(!mergeValues) { FinalizeLoading(); return; }
679 else if(!node.parent)
682 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
683 if(!mergeValues) { FinalizeLoading(); return; }
690 class StringOptionBox : OptionBox<String>
694 bool NotifyModified(EditBox editBox)
696 ((OptionBox)editBox.id).Retrieve();
700 textHorzScroll = true;
703 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
705 String * string = (String*)((byte *)options + option);
706 if(*string) delete *string;
707 *string = CopyString(((EditBox)editor).contents);
710 void LoadOption(ProjectOptions options)
712 ((EditBox)editor).contents = options ? *(String*)((byte *)options + option) : "";
713 ((EditBox)editor).Deselect();
716 bool OptionCheck(ProjectOptions options)
718 String string = *(String*)((byte *)options + option);
719 return string && string[0];
722 void UnsetOption(ProjectOptions options)
724 delete *(String*)((byte *)options + option);
728 class PathOptionBox : OptionBox<String>
730 bool Window::EditBoxORB(int x, int y, Modifiers mods)
732 Window parent = this.parent;
733 x += clientStart.x + position.x;
734 y += clientStart.y + position.y;
735 return ((OptionBox)this).OptionBox_OnRightButtonDown(parent, x, y, mods);
740 typeExpected = directory, browseDialog = { };
741 editBox.OnRightButtonDown = (void *)EditBoxORB;
743 bool NotifyModified(PathBox pathBox)
745 ((OptionBox)pathBox.id).Retrieve();
750 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
752 String * string = (String*)((byte *)options + option);
753 String slashPath = ((PathBox)editor).slashPath;
754 if(*string) delete *string;
755 *string = CopyString(slashPath);//(slashPath && slashPath[0]) ? CopyString(slashPath) : null;
758 void LoadOption(ProjectOptions options)
760 ((PathBox)editor).path = options ? *(String*)((byte *)options + option) : "";
761 ((PathBox)editor).Deselect();
764 bool OptionCheck(ProjectOptions options)
766 String string = *(String*)((byte *)options + option);
767 return string && string[0];
770 void UnsetOption(ProjectOptions options)
772 delete *(String*)((byte *)options + option);
776 class MultiStringOptionBox : OptionBox<Array<String>>
781 caseSensitive = true;
783 virtual Array<String> GetStrings();
784 virtual void SetStrings(Array<String> value);
786 Array<String> tempStrings;
788 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
790 Array<String> newStrings = GetStrings();
791 Array<String> * strings = (Array<String>*)((byte *)options + option);
792 if(*strings) { strings->Free(); delete *strings; }
796 Iterator<String> it { newStrings };
798 FigureOutInherited();
802 Array<String> ts = tempStrings;
807 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
808 if(found && (!configReplaces || platform)) // ADDED || platform here...
818 *strings = newStrings;
823 void LoadOption(ProjectOptions options)
827 Array<String> strings = options ? *((Array<String>*)((byte *)options + option) : null;
835 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
836 if(!found) tempStrings.Add(s);
842 SetStrings(options ? *(Array<String>*)((byte *)options + option) : null);
846 void FinalizeLoading()
850 SetStrings(tempStrings);
855 bool OptionSet(ProjectOptions options)
857 Array<String> strings = *(Array<String>*)((byte *)options + option);
858 if(mergeValues && !configReplaces)
860 return strings && strings.count;
863 return strings != null;
866 bool OptionCheck(ProjectOptions options)
868 Array<String> strings = *(Array<String>*)((byte *)options + option);
869 return strings && strings.count;
872 void UnsetOption(ProjectOptions options)
874 Array<String> * strings = (Array<String>*)((byte *)options + option);
875 if(*strings) { strings->Free(); delete *strings; }
879 class StringArrayOptionBox : MultiStringOptionBox
881 editor = StringListBox
883 bool NotifyModified(EditBox editBox)
885 ((OptionBox)editBox.id).Retrieve();
890 // NO VIRTUAL PROPERTIES YET...
891 Array<String> GetStrings() { return ((StringListBox)editor).strings; }
892 void SetStrings(Array<String> value) { ((StringListBox)editor).strings = value; }
895 class StringsArrayOptionBox : MultiStringOptionBox
905 bool NotifyModified(StringsBox stringsBox)
907 ((OptionBox)stringsBox.id).Retrieve();
912 Array<String> GetStrings() { return ((StringsBox)editor).strings; }
913 void SetStrings(Array<String> value) { ((StringsBox)editor).strings = value; }
916 class DirsArrayOptionBox : MultiStringOptionBox
918 editor = DirectoriesBox
920 bool NotifyModified(DirectoriesBox dirsBox)
922 ((OptionBox)dirsBox.id).Retrieve();
926 bool OnChangedDir(char * * directory)
928 char fixedDirectory[MAX_LOCATION] = "";
929 if(PathCat(fixedDirectory, *directory))
931 char cwdBackup[MAX_LOCATION];
934 GetWorkingDir(cwdBackup, sizeof(cwdBackup));
935 ChangeWorkingDir(project.topNode.path);
937 FileFixCase(fixedDirectory);
939 ChangeWorkingDir(cwdBackup);
941 *directory = CopyString(fixedDirectory);
947 bool OnPrepareBrowseDir(char * * directory)
949 char dir[MAX_LOCATION];
952 GetSystemPathBuffer(dir, project.topNode.path);
954 PathCat(dir, *directory);
957 strcpy(dir, *directory);
962 *directory = CopyString(dir);
964 // GCC 4.4 bug: ----- path becomes *directory
965 //strcpy(dir, path ? path : "");
969 bool OnBrowsedDir(char * * directory)
973 char path[MAX_LOCATION];
974 MakePathRelative(*directory, project.topNode.path, path);
976 *directory = CopyString(path);
982 Array<String> GetStrings() { return ((DirectoriesBox)editor).strings; }
983 void SetStrings(Array<String> value) { ((DirectoriesBox)editor).strings = value; }
986 class BoolOptionBox : OptionBox<SetBool>
992 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
994 ((OptionBox)button.id).Retrieve();
999 bool OptionCheck(ProjectOptions options)
1001 return *(SetBool*)((byte *)options + option) == true;
1004 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1006 bool checked = ((Button)editor).checked;
1007 *(SetBool*)((byte *)options + option) = checked ? true :
1008 ((currentNode.parent || isCfgOrPlt) ? false : unset);
1011 void LoadOption(ProjectOptions options)
1013 ((Button)editor).checked = options && (*(SetBool*)((byte *)options + option) == true);
1017 class DropOptionBox : OptionBox
1021 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
1023 ((OptionBox)dropBox.id).Retrieve();
1028 void LoadOption(ProjectOptions options)
1030 DropBox dropBox = (DropBox)editor;
1031 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1032 dropBox.currentRow = value ? dropBox.FindRow((int)value) : dropBox.firstRow;
1035 void RetrieveOption(ProjectOptions options, bool isCfgOrPlt)
1037 DropBox dropBox = (DropBox)editor;
1038 DataRow row = dropBox.currentRow;
1039 Z value = (Z)(row ? row.tag : 0);
1040 *(Z*)((byte *)options + option) = value;
1044 class TargetTypeDB : DropOptionBox<TargetTypes>
1050 row = ((DropBox)editor).AddRow();
1051 row.tag = TargetTypes::executable;
1052 row.SetData(null, $"Executable");
1054 row = ((DropBox)editor).AddRow();
1055 row.tag = TargetTypes::sharedLibrary;
1056 row.SetData(null, $"Shared Library");
1058 row = ((DropBox)editor).AddRow();
1059 row.tag = TargetTypes::staticLibrary;
1060 row.SetData(null, $"Static Library");
1063 bool OptionCheck(ProjectOptions options)
1065 TargetTypes value = *(TargetTypes*)((byte *)options + option);
1066 return value && value != executable;
1070 class OptimizationDB : DropOptionBox<OptimizationStrategy>
1075 row = ((DropBox)editor).AddRow();
1076 row.tag = OptimizationStrategy::none;
1077 row.SetData(null, $"None");
1079 row = ((DropBox)editor).AddRow();
1080 row.tag = OptimizationStrategy::speed;
1081 row.SetData(null, $"For Speed (-O2)");
1083 row = ((DropBox)editor).AddRow();
1084 row.tag = OptimizationStrategy::size;
1085 row.SetData(null, $"For Size (-Os)");
1088 bool OptionCheck(ProjectOptions options)
1090 OptimizationStrategy value = *(OptimizationStrategy*)((byte *)options + option);
1091 return value && value != none;
1095 class WarningsDB : DropOptionBox<WarningsOption>
1100 row = ((DropBox)editor).AddRow();
1101 row.tag = WarningsOption::normal;
1102 row.SetData(null, $"Normal");
1104 row = ((DropBox)editor).AddRow();
1105 row.tag = WarningsOption::none;
1106 row.SetData(null, $"None");
1108 row = ((DropBox)editor).AddRow();
1109 row.tag = WarningsOption::all;
1110 row.SetData(null, $"All");
1113 bool OptionCheck(ProjectOptions options)
1115 WarningsOption value = *(WarningsOption*)((byte *)options + option);
1116 return value && value != none;
1120 void DrawStipple(Surface surface, Size clientSize)
1124 int x2 = clientSize.w - 1;
1125 int y2 = clientSize.h - 1;
1126 if((x2 - x1) & 1) x2--;
1127 if((y2 - y1) & 1) y2--;
1129 surface.LineStipple(0x5555);
1130 surface.Rectangle(x1, y1, x2, y2);
1131 surface.LineStipple(0);
1134 class BuildTab : Tab
1137 background = activeBorder;
1140 ProjectNode backupNode;
1141 String activeConfigName;
1143 ProjectNode lastSelectedNode;
1145 property char * selectedConfigName
1151 SelectorButton button = (SelectorButton)configSelector.selectedButton;
1152 if(button && button.id)
1154 ProjectConfig config = (ProjectConfig)button.id;
1162 property char * selectedPlatformName
1168 SelectorButton button = (SelectorButton)platformSelector.selectedButton;
1169 if(button && button.id)
1171 Platform platform = (Platform)button.id;
1172 char * platformName = platform ? platform.OnGetString(0,0,0) : null; // all these platformName are leaking, no?
1173 return platformName;
1180 Label labelConfigurations
1182 this, anchor = { left = 8, top = 14 }, labeledWindow = configSelector;
1184 void OnRedraw(Surface surface)
1186 Label::OnRedraw(surface);
1187 if(labeledWindow.active) DrawStipple(surface, clientSize);
1190 SelectorBar configSelector
1192 this, text = $"Configurations: ", anchor = { left = 98, top = 8, right = 54 }; size = { 0, 26 };
1194 direction = horizontal, scrollable = true;
1196 bool OnKeyDown(Key key, unichar ch)
1200 ((BuildTab)parent).createConfig.NotifyClicked(parent, ((BuildTab)parent).createConfig, 0, 0, 0);
1205 ((BuildTab)parent).deleteConfig.NotifyClicked(parent, ((BuildTab)parent).deleteConfig, 0, 0, 0);
1208 return SelectorBar::OnKeyDown(key, ch);
1211 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1213 ((BuildTab)master).labelConfigurations.Update(null);
1220 parent = this, bevelOver = true, inactive = true;
1222 anchor = { top = 10, right = 31 };
1223 hotKey = altC, bitmap = BitmapResource { fileName = ":actions/docNew.png", alphaBlend = true };
1225 bool NotifyClicked(Button b, int x, int y, Modifiers mods)
1227 char tmp[MAX_F_STRING];
1228 ProjectConfig config;
1229 EditableSelectorButton button;
1231 FindUniqueConfigName("NewConfig", false, tmp);
1235 makingModified = true;
1236 compilingModified = true;
1237 linkingModified = true;
1238 name = CopyString(tmp);
1241 // objectsDirectory = /*CopyString(*/defaultObjDirExpression/*)*/;
1244 if(!project.topNode.configurations) project.topNode.configurations = { };
1245 project.topNode.configurations.Add(config);
1247 targetType = project.config.options.targetType;
1249 config.options.targetFileName = project.moduleName;
1250 config.options.targetDir.dir = "";
1251 config.options.objectsDirectory = defaultObjDirExpression);
1252 config.options.debug = true;
1253 config.options.optimization = none;
1254 config.options.warnings = all;
1259 configSelector, renameable = true, master = this, text = config.name, id = (int)config;
1260 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1263 configSelector.Select(button);
1264 modifiedDocument = true;
1268 /*Button duplicateConfig
1270 parent = this, bevelOver = true, inactive = true;
1272 anchor = { top = 10, right = 31 };
1273 hotKey = altU, bitmap = BitmapResource { fileName = ":actions/editCopy.png", alphaBlend = true };
1277 parent = this, bevelOver = true, inactive = true;
1279 anchor = { top = 10, right = 8 };
1280 hotKey = altD, bitmap = BitmapResource { fileName = ":actions/delete2.png", alphaBlend = true };
1282 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1286 String title = PrintString($"Delete ", config.name, $" Configuration");
1287 String msg = PrintString($"Are you sure you wish to delete the ", config.name, $" configuration?");
1288 if(MessageBox { type = okCancel, text = title, contents = msg }.Modal() == ok)
1290 Iterator<Window> it { configSelector.controls };
1291 ProjectConfig configToDelete = config;
1295 SelectorButton button = (SelectorButton)it.data;
1296 if((ProjectConfig)button.id == config)
1298 button.visible = false;
1303 button = (SelectorButton)it.data;
1304 config = (ProjectConfig)button.id;
1305 configSelector.Select(button);
1311 SelectorButton button = configSelector.FindButtonByID((int)configToDelete);
1313 configSelector.RemoveButton(button);
1315 project.topNode.DeleteConfig(configToDelete);
1317 modifiedDocument = true;
1326 Label labelPlatforms
1328 this, anchor = { left = 8, top = 44 }, labeledWindow = platformSelector;
1330 void OnRedraw(Surface surface)
1332 Label::OnRedraw(surface);
1333 if(labeledWindow.active) DrawStipple(surface, clientSize);
1336 SelectorBar platformSelector
1338 this, text = $"Platforms: ", anchor = { left = 64, top = 38, right = 54 }; size = { 0, 26 };
1340 direction = horizontal, scrollable = true;
1342 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1344 ((BuildTab)master).labelPlatforms.Update(null);
1349 TabControl buildTabControl
1351 this, background = activeBorder, anchor = { left = 8, top = 64, right = 8, bottom = 8 };
1352 curTab = compilerTab;
1354 CompilerTab compilerTab { this, tabControl = buildTabControl };
1355 LinkerTab linkerTab { this, tabControl = buildTabControl };
1356 BuilderTab builderTab { this, tabControl = buildTabControl };
1359 this, font = { font.faceName, font.size, italic = true }, stayOnTop = true,
1360 text = $"(Right click or press Ctrl-Del to revert an option to inherited value)", anchor = { top = 72, right = 16 }
1363 void FindUniqueConfigName(char * baseName, bool startWithNumber, char * output)
1366 char tmp[MAX_F_STRING];
1368 sprintf(tmp, "%s%d", baseName, num);
1370 strcpy(tmp, baseName);
1373 ProjectConfig config = null;
1374 for(c : project.topNode.configurations)
1375 { // TOFIX: Error when omitting these brackets, c not found
1376 if(c.name && !strcmp(c.name, tmp))
1385 sprintf(tmp, "%s%d", baseName, num);
1390 strcpy(output, tmp);
1393 bool PlatformClicked(Button clickedButton, int x, int y, Modifiers mods)
1395 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1397 platform = (Platform)clickedButton.id;
1399 // Load Settings Into Dialog
1400 compilerTab.LoadSettings();
1401 linkerTab.LoadSettings();
1402 builderTab.LoadSettings();
1405 buildTabControl.Activate();
1407 if(compilerTab.rightPaneHeader.visible)
1408 compilerTab.rightPaneHeader.Update(null);
1409 ((ProjectSettings)master).UpdateDialogTitle();
1416 platformSelector.DestroyChildren();
1417 configSelector.DestroyChildren();
1419 delete activeConfigName;
1422 bool ConfigOnRename(EditableSelectorButton button, char * * oldName, char * * newName)
1427 for(c = 0; (ch = (*newName)[c]); c++)
1429 if(ch == '_' || isalpha(ch) || (isdigit(ch) && d))
1430 (*newName)[d++] = ch;
1436 for(c : project.topNode.configurations; c != config)
1438 if(!strcmpi(c.name, *newName))
1444 if(found || !(*newName)[0])
1446 char tmp[MAX_F_STRING];
1447 char * tmpName = config.name;
1449 FindUniqueConfigName("NewConfig", false, tmp);
1450 config.name = tmpName;
1452 *newName = CopyString(tmp);
1456 if(activeConfigName && !strcmp(activeConfigName, *oldName))
1458 delete activeConfigName;
1459 activeConfigName = CopyString(*newName);
1462 project.topNode.RenameConfig(config.name, *newName);
1464 modifiedDocument = true;
1468 bool ConfigClicked(Button clickedButton, int x, int y, Modifiers mods)
1470 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1472 config = (ProjectConfig)clickedButton.id;
1474 // Load Settings Into Dialog
1475 compilerTab.LoadSettings();
1476 linkerTab.LoadSettings();
1477 builderTab.LoadSettings();
1479 deleteConfig.disabled = (clickedButton._class == class(SelectorButton));
1482 buildTabControl.Activate();
1484 if(compilerTab.rightPaneHeader.visible)
1485 compilerTab.rightPaneHeader.Update(null);
1486 ((ProjectSettings)master).UpdateDialogTitle();
1491 void SelectNode(ProjectNode node, bool ignoreAsLastSelection)
1493 if(node != currentNode)
1495 Window ac = compilerTab.rightPane.activeChild;
1496 bool prevNodeRes = currentNode ? currentNode.isInResources : false;
1499 if(!node) node = project.topNode;
1501 newNodeRes = node.isInResources;
1504 if(!ignoreAsLastSelection)
1505 lastSelectedNode = node;
1507 ((ProjectSettings)master).UpdateDialogTitle();
1508 if(node.type == project)
1510 compilerTab.rightPaneHeader.visible = false;
1514 compilerTab.rightPaneHeader.id = (int)node;
1515 compilerTab.rightPaneHeader.Update(null);
1516 compilerTab.rightPaneHeader.visible = true;
1520 DataRow row = compilerTab.fileList.FindSubRow((int)currentNode);
1523 compilerTab.fileList.currentRow = row;
1524 while((row = row.parent))
1525 row.collapsed = false;
1529 if(prevNodeRes != newNodeRes)
1531 compilerTab.labelObjDir.visible = !newNodeRes;
1532 compilerTab.objDir.visible = !newNodeRes;
1533 compilerTab.excludeFromBuild.visible = !newNodeRes;
1534 compilerTab.labelPreprocessorDefs.visible = !newNodeRes;
1535 compilerTab.preprocessorDefs.visible = !newNodeRes;
1536 compilerTab.labelDefaultNameSpace.visible = !newNodeRes;
1537 compilerTab.defaultNameSpace.visible = !newNodeRes;
1538 compilerTab.strictNameSpaces.visible = !newNodeRes;
1539 compilerTab.memoryGuard.visible = !newNodeRes;
1540 compilerTab.noLineNumbers.visible = !newNodeRes;
1541 compilerTab.debug.visible = !newNodeRes;
1542 compilerTab.labelWarnings.visible = !newNodeRes;
1543 compilerTab.warnings.visible = !newNodeRes;
1544 compilerTab.profiling.visible = !newNodeRes;
1545 compilerTab.labelOptimization.visible = !newNodeRes;
1546 compilerTab.optimization.visible = !newNodeRes;
1547 compilerTab.labelIncludeDirs.visible = !newNodeRes;
1548 compilerTab.includeDirs.visible = !newNodeRes;
1551 if(node == project.topNode)
1553 compilerTab.objDir.visible = true;
1554 compilerTab.labelObjDir.visible = true;
1556 compilerTab.excludeFromBuild.visible = false;
1560 compilerTab.objDir.visible = false;
1561 compilerTab.labelObjDir.visible = false;
1563 compilerTab.excludeFromBuild.visible = (node != project.resNode);
1566 // Load Settings Into Dialog
1567 compilerTab.LoadSettings();
1568 linkerTab.LoadSettings();
1569 builderTab.LoadSettings();
1575 if(ac == compilerTab.excludeFromBuild.editor)
1576 ac = compilerTab.objDir.editor;
1577 else if(compilerTab.excludeFromBuild.editor.visible)
1578 ac = compilerTab.excludeFromBuild.editor;
1585 void CreateConfigButtons()
1587 SelectorButton commonButton;
1589 // Create Config Buttons
1590 commonButton = SelectorButton
1592 configSelector, master = this, text = $"Common", id = (int)null; font = { font.faceName, font.size, true };
1594 NotifyClicked = ConfigClicked;
1599 if(project.topNode.configurations)
1601 for(c : project.topNode.configurations)
1603 EditableSelectorButton button
1605 configSelector, master = this, renameable = true, text = c.name, id = (int)c;
1606 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1615 SelectorButton button;
1617 activeConfigName = project.config ? CopyString(project.config.name) : null;
1619 compilerTab.AddNode(project.topNode, null);
1621 CreateConfigButtons();
1623 platformButton = button =
1625 platformSelector, master = this, text = $"Common", id = 0; font = { font.faceName, font.size, true };
1626 NotifyClicked = PlatformClicked; checked = true;
1631 for(p = (Platform)1; p < Platform::enumSize; p++)
1633 SelectorButton button
1635 platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int)p;
1636 NotifyClicked = PlatformClicked;
1640 SelectorButton platformButton;
1644 // Backup Current Settings
1645 backupNode = project.topNode.Backup();
1647 buildTabControl.Activate();
1650 Iterator<Window> it { configSelector.controls };
1653 SelectorButton configButton = (SelectorButton)it.data;
1654 ProjectConfig buttonConfig = (ProjectConfig)configButton.id;
1655 if(buttonConfig == project.config)
1657 configButton.Activate();
1658 configButton.checked = true;
1659 ConfigClicked(configButton, 0, 0, (Modifiers)null);
1666 platformButton.MakeActive();
1667 platformButton = null;
1676 lastSelectedNode = null;
1678 project.config = null;
1680 /* // THIS IS NOW AUTOMATED WITH A project CHECK IN ProjectNode
1681 project.configurations = project.topNode.configurations;
1682 project.platforms = project.topNode.platforms;
1683 project.options = project.topNode.options;
1686 if(project.topNode.configurations)
1688 for(c : project.topNode.configurations)
1690 if(!strcmpi(c.name, activeConfigName))
1699 void RevertChanges()
1701 String configName = config ? CopyString(config.name) : null;
1703 // Revert to saved project options
1704 project.topNode.Revert(backupNode);
1706 configSelector.DestroyChildren();
1707 CreateConfigButtons();
1709 // Reselect Configuration
1712 Iterator<Window> it { configSelector.controls };
1715 Button button = (Button)it.data;
1716 ProjectConfig c = (ProjectConfig)button.id;
1717 if(c && !strcmp(c.name, configName))
1721 button.checked = true;
1722 ConfigClicked(button, 0,0, 0);
1728 SelectNode(project.topNode, false);
1733 bool OnClose(bool parentClosing)
1735 if(modifiedDocument)
1737 DialogResult diagRes = MessageBox
1739 type = yesNoCancel, master = ide,
1740 text = $"Save changes to project settings?",
1741 contents = $"Would you like to save changes made to the build options?"
1745 if(diagRes == cancel)
1749 project.MarkChanges(backupNode);
1750 project.topNode.modified = true;
1751 ide.projectView.modifiedDocument = true;
1752 ide.projectView.Update(null);
1754 modifiedDocument = false;
1760 class CompilerTab : Tab
1762 background = activeBorder;
1765 Window leftPane { this, size = { 180 }, anchor = { left = 0, top = 0, bottom = 0 }, background = activeBorder };
1767 Label labelFileList { leftPane, this, position = { 8, 8 }, labeledWindow = fileList };
1770 leftPane, this, borderStyle = deep, hasVertScroll = true, hasHorzScroll = true;
1771 // THIS WOULD BE EVEN MORE FUN: multiSelect = true,
1772 fullRowSelect = false, collapseControl = true, treeBranches = true;
1773 alwaysHighLight = true;
1774 selectionColor = unfocusedSelectorColor;
1776 anchor = Anchor { left = 8, top = 24, right = 4, bottom = 8 };
1779 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1781 BuildTab buildTab = (BuildTab)master;
1782 ProjectNode node = (ProjectNode)row.tag;
1783 buildTab.SelectNode(node, false);
1787 void OnRedraw(Surface surface)
1789 ide.projectView.drawingInProjectSettingsDialog = true;
1790 ListBox::OnRedraw(surface);
1791 ide.projectView.drawingInProjectSettingsDialog = false;
1794 bool NotifyActivate(Window window, bool active, Window previous)
1798 //subclass(Skin) skinClass = (subclass(Skin))eSystem_FindClass(app, app.skin);
1799 fileList.selectionColor = Color { 10, 36, 106 }; //skinClass.selectionColor; // darkBlue;
1801 else if(fileList.currentRow)
1803 DataRow currentRow = fileList.currentRow;
1804 //int headerSize = ((fileList.style.header) ? fileList.rowHeight : 0);
1805 int height = fileList.clientSize.h + 1;// - fileList.headerSize;
1806 fileList.selectionColor = unfocusedSelectorColor;
1807 if(currentRow && currentRow.index * fileList.rowHeight > fileList.scroll.y + height - fileList.rowHeight)
1808 fileList.SetScrollPosition(fileList.scroll.x, currentRow.index * fileList.rowHeight - height + fileList.rowHeight);
1809 else if(!currentRow || currentRow.index * fileList.rowHeight < fileList.scroll.y)
1810 fileList.SetScrollPosition(fileList.scroll.x, currentRow ? currentRow.index * fileList.rowHeight : 0);
1820 this, anchor = { left = 196, top = 0, right = 0, bottom = 0 }, background = activeBorder, tabCycle = true;
1823 Window rightPaneHeader
1825 rightPane, this, size = { h = 21 }, anchor = { left = 0, top = 0, right = 0 }, background = Color { 70, 96, 166 };//0x0F3F66;
1826 foreground = white; visible = false;
1828 void OnRedraw(Surface surface)
1832 ide.projectView.drawingInProjectSettingsDialogHeader = true;
1833 class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay](class(ProjectNode),
1834 id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
1835 ide.projectView.drawingInProjectSettingsDialogHeader = false;
1840 PaneSplitter splitter
1842 this, leftPane = leftPane, rightPane = rightPane, split = 188
1845 Label labelObjDir { rightPane, this, position = { 8, 8 }, labeledWindow = objDir };
1846 PathOptionBox objDir
1848 rightPane, this, size = { 250, 22 }, anchor = { left = 8, top = 24, right = 8 };
1849 text = $"Intermediate Objects Directory", hotKey = altJ, option = OPTION(objectsDirectory);
1852 BoolOptionBox excludeFromBuild
1854 rightPane, this, position = { 8, 28 },
1855 text = $"Exclude from Build", visible = false, option = OPTION(excludeFromBuild);
1858 Label labelPreprocessorDefs { rightPane, this, position = { 8, 50 }, labeledWindow = preprocessorDefs };
1859 StringArrayOptionBox preprocessorDefs
1861 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
1862 text = $"Preprocessor Definitions", hotKey = altD, option = OPTION(preprocessorDefinitions);
1865 Label labelDefaultNameSpace { rightPane, this, position = { 8, 92 }, labeledWindow = defaultNameSpace };
1866 StringOptionBox defaultNameSpace
1868 rightPane, this, size = { 160, 22 }, position = { 8, 108 };
1869 text = $"Default Name Space", option = OPTION(defaultNameSpace);
1871 BoolOptionBox strictNameSpaces
1873 rightPane, this, position = { 172, 112 },
1874 text = $"Strict Name Spaces", option = OPTION(strictNameSpaces);
1877 BoolOptionBox memoryGuard
1879 rightPane, this, position = { 8, 154 };
1880 text = $"MemoryGuard", hotKey = altM, option = OPTION(memoryGuard);
1883 Label labelWarnings { rightPane, position = { 116, 138 }, labeledWindow = warnings };
1886 rightPane, this, position = { 116, 154 };
1887 text = $"Warnings", hotKey = altW, option = OPTION(warnings);
1890 Label labelOptimization { rightPane, position = { 244, 138 }, labeledWindow = optimization };
1891 OptimizationDB optimization
1893 rightPane, this, position = { 244, 154 }, size = { 120, 22 };
1894 text = $"Optimization", hotKey = altO, option = OPTION(optimization);
1899 rightPane, this, position = { 8, 188 };
1900 text = $"Debuggable", hotKey = altG, option = OPTION(debug);
1903 BoolOptionBox profiling
1905 rightPane, this, position = { 116, 188 };
1906 text = $"Profiling Data", hotKey = altP, option = OPTION(profile);
1909 BoolOptionBox noLineNumbers
1911 rightPane, this, position = { 244, 188 };
1912 text = $"No Line Numbers", hotKey = altN, option = OPTION(noLineNumbers);
1915 Label labelIncludeDirs { includeDirs.editor, labeledWindow = includeDirs, position = { 0, 6 }; };
1916 DirsArrayOptionBox includeDirs
1918 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 208, right = 8, bottom = 8 };
1919 text = $"Additional Include Directories", hotKey = altI, option = OPTION(includeDirs);
1924 fileList.AddField(DataField { dataType = class(ProjectNode), freeData = false,
1925 userData = null /* Now set in the ProjectNode directly to know we're in ProjectSettings Dialog -- ide.projectView*/ });
1930 BuildTab buildTab = (BuildTab)master;
1931 buildTab.SelectNode(buildTab.lastSelectedNode, true);
1935 void AddNode(ProjectNode node, DataRow addTo)
1937 DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
1939 row.tag = (int)node;
1941 row.SetData(null, node);
1943 if(node.files && node.files.first && node.parent &&
1944 !(!node.parent.parent &&
1945 (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") ||
1946 !strcmpi(node.name, "src") || !strcmpi(node.name, "tools"))))
1947 row.collapsed = true;
1948 else if(node.type == folder)
1949 node.icon = openFolder;
1953 for(child : node.files)
1954 AddNode(child, row);
1961 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
1962 if(eClass_IsDerived(ob._class, class(OptionBox)))
1965 if(activeChild && activeChild.active)
1967 Window control = activeChild;
1968 control.Deactivate();
1975 objDir.editor.Activate();
1980 class LinkerTab : Tab
1982 background = activeBorder;
1985 Label labelTargetName { this, position = { 8, 8 }, labeledWindow = targetName };
1986 StringOptionBox targetName
1988 this, position = { 8, 24 }, size = { 200, 22 };
1989 text = $"Target Name", hotKey = altN, option = OPTION(targetFileName);
1992 Label labelTargetType { this, position = { 216, 8 }, labeledWindow = targetType };
1993 TargetTypeDB targetType
1995 this, position = { 216, 24 }, size = { 120, 22 };
1996 text = $"Target Type", hotKey = altT, option = OPTION(targetType);
1999 Label labelTargetDirectory { this, position = { 344, 8 }, labeledWindow = targetDirectory };
2000 PathOptionBox targetDirectory
2002 this, size = { 270, 22 }, anchor = { left = 344, top = 24, right = 8 };
2003 hotKey = altR, text = $"Target Directory", option = OPTION(targetDirectory);
2006 Label labelLibraries { this, position = { 8, 50 }, labeledWindow = libraries };
2007 StringArrayOptionBox libraries
2009 this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
2010 text = $"Additional Libraries", hotKey = altL, option = OPTION(libraries);
2011 configReplaces = true;
2014 Label labelLinkerOptions { this, position = { 8, 92 }, labeledWindow = linkerOptions };
2015 StringArrayOptionBox linkerOptions
2017 this, size = { 290, 22 }, anchor = { left = 8, top = 108, right = 8 };
2018 text = $"Linker Options", hotKey = altO, option = OPTION(linkerOptions);
2019 configReplaces = true;
2022 BoolOptionBox console
2024 this, position = { 8, 138 };
2025 text = $"Console Application", hotKey = altC, option = OPTION(console);
2028 BoolOptionBox compress
2030 this, position = { 8, 162 };
2031 text = $"Compress", hotKey = altW, option = OPTION(compress);
2034 Label labelLibraryDirs { libraryDirs.editor, labeledWindow = libraryDirs, position = { 0, 6 }; };
2035 DirsArrayOptionBox libraryDirs
2037 this, size = { 290, 22 }, anchor = { left = 8, top = 182, right = 8, bottom = 8 };
2038 text = $"Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs);
2043 ((BuildTab)master).SelectNode(project.topNode, true);
2050 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2051 if(eClass_IsDerived(ob._class, class(OptionBox)))
2053 compress.disabled = (config && config.options && config.options.debug == true) || project.topNode.options.debug == true;
2055 if(activeChild && activeChild.active)
2057 Window control = activeChild;
2058 control.Deactivate();
2064 class BuilderTab : Tab
2066 background = activeBorder;
2069 Label labelPrebuildCommands { prebuildCommands.editor, labeledWindow = prebuildCommands, position = { 0, 6 }; };
2070 StringsArrayOptionBox prebuildCommands
2072 this, size = { 290, 100 }, anchor = { left = 8, top = 52, right = 8 };
2073 text = $"Pre-build Commands", hotKey = altE, option = OPTION(prebuildCommands);
2076 Label labelPostbuildCommands { postbuildCommands.editor, labeledWindow = postbuildCommands, position = { 0, 6 }; };
2077 StringsArrayOptionBox postbuildCommands
2079 this, size = { 290, 100 }, anchor = { left = 8, top = 160, right = 8 };
2080 text = $"Post-build Commands", hotKey = altT, option = OPTION(postbuildCommands);
2085 bool disabled = strlen(((BuildTab)master).selectedPlatformName) > 0;
2087 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2088 if(eClass_IsDerived(ob._class, class(OptionBox)))
2091 if(activeChild && activeChild.active)
2093 Window control = activeChild;
2094 control.Deactivate();