2 import "WorkspaceSettings"
3 import "ProjectTabSettings"
4 import "DirectoriesBox"
8 static ProjectConfig config;
9 static Platform platform;
10 static ProjectNode currentNode;
11 static Project project;
13 static String MakeString(char * s, int len)
15 String string = new char[len+1];
16 memcpy(string, s, len);
21 class StringListBox : EditBox
23 textHorzScroll = true;
25 property Array<String> strings
35 bool quoted = strchr(item, ' ') != null;
49 Array<String> array { };
51 char * contents = property::contents;
55 for(c = 0; (ch = contents[c]); c++)
57 if(ch == ' ' && !quoted)
60 array.Add(MakeString(contents + start, c - start));
68 array.Add(MakeString(contents + start, c - start));
80 array.Add(MakeString(contents + start, c - start));
86 define dialogTitle = "Project Settings";
87 static Color unfocusedSelectorColor { 70, 96, 166 };
88 class ProjectSettings : Window
91 background = activeBorder;
92 borderStyle = sizable;
93 minClientSize = { 650, 490 };
98 property Project project
103 projectTab.project = value;
106 buildTab.SelectNode(project.topNode, false);
108 if(project && project.topNode && project.topNode.name && project.topNode.name[0])
111 get { return ::project; }
114 property ProjectNode projectNode
116 set { buildTab.SelectNode(value, false); }
117 get { return currentNode; }
120 void UpdateDialogTitle()
122 //char * s = PrintString("Project Settings - ", project.topNode.fileName);
124 char * projectName = new char[strlen(project.topNode.name) + 1];
125 char * nodeName = currentNode && currentNode != project.topNode ? currentNode.name : "";
126 char * config = buildTab.selectedConfigName;
127 char * platform = buildTab.selectedPlatformName;
128 char * label = new char[strlen(dialogTitle) + 3 + strlen(project.topNode.name) + 3 +
129 strlen(nodeName) + 2 + strlen(config) + 1 + strlen(platform) + 1 + 1];
130 strcpy(label, dialogTitle);
131 strcat(label, " - ");
132 strcpy(projectName, project.topNode.name);
133 StripExtension(projectName);
134 strcat(label, projectName);
135 if(currentNode && currentNode.type != project)
137 strcat(label, " - ");
138 strcat(label, nodeName);
140 if(strlen(config) || strlen(platform))
144 strcat(label, config);
145 if(strlen(config) && strlen(platform))
148 strcat(label, platform);
161 TabControl prjTabControl
163 this, background = activeBorder, anchor = { left = 8, top = 4, right = 8, bottom = 38 };
165 ProjectTab projectTab { this, tabControl = prjTabControl };
166 BuildTab buildTab { this, tabControl = prjTabControl };
167 WorkspaceTab workspaceTab { this, tabControl = prjTabControl };
171 this, size = { 80, 22 };
172 anchor = { right = 8, bottom = 8 };
173 text = "Cancel", hotKey = escape, id = DialogResult::cancel;
175 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
177 if(prjTabControl.curTab.modifiedDocument)
179 DialogResult diagRes = MessageBox
181 type = okCancel, master = ide,
182 text = "Lose Changes?",
183 contents = "Are you sure you wish to discard changes made to the build options?"
187 if(prjTabControl.curTab == buildTab)
189 buildTab.RevertChanges();
190 buildTab.modifiedDocument = false;
192 if(prjTabControl.curTab == workspaceTab)
194 workspaceTab.modifiedDocument = false;
196 if(prjTabControl.curTab == projectTab)
198 projectTab.modifiedDocument = false;
200 Destroy(DialogResult::cancel);
204 Destroy(DialogResult::cancel);
210 this, size = { 80, 22 };
211 anchor = { right = 96, bottom = 8 };
212 text = "OK", isDefault = true;
214 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
216 if(prjTabControl.curTab == buildTab && buildTab.modifiedDocument)
218 buildTab.modifiedDocument = false;
220 project.topNode.modified = true;
221 project.MarkChanges(buildTab.backupNode);
222 ide.projectView.modifiedDocument = true;
223 ide.projectView.Update(null);
225 if(prjTabControl.curTab == workspaceTab && workspaceTab.modifiedDocument)
227 workspaceTab.SaveChanges();
228 workspaceTab.modifiedDocument = false;
230 if(prjTabControl.curTab == projectTab && projectTab.modifiedDocument)
232 projectTab.SaveChanges();
233 projectTab.modifiedDocument = false;
235 Destroy(DialogResult::ok);
243 prjTabControl.curTab = buildTab;
248 #define OPTION(x) ((uint)(&((ProjectOptions)0).x))
250 // TOFIX: USING T INSTEAD OF Z HERE CAUSED US SOME CONFLICTS WITH T IN Array TEMPLATES
252 class OptionBox<class Z> : CommonControl
254 bool mergeValues, configReplaces;
263 property Window editor
269 editor.OnRightButtonDown = OptionBox_OnRightButtonDown;
270 chainKeyDown = (void *)editor.OnKeyDown;
271 editor.OnKeyDown = OptionBox_OnKeyDown;
275 property bool visible { set { editor.visible = value; } get { return editor.visible; } }
276 property Window parent { set { editor.parent = value; Window::parent = value; master = value; editor.id = (int)this; } }
277 property Point position { set { editor.position = value; } }
278 property Size size { set { editor.size = value; } }
279 property Anchor anchor { set { editor.anchor = value; } }
280 property Key hotKey { set { editor.hotKey = value; } }
281 property char * text { set { editor.text = value; Window::text = value; } }
291 bool NotifySelect(MenuItem selection, Modifiers mods)
293 OptionBox ob = (OptionBox)id;
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 void SetAttribs(int code)
325 for(c = Window::parent.firstChild; c; c = c.next)
327 if(eClass_IsDerived(c._class, class(Label)))
330 if(label.labeledWindow == this)
338 for(c = editor.firstChild; c; c = c.next)
340 if(eClass_IsDerived(c._class, class(Label)))
347 // control.foreground = foreground;
349 if(code == 0 || code == 1)
351 editor.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
352 editor.background = white;
356 Color foreground = 0x0F3F66;
357 int r = foreground.r, g = foreground.g, b = foreground.b;
361 editor.font = { editor.font.faceName, editor.font.size };
363 r = (int)(alpha * r + src.r * (1 - alpha));
364 g = (int)(alpha * g + src.g * (1 - alpha));
365 b = (int)(alpha * b + src.b * (1 - alpha));
367 r = Max(0,Min(255,r));
368 g = Max(0,Min(255,g));
369 b = Max(0,Min(255,b));
371 editor.background = Color { (byte) r, (byte) g, (byte) b };
376 label.font = { editor.font.faceName, editor.font.size, bold = (code == 1) };
377 //label.foreground = foreground;
381 virtual void FinalizeLoading();
383 virtual void LoadOption(ProjectOptions options);
384 virtual void RetrieveOption(ProjectOptions options);
385 virtual void UnsetOption(ProjectOptions options)
388 *(Z*)((byte *)options + option) = value;
391 virtual bool OptionSet(ProjectOptions options)
393 // TOFIX: If you get a crash here, it might be because JSON.ec must be after ProjectConfig.ec in the project files
394 // JSON.ec must also be before ProjectSettings.ec in the project files
395 if(*(Z*)((byte *)options + option))
399 // BUG: OptionCheck = OptionSet; // Overrides derived classes OptionCheck ?
401 virtual bool OptionCheck(ProjectOptions options)
403 return OptionSet(options);
406 void MarkBuildTabModified()
408 BuildTab buildTab = (BuildTab)master;
409 while(buildTab && buildTab._class != class(BuildTab))
410 buildTab = (BuildTab)buildTab.master;
411 if(buildTab) buildTab.modifiedDocument = true;
416 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
417 MarkBuildTabModified();
421 ProjectConfig c = null;
422 if(currentNode.configurations)
424 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
429 PlatformOptions p = null;
432 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
435 if(p.options && OptionSet(p.options))
436 UnsetOption(p.options);
437 if(p.options && p.options.isEmpty)
441 Iterator<PlatformOptions> it { c.platforms };
449 if(!c.platforms.count)
455 if(c.options && OptionSet(c.options))
456 UnsetOption(c.options);
457 if(c.options && c.options.isEmpty)
460 // DON'T DELETE PROJECT CONFIGS HERE!
461 if(!c.options && currentNode != project.topNode)
463 Iterator<ProjectConfig> it { currentNode.configurations };
471 if(!currentNode.configurations.count)
472 delete currentNode.configurations;
479 PlatformOptions p = null;
480 if(currentNode.platforms)
482 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
485 if(p.options && OptionSet(p.options))
486 UnsetOption(p.options);
487 if(p.options && p.options.isEmpty)
491 Iterator<PlatformOptions> it { currentNode.platforms };
499 if(!currentNode.platforms.count)
500 delete currentNode.platforms;
506 if(currentNode.options && OptionSet(currentNode.options))
507 UnsetOption(currentNode.options);
508 if(currentNode.options && currentNode.options.isEmpty)
509 delete currentNode.options;
514 void FigureOutInherited()
517 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
518 bool skipped = false;
519 for(node = currentNode; node; node = node.parent)
521 if(config && node.configurations)
523 for(c : node.configurations; !strcmpi(c.name, config.name))
525 if(platform && c.platforms)
527 for(p : c.platforms; !strcmpi(p.name, platformName))
529 if(skipped && p.options && OptionSet(p.options))
530 LoadOption(p.options);
536 if(skipped && c.options && OptionSet(c.options))
538 LoadOption(c.options);
539 if(configReplaces) return;
545 if(platform && node.platforms)
547 for(p : node.platforms; !strcmpi(p.name, platformName))
549 if(skipped && p.options && OptionSet(p.options))
550 LoadOption(p.options);
555 if(skipped && node.options && OptionSet(node.options))
556 LoadOption(node.options);
557 else if(skipped && !node.parent)
565 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
566 MarkBuildTabModified();
569 ProjectConfig c = null;
570 if(!currentNode.configurations) currentNode.configurations = { };
571 for(i : currentNode.configurations; !strcmpi(i.name, config.name)) { c = i; break; }
573 currentNode.configurations.Add(c = ProjectConfig { name = CopyString(config.name) });
576 PlatformOptions p = null;
577 if(!c.platforms) c.platforms = { };
579 for(i : c.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
581 c.platforms.Add(p = PlatformOptions { CopyString(platformName) });
583 if(!p.options) p.options = { };
584 RetrieveOption(p.options);
585 if(!mergeValues) SetAttribs(1);
588 if(!c.options) c.options = { };
589 RetrieveOption(c.options);
590 if(!mergeValues) SetAttribs(1);
595 PlatformOptions p = null;
596 if(!currentNode.platforms) currentNode.platforms = { };
597 for(i : currentNode.platforms; !strcmpi(i.name, platformName)) { p = i; break; }
599 currentNode.platforms.Add(p = PlatformOptions { CopyString(platformName) });
601 if(!p.options) p.options = { };
602 RetrieveOption(p.options);
603 if(!mergeValues) SetAttribs(1);
607 if(!currentNode.options) currentNode.options = { };
608 RetrieveOption(currentNode.options);
609 if(!mergeValues) SetAttribs((currentNode.parent || OptionCheck(currentNode.options)) ? 1 : 0);
615 char * platformName = platform ? platform.OnGetString(0,0,0) : null;
616 bool setAttribs = false;
617 for(node = currentNode; node; node = node.parent)
619 ProjectConfig nodeConfig = null;
620 if(config && node.configurations)
622 for(c : node.configurations; !strcmpi(c.name, config.name))
624 if(platform && c.platforms)
626 for(p : c.platforms; !strcmpi(p.name, platformName))
628 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
630 LoadOption(p.options);
631 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode) ? 1 : 2); }
632 if(!mergeValues) { FinalizeLoading(); return; }
642 if(platform && node.platforms)
644 for(p : node.platforms; !strcmpi(p.name, platformName))
646 if(p.options && (mergeValues ? OptionCheck(p.options) : OptionSet(p.options)))
648 LoadOption(p.options);
649 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config) ? 1 : 2); }
650 if(!mergeValues) { FinalizeLoading(); return; }
656 if(nodeConfig && nodeConfig.options && ((mergeValues && !configReplaces) ? OptionCheck(nodeConfig.options) : OptionSet(nodeConfig.options)))
658 LoadOption(nodeConfig.options);
659 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !platform) ? 1 : 2); }
660 if(!mergeValues || configReplaces) { FinalizeLoading(); return; }
663 if(node.options && (mergeValues ? OptionCheck(node.options) : OptionSet(node.options)))
665 LoadOption(node.options);
666 if(!node.parent && !OptionCheck(node.options))
668 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
672 if(!setAttribs) { setAttribs = true; SetAttribs((node == currentNode && !config && !platform) ? 1 : 2); }
674 if(!mergeValues) { FinalizeLoading(); return; }
676 else if(!node.parent)
679 if(!setAttribs) { setAttribs = true; SetAttribs(0); }
680 if(!mergeValues) { FinalizeLoading(); return; }
687 class StringOptionBox : OptionBox<String>
691 bool NotifyModified(EditBox editBox)
693 ((OptionBox)editBox.id).Retrieve();
697 textHorzScroll = true;
700 void RetrieveOption(ProjectOptions options)
702 String * string = (String*)((byte *)options + option);
703 if(*string) delete *string;
704 *string = CopyString(((EditBox)editor).contents);
707 void LoadOption(ProjectOptions options)
709 ((EditBox)editor).contents = options ? *(String*)((byte *)options + option) : "";
710 ((EditBox)editor).Deselect();
713 bool OptionCheck(ProjectOptions options)
715 String string = *(String*)((byte *)options + option);
716 return string && string[0];
719 void UnsetOption(ProjectOptions options)
721 delete *(String*)((byte *)options + option);
725 class PathOptionBox : OptionBox<String>
727 bool Window::EditBoxORB(int x, int y, Modifiers mods)
729 Window parent = this.parent;
730 x += clientStart.x + position.x;
731 y += clientStart.y + position.y;
732 return ((OptionBox)this).OptionBox_OnRightButtonDown(parent, x, y, mods);
737 typeExpected = directory, browseDialog = { };
738 editBox.OnRightButtonDown = (void *)EditBoxORB;
740 bool NotifyModified(PathBox pathBox)
742 ((OptionBox)pathBox.id).Retrieve();
747 void RetrieveOption(ProjectOptions options)
749 String * string = (String*)((byte *)options + option);
750 String slashPath = ((PathBox)editor).slashPath;
751 if(*string) delete *string;
752 *string = CopyString(slashPath);//(slashPath && slashPath[0]) ? CopyString(slashPath) : null;
755 void LoadOption(ProjectOptions options)
757 ((PathBox)editor).path = options ? *(String*)((byte *)options + option) : "";
758 ((PathBox)editor).Deselect();
761 bool OptionCheck(ProjectOptions options)
763 String string = *(String*)((byte *)options + option);
764 return string && string[0];
767 void UnsetOption(ProjectOptions options)
769 delete *(String*)((byte *)options + option);
773 class MultiStringOptionBox : OptionBox<Array<String>>
778 caseSensitive = true;
780 virtual Array<String> GetStrings();
781 virtual void SetStrings(Array<String> value);
783 Array<String> tempStrings;
785 void RetrieveOption(ProjectOptions options)
787 Array<String> newStrings = GetStrings();
788 Array<String> * strings = (Array<String>*)((byte *)options + option);
789 if(*strings) { strings->Free(); delete *strings; }
793 Iterator<String> it { newStrings };
795 FigureOutInherited();
799 Array<String> ts = tempStrings;
804 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
805 if(found && (!configReplaces || platform)) // ADDED || platform here...
815 *strings = newStrings;
820 void LoadOption(ProjectOptions options)
824 Array<String> strings = options ? *((Array<String>*)((byte *)options + option) : null;
832 for(i : tempStrings; !(caseSensitive ? strcmp : strcmpi)(i, s)) { found = true; break; }
833 if(!found) tempStrings.Add(s);
839 SetStrings(options ? *(Array<String>*)((byte *)options + option) : null);
843 void FinalizeLoading()
847 SetStrings(tempStrings);
852 bool OptionSet(ProjectOptions options)
854 Array<String> strings = *(Array<String>*)((byte *)options + option);
855 if(mergeValues && !configReplaces)
857 return strings && strings.count;
860 return strings != null;
863 bool OptionCheck(ProjectOptions options)
865 Array<String> strings = *(Array<String>*)((byte *)options + option);
866 return strings && strings.count;
869 void UnsetOption(ProjectOptions options)
871 Array<String> * strings = (Array<String>*)((byte *)options + option);
872 if(*strings) { strings->Free(); delete *strings; }
876 class StringArrayOptionBox : MultiStringOptionBox
878 editor = StringListBox
880 bool NotifyModified(EditBox editBox)
882 ((OptionBox)editBox.id).Retrieve();
887 // NO VIRTUAL PROPERTIES YET...
888 Array<String> GetStrings() { return ((StringListBox)editor).strings; }
889 void SetStrings(Array<String> value) { ((StringListBox)editor).strings = value; }
892 class StringsArrayOptionBox : MultiStringOptionBox
902 bool NotifyModified(StringsBox stringsBox)
904 ((OptionBox)stringsBox.id).Retrieve();
909 Array<String> GetStrings() { return ((StringsBox)editor).strings; }
910 void SetStrings(Array<String> value) { ((StringsBox)editor).strings = value; }
913 class DirsArrayOptionBox : MultiStringOptionBox
915 editor = DirectoriesBox
917 bool NotifyModified(DirectoriesBox dirsBox)
919 ((OptionBox)dirsBox.id).Retrieve();
923 bool OnChangedDir(char * * directory)
925 char fixedDirectory[MAX_LOCATION] = "";
926 if(PathCat(fixedDirectory, *directory))
928 char cwdBackup[MAX_LOCATION];
931 GetWorkingDir(cwdBackup, sizeof(cwdBackup));
932 ChangeWorkingDir(project.topNode.path);
934 FileFixCase(fixedDirectory);
936 ChangeWorkingDir(cwdBackup);
938 *directory = CopyString(fixedDirectory);
944 bool OnPrepareBrowseDir(char * * directory)
946 char dir[MAX_LOCATION];
949 GetSystemPathBuffer(dir, project.topNode.path);
951 PathCat(dir, *directory);
954 strcpy(dir, *directory);
959 *directory = CopyString(dir);
961 // GCC 4.4 bug: ----- path becomes *directory
962 //strcpy(dir, path ? path : "");
966 bool OnBrowsedDir(char * * directory)
970 char path[MAX_LOCATION];
971 MakePathRelative(*directory, project.topNode.path, path);
973 *directory = CopyString(path);
979 Array<String> GetStrings() { return ((DirectoriesBox)editor).strings; }
980 void SetStrings(Array<String> value) { ((DirectoriesBox)editor).strings = value; }
983 class BoolOptionBox : OptionBox<SetBool>
989 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
991 ((OptionBox)button.id).Retrieve();
996 bool OptionCheck(ProjectOptions options)
998 return *(SetBool*)((byte *)options + option) == true;
1001 void RetrieveOption(ProjectOptions options)
1003 bool checked = ((Button)editor).checked;
1004 *(SetBool*)((byte *)options + option) = checked ? true : (currentNode.parent ? false : unset);
1007 void LoadOption(ProjectOptions options)
1009 ((Button)editor).checked = options && (*(SetBool*)((byte *)options + option) == true);
1013 class DropOptionBox : OptionBox
1017 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
1019 ((OptionBox)dropBox.id).Retrieve();
1024 void LoadOption(ProjectOptions options)
1026 DropBox dropBox = (DropBox)editor;
1027 Z value = options ? *(Z*)((byte *)options + option) : (Z)0;
1028 dropBox.currentRow = value ? dropBox.FindRow((int)value) : dropBox.firstRow;
1031 void RetrieveOption(ProjectOptions options)
1033 DropBox dropBox = (DropBox)editor;
1034 DataRow row = dropBox.currentRow;
1035 Z value = (Z)(row ? row.tag : 0);
1036 *(Z*)((byte *)options + option) = value;
1040 class TargetTypeDB : DropOptionBox<TargetTypes>
1046 row = ((DropBox)editor).AddRow();
1047 row.tag = TargetTypes::executable;
1048 row.SetData(null, "Executable");
1050 row = ((DropBox)editor).AddRow();
1051 row.tag = TargetTypes::sharedLibrary;
1052 row.SetData(null, "Shared Library");
1054 row = ((DropBox)editor).AddRow();
1055 row.tag = TargetTypes::staticLibrary;
1056 row.SetData(null, "Static Library");
1059 bool OptionCheck(ProjectOptions options)
1061 TargetTypes value = *(TargetTypes*)((byte *)options + option);
1062 return value && value != executable;
1066 class OptimizationDB : DropOptionBox<OptimizationStrategy>
1071 row = ((DropBox)editor).AddRow();
1072 row.tag = OptimizationStrategy::none;
1073 row.SetData(null, "None");
1075 row = ((DropBox)editor).AddRow();
1076 row.tag = OptimizationStrategy::speed;
1077 row.SetData(null, "For Speed (-O2)");
1079 row = ((DropBox)editor).AddRow();
1080 row.tag = OptimizationStrategy::size;
1081 row.SetData(null, "For Size (-Os)");
1084 bool OptionCheck(ProjectOptions options)
1086 OptimizationStrategy value = *(OptimizationStrategy*)((byte *)options + option);
1087 return value && value != none;
1091 class WarningsDB : DropOptionBox<WarningsOption>
1096 row = ((DropBox)editor).AddRow();
1097 row.tag = WarningsOption::normal;
1098 row.SetData(null, "Normal");
1100 row = ((DropBox)editor).AddRow();
1101 row.tag = WarningsOption::none;
1102 row.SetData(null, "None");
1104 row = ((DropBox)editor).AddRow();
1105 row.tag = WarningsOption::all;
1106 row.SetData(null, "All");
1109 bool OptionCheck(ProjectOptions options)
1111 WarningsOption value = *(WarningsOption*)((byte *)options + option);
1112 return value && value != none;
1116 void DrawStipple(Surface surface, Size clientSize)
1120 int x2 = clientSize.w - 1;
1121 int y2 = clientSize.h - 1;
1122 if((x2 - x1) & 1) x2--;
1123 if((y2 - y1) & 1) y2--;
1125 surface.LineStipple(0x5555);
1126 surface.Rectangle(x1, y1, x2, y2);
1127 surface.LineStipple(0);
1130 class BuildTab : Tab
1133 background = activeBorder;
1136 ProjectNode backupNode;
1137 String activeConfigName;
1139 ProjectNode lastSelectedNode;
1141 property char * selectedConfigName
1147 SelectorButton button = (SelectorButton)configSelector.selectedButton;
1148 if(button && button.id)
1150 ProjectConfig config = (ProjectConfig)button.id;
1158 property char * selectedPlatformName
1164 SelectorButton button = (SelectorButton)platformSelector.selectedButton;
1165 if(button && button.id)
1167 Platform platform = (Platform)button.id;
1168 char * platformName = platform ? platform.OnGetString(0,0,0) : null; // all these platformName are leaking, no?
1169 return platformName;
1176 Label labelConfigurations
1178 this, anchor = { left = 8, top = 14 }, labeledWindow = configSelector;
1180 void OnRedraw(Surface surface)
1182 Label::OnRedraw(surface);
1183 if(labeledWindow.active) DrawStipple(surface, clientSize);
1186 SelectorBar configSelector
1188 this, text = "Configurations: ", anchor = { left = 98, top = 8, right = 54 }; size = { 0, 26 };
1190 direction = horizontal, scrollable = true;
1192 bool OnKeyDown(Key key, unichar ch)
1196 ((BuildTab)parent).createConfig.NotifyClicked(parent, ((BuildTab)parent).createConfig, 0, 0, 0);
1201 ((BuildTab)parent).deleteConfig.NotifyClicked(parent, ((BuildTab)parent).deleteConfig, 0, 0, 0);
1204 return SelectorBar::OnKeyDown(key, ch);
1207 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1209 ((BuildTab)master).labelConfigurations.Update(null);
1216 parent = this, bevelOver = true, inactive = true;
1218 anchor = { top = 10, right = 31 };
1219 hotKey = altC, bitmap = BitmapResource { fileName = ":actions/docNew.png", alphaBlend = true };
1221 bool NotifyClicked(Button b, int x, int y, Modifiers mods)
1223 char tmp[MAX_F_STRING];
1224 ProjectConfig config;
1225 EditableSelectorButton button;
1227 FindUniqueConfigName("NewConfig", false, tmp);
1231 makingModified = true;
1232 compilingModified = true;
1233 linkingModified = true;
1234 name = CopyString(tmp);
1237 // objectsDirectory = CopyString(defaultObjDirExpression);
1240 if(!project.topNode.configurations) project.topNode.configurations = { };
1241 project.topNode.configurations.Add(config);
1243 targetType = project.config.options.targetType;
1245 config.options.targetFileName = CopyString(project.moduleName);
1246 config.targetDir.dir = "";
1247 config.objectsDirectory = CopyString(defaultObjDirExpression);
1248 config.options.debug = true;
1249 config.options.optimization = none;
1250 config.options.warnings = all;
1255 configSelector, renameable = true, master = this, text = config.name, id = (int)config;
1256 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1259 configSelector.Select(button);
1260 modifiedDocument = true;
1264 /*Button duplicateConfig
1266 parent = this, bevelOver = true, inactive = true;
1268 anchor = { top = 10, right = 31 };
1269 hotKey = altU, bitmap = BitmapResource { fileName = ":actions/editCopy.png", alphaBlend = true };
1273 parent = this, bevelOver = true, inactive = true;
1275 anchor = { top = 10, right = 8 };
1276 hotKey = altD, bitmap = BitmapResource { fileName = ":actions/delete2.png", alphaBlend = true };
1278 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1282 String title = PrintString("Delete ", config.name, " Configuration");
1283 String msg = PrintString("Are you sure you wish to delete the ", config.name, " configuration?");
1284 if(MessageBox { type = okCancel, text = title, contents = msg }.Modal() == ok)
1286 Iterator<Window> it { configSelector.controls };
1287 ProjectConfig configToDelete = config;
1291 SelectorButton button = (SelectorButton)it.data;
1292 if((ProjectConfig)button.id == config)
1294 button.visible = false;
1300 button = (SelectorButton)it.data;
1301 config = (ProjectConfig)button.id;
1302 configSelector.Select(button);
1307 project.topNode.DeleteConfig(configToDelete);
1309 modifiedDocument = true;
1318 Label labelPlatforms
1320 this, anchor = { left = 8, top = 44 }, labeledWindow = platformSelector;
1322 void OnRedraw(Surface surface)
1324 Label::OnRedraw(surface);
1325 if(labeledWindow.active) DrawStipple(surface, clientSize);
1328 SelectorBar platformSelector
1330 this, text = "Platforms: ", anchor = { left = 64, top = 38, right = 54 }; size = { 0, 26 };
1332 direction = horizontal, scrollable = true;
1334 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1336 ((BuildTab)master).labelPlatforms.Update(null);
1341 TabControl buildTabControl
1343 this, background = activeBorder, anchor = { left = 8, top = 64, right = 8, bottom = 8 };
1344 curTab = compilerTab;
1346 CompilerTab compilerTab { this, tabControl = buildTabControl };
1347 LinkerTab linkerTab { this, tabControl = buildTabControl };
1348 BuilderTab builderTab { this, tabControl = buildTabControl };
1351 this, font = { font.faceName, font.size, italic = true }, stayOnTop = true,
1352 text = "(Right click or press Ctrl-Del to revert an option to inherited value)", anchor = { top = 72, right = 16 }
1355 void FindUniqueConfigName(char * baseName, bool startWithNumber, char * output)
1358 char tmp[MAX_F_STRING];
1360 sprintf(tmp, "%s%d", baseName, num);
1362 strcpy(tmp, baseName);
1365 ProjectConfig config = null;
1366 for(c : project.topNode.configurations)
1367 { // TOFIX: Error when omitting these brackets, c not found
1368 if(c.name && !strcmp(c.name, tmp))
1377 sprintf(tmp, "%s%d", baseName, num);
1382 strcpy(output, tmp);
1385 bool PlatformClicked(Button clickedButton, int x, int y, Modifiers mods)
1387 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1389 platform = (Platform)clickedButton.id;
1391 // Load Settings Into Dialog
1392 compilerTab.LoadSettings();
1393 linkerTab.LoadSettings();
1394 builderTab.LoadSettings();
1397 buildTabControl.Activate();
1399 if(compilerTab.rightPaneHeader.visible)
1400 compilerTab.rightPaneHeader.Update(null);
1401 ((ProjectSettings)master).UpdateDialogTitle();
1408 platformSelector.DestroyChildren();
1409 configSelector.DestroyChildren();
1411 delete activeConfigName;
1414 bool ConfigOnRename(EditableSelectorButton button, char * * oldName, char * * newName)
1419 for(c = 0; (ch = (*newName)[c]); c++)
1421 if(ch == '_' || isalpha(ch) || (isdigit(ch) && d))
1422 (*newName)[d++] = ch;
1428 for(c : project.topNode.configurations; c != config)
1430 if(!strcmpi(c.name, *newName))
1436 if(found || !(*newName)[0])
1438 char tmp[MAX_F_STRING];
1439 char * tmpName = config.name;
1441 FindUniqueConfigName("NewConfig", false, tmp);
1442 config.name = tmpName;
1444 *newName = CopyString(tmp);
1448 if(activeConfigName && !strcmp(activeConfigName, *oldName))
1450 delete activeConfigName;
1451 activeConfigName = CopyString(*newName);
1454 project.topNode.RenameConfig(config.name, *newName);
1456 modifiedDocument = true;
1460 bool ConfigClicked(Button clickedButton, int x, int y, Modifiers mods)
1462 if(!eClass_IsDerived(clickedButton._class, class(EditableSelectorButton)) || !((EditableSelectorButton)clickedButton).editBox)
1464 config = (ProjectConfig)clickedButton.id;
1466 // Load Settings Into Dialog
1467 compilerTab.LoadSettings();
1468 linkerTab.LoadSettings();
1469 builderTab.LoadSettings();
1471 deleteConfig.disabled = (clickedButton._class == class(SelectorButton));
1474 buildTabControl.Activate();
1476 if(compilerTab.rightPaneHeader.visible)
1477 compilerTab.rightPaneHeader.Update(null);
1478 ((ProjectSettings)master).UpdateDialogTitle();
1483 void SelectNode(ProjectNode node, bool ignoreAsLastSelection)
1485 if(node != currentNode)
1487 Window ac = compilerTab.rightPane.activeChild;
1488 bool prevNodeRes = currentNode ? currentNode.isInResources : false;
1491 if(!node) node = project.topNode;
1493 newNodeRes = node.isInResources;
1496 if(!ignoreAsLastSelection)
1497 lastSelectedNode = node;
1499 ((ProjectSettings)master).UpdateDialogTitle();
1500 if(node.type == project)
1502 compilerTab.rightPaneHeader.visible = false;
1506 compilerTab.rightPaneHeader.id = (int)node;
1507 compilerTab.rightPaneHeader.Update(null);
1508 compilerTab.rightPaneHeader.visible = true;
1512 DataRow row = compilerTab.fileList.FindSubRow((int)currentNode);
1515 compilerTab.fileList.currentRow = row;
1516 while((row = row.parent))
1517 row.collapsed = false;
1521 if(prevNodeRes != newNodeRes)
1523 compilerTab.labelObjDir.visible = !newNodeRes;
1524 compilerTab.objDir.visible = !newNodeRes;
1525 compilerTab.excludeFromBuild.visible = !newNodeRes;
1526 compilerTab.labelPreprocessorDefs.visible = !newNodeRes;
1527 compilerTab.preprocessorDefs.visible = !newNodeRes;
1528 compilerTab.labelDefaultNameSpace.visible = !newNodeRes;
1529 compilerTab.defaultNameSpace.visible = !newNodeRes;
1530 compilerTab.strictNameSpaces.visible = !newNodeRes;
1531 compilerTab.memoryGuard.visible = !newNodeRes;
1532 compilerTab.noLineNumbers.visible = !newNodeRes;
1533 compilerTab.debug.visible = !newNodeRes;
1534 compilerTab.labelWarnings.visible = !newNodeRes;
1535 compilerTab.warnings.visible = !newNodeRes;
1536 compilerTab.profiling.visible = !newNodeRes;
1537 compilerTab.labelOptimization.visible = !newNodeRes;
1538 compilerTab.optimization.visible = !newNodeRes;
1539 compilerTab.labelIncludeDirs.visible = !newNodeRes;
1540 compilerTab.includeDirs.visible = !newNodeRes;
1543 if(node == project.topNode)
1545 compilerTab.objDir.visible = true;
1546 compilerTab.labelObjDir.visible = true;
1548 compilerTab.excludeFromBuild.visible = false;
1552 compilerTab.objDir.visible = false;
1553 compilerTab.labelObjDir.visible = false;
1555 compilerTab.excludeFromBuild.visible = (node != project.resNode);
1558 // Load Settings Into Dialog
1559 compilerTab.LoadSettings();
1560 linkerTab.LoadSettings();
1561 builderTab.LoadSettings();
1567 if(ac == compilerTab.excludeFromBuild.editor)
1568 ac = compilerTab.objDir.editor;
1569 else if(compilerTab.excludeFromBuild.editor.visible)
1570 ac = compilerTab.excludeFromBuild.editor;
1577 void CreateConfigButtons()
1579 SelectorButton commonButton;
1581 // Create Config Buttons
1582 commonButton = SelectorButton
1584 configSelector, master = this, text = "Common", id = (int)null; font = { font.faceName, font.size, true };
1586 NotifyClicked = ConfigClicked;
1591 if(project.topNode.configurations)
1593 for(c : project.topNode.configurations)
1595 EditableSelectorButton button
1597 configSelector, master = this, renameable = true, text = c.name, id = (int)c;
1598 NotifyClicked = ConfigClicked, OnRename = ConfigOnRename;
1607 SelectorButton button;
1609 activeConfigName = project.config ? CopyString(project.config.name) : null;
1611 compilerTab.AddNode(project.topNode, null);
1613 CreateConfigButtons();
1615 platformButton = button =
1617 platformSelector, master = this, text = "Common", id = 0; font = { font.faceName, font.size, true };
1618 NotifyClicked = PlatformClicked; checked = true;
1623 for(p = (Platform)1; p < Platform::enumSize; p++)
1625 SelectorButton button
1627 platformSelector, master = this, text = p.OnGetString(0,0,0), id = (int)p;
1628 NotifyClicked = PlatformClicked;
1632 SelectorButton platformButton;
1636 // Backup Current Settings
1637 backupNode = project.topNode.Backup();
1639 buildTabControl.Activate();
1642 Iterator<Window> it { configSelector.controls };
1645 SelectorButton configButton = (SelectorButton)it.data;
1646 ProjectConfig buttonConfig = (ProjectConfig)configButton.id;
1647 if(buttonConfig == project.config)
1649 configButton.Activate();
1650 configButton.checked = true;
1651 ConfigClicked(configButton, 0, 0, (Modifiers)null);
1658 platformButton.MakeActive();
1659 platformButton = null;
1668 lastSelectedNode = null;
1670 project.config = null;
1672 project.configurations = project.topNode.configurations;
1673 project.platforms = project.topNode.platforms;
1674 project.options = project.topNode.options;
1676 if(project.topNode.configurations)
1678 for(c : project.topNode.configurations)
1680 if(!strcmpi(c.name, activeConfigName))
1689 void RevertChanges()
1691 String configName = config ? CopyString(config.name) : null;
1693 // Revert to saved project options
1694 project.topNode.Revert(backupNode);
1696 configSelector.DestroyChildren();
1697 CreateConfigButtons();
1699 // Reselect Configuration
1702 Iterator<Window> it { configSelector.controls };
1705 Button button = (Button)it.data;
1706 ProjectConfig c = (ProjectConfig)button.id;
1707 if(c && !strcmp(c.name, configName))
1711 button.checked = true;
1712 ConfigClicked(button, 0,0, 0);
1718 SelectNode(project.topNode, false);
1723 bool OnClose(bool parentClosing)
1725 if(modifiedDocument)
1727 DialogResult diagRes = MessageBox
1729 type = yesNoCancel, master = ide,
1730 text = "Save changes to project settings?",
1731 contents = "Would you like to save changes made to the build options?"
1735 if(diagRes == cancel)
1739 project.MarkChanges(backupNode);
1740 project.topNode.modified = true;
1741 ide.projectView.modifiedDocument = true;
1742 ide.projectView.Update(null);
1744 modifiedDocument = false;
1750 class CompilerTab : Tab
1752 background = activeBorder;
1755 Window leftPane { this, size = { 180 }, anchor = { left = 0, top = 0, bottom = 0 }, background = activeBorder };
1757 Label labelFileList { leftPane, this, position = { 8, 8 }, labeledWindow = fileList };
1760 leftPane, this, borderStyle = deep, hasVertScroll = true, hasHorzScroll = true;
1761 // THIS WOULD BE EVEN MORE FUN: multiSelect = true,
1762 fullRowSelect = false, collapseControl = true, treeBranches = true;
1763 alwaysHighLight = true;
1764 selectionColor = unfocusedSelectorColor;
1766 anchor = Anchor { left = 8, top = 24, right = 4, bottom = 8 };
1769 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1771 BuildTab buildTab = (BuildTab)master;
1772 ProjectNode node = (ProjectNode)row.tag;
1773 buildTab.SelectNode(node, false);
1777 void OnRedraw(Surface surface)
1779 ide.projectView.drawingInProjectSettingsDialog = true;
1780 ListBox::OnRedraw(surface);
1781 ide.projectView.drawingInProjectSettingsDialog = false;
1784 bool NotifyActivate(Window window, bool active, Window previous)
1788 //subclass(Skin) skinClass = (subclass(Skin))eSystem_FindClass(app, app.skin);
1789 fileList.selectionColor = Color { 10, 36, 106 }; //skinClass.selectionColor; // darkBlue;
1791 else if(fileList.currentRow)
1793 DataRow currentRow = fileList.currentRow;
1794 //int headerSize = ((fileList.style.header) ? fileList.rowHeight : 0);
1795 int height = fileList.clientSize.h + 1;// - fileList.headerSize;
1796 fileList.selectionColor = unfocusedSelectorColor;
1797 if(currentRow && currentRow.index * fileList.rowHeight > fileList.scroll.y + height - fileList.rowHeight)
1798 fileList.SetScrollPosition(fileList.scroll.x, currentRow.index * fileList.rowHeight - height + fileList.rowHeight);
1799 else if(!currentRow || currentRow.index * fileList.rowHeight < fileList.scroll.y)
1800 fileList.SetScrollPosition(fileList.scroll.x, currentRow ? currentRow.index * fileList.rowHeight : 0);
1810 this, anchor = { left = 196, top = 0, right = 0, bottom = 0 }, background = activeBorder, tabCycle = true;
1813 Window rightPaneHeader
1815 rightPane, this, size = { h = 21 }, anchor = { left = 0, top = 0, right = 0 }, background = Color { 70, 96, 166 };//0x0F3F66;
1816 foreground = white; visible = false;
1818 void OnRedraw(Surface surface)
1822 ide.projectView.drawingInProjectSettingsDialogHeader = true;
1823 class(ProjectNode)._vTbl[__ecereVMethodID_class_OnDisplay](class(ProjectNode),
1824 id, surface, 8, 2, clientSize.w, ide.projectView, Alignment::left, DataDisplayFlags { selected = true });
1825 ide.projectView.drawingInProjectSettingsDialogHeader = false;
1830 PaneSplitter splitter
1832 this, leftPane = leftPane, rightPane = rightPane, split = 188
1835 Label labelObjDir { rightPane, this, position = { 8, 8 }, labeledWindow = objDir };
1836 PathOptionBox objDir
1838 rightPane, this, size = { 250, 22 }, anchor = { left = 8, top = 24, right = 8 };
1839 text = "Intermediate Objects Directory", hotKey = altJ, option = OPTION(objectsDirectory);
1842 BoolOptionBox excludeFromBuild
1844 rightPane, this, position = { 8, 28 },
1845 text = "Exclude from Build", visible = false, option = OPTION(excludeFromBuild);
1848 Label labelPreprocessorDefs { rightPane, this, position = { 8, 50 }, labeledWindow = preprocessorDefs };
1849 StringArrayOptionBox preprocessorDefs
1851 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
1852 text = "Preprocessor Definitions", hotKey = altD, option = OPTION(preprocessorDefinitions);
1855 Label labelDefaultNameSpace { rightPane, this, position = { 8, 92 }, labeledWindow = defaultNameSpace };
1856 StringOptionBox defaultNameSpace
1858 rightPane, this, size = { 160, 22 }, position = { 8, 108 };
1859 text = "Default Name Space", option = OPTION(defaultNameSpace);
1861 BoolOptionBox strictNameSpaces
1863 rightPane, this, position = { 172, 112 },
1864 text = "Strict Name Spaces", option = OPTION(strictNameSpaces);
1867 BoolOptionBox memoryGuard
1869 rightPane, this, position = { 8, 154 };
1870 text = "MemoryGuard", hotKey = altM, option = OPTION(memoryGuard);
1873 Label labelWarnings { rightPane, position = { 116, 138 }, labeledWindow = warnings };
1876 rightPane, this, position = { 116, 154 };
1877 text = "Warnings", hotKey = altW, option = OPTION(warnings);
1880 Label labelOptimization { rightPane, position = { 244, 138 }, labeledWindow = optimization };
1881 OptimizationDB optimization
1883 rightPane, this, position = { 244, 154 }, size = { 120, 22 };
1884 text = "Optimization", hotKey = altO, option = OPTION(optimization);
1889 rightPane, this, position = { 8, 188 };
1890 text = "Debuggable", hotKey = altG, option = OPTION(debug);
1893 BoolOptionBox profiling
1895 rightPane, this, position = { 116, 188 };
1896 text = "Profiling Data", hotKey = altP, option = OPTION(profile);
1899 BoolOptionBox noLineNumbers
1901 rightPane, this, position = { 244, 188 };
1902 text = "No Line Numbers", hotKey = altN, option = OPTION(noLineNumbers);
1905 Label labelIncludeDirs { includeDirs.editor, labeledWindow = includeDirs, position = { 0, 6 }; };
1906 DirsArrayOptionBox includeDirs
1908 rightPane, this, size = { 290, 22 }, anchor = { left = 8, top = 208, right = 8, bottom = 8 };
1909 text = "Additional Include Directories", hotKey = altI, option = OPTION(includeDirs);
1914 fileList.AddField(DataField { dataType = class(ProjectNode), freeData = false,
1915 userData = null /* Now set in the ProjectNode directly to know we're in ProjectSettings Dialog -- ide.projectView*/ });
1920 BuildTab buildTab = (BuildTab)master;
1921 buildTab.SelectNode(buildTab.lastSelectedNode, true);
1925 void AddNode(ProjectNode node, DataRow addTo)
1927 DataRow row = addTo ? addTo.AddRow() : fileList.AddRow();
1929 row.tag = (int)node;
1931 row.SetData(null, node);
1933 if(node.files && node.files.first && node.parent &&
1934 !(!node.parent.parent &&
1935 (!strcmpi(node.name, "notes") || !strcmpi(node.name, "sources") ||
1936 !strcmpi(node.name, "src") || !strcmpi(node.name, "tools"))))
1937 row.collapsed = true;
1938 else if(node.type == folder)
1939 node.icon = openFolder;
1943 for(child : node.files)
1944 AddNode(child, row);
1951 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
1952 if(eClass_IsDerived(ob._class, class(OptionBox)))
1955 if(activeChild && activeChild.active)
1957 Window control = activeChild;
1958 control.Deactivate();
1965 objDir.editor.Activate();
1970 class LinkerTab : Tab
1972 background = activeBorder;
1975 Label labelTargetName { this, position = { 8, 8 }, labeledWindow = targetName };
1976 StringOptionBox targetName
1978 this, position = { 8, 24 }, size = { 200, 22 };
1979 text = "Target Name", hotKey = altN, option = OPTION(targetFileName);
1982 Label labelTargetType { this, position = { 216, 8 }, labeledWindow = targetType };
1983 TargetTypeDB targetType
1985 this, position = { 216, 24 }, size = { 120, 22 };
1986 text = "Target Type", hotKey = altT, option = OPTION(targetType);
1989 Label labelTargetDirectory { this, position = { 344, 8 }, labeledWindow = targetDirectory };
1990 PathOptionBox targetDirectory
1992 this, size = { 270, 22 }, anchor = { left = 344, top = 24, right = 8 };
1993 hotKey = altR, text = "Target Directory", option = OPTION(targetDirectory);
1996 Label labelLibraries { this, position = { 8, 50 }, labeledWindow = libraries };
1997 StringArrayOptionBox libraries
1999 this, size = { 290, 22 }, anchor = { left = 8, top = 66, right = 8 };
2000 text = "Additional Libraries", hotKey = altL, option = OPTION(libraries);
2001 configReplaces = true;
2004 Label labelLinkerOptions { this, position = { 8, 92 }, labeledWindow = linkerOptions };
2005 StringArrayOptionBox linkerOptions
2007 this, size = { 290, 22 }, anchor = { left = 8, top = 108, right = 8 };
2008 text = "Linker Options", hotKey = altO, option = OPTION(linkerOptions);
2009 configReplaces = true;
2012 BoolOptionBox console
2014 this, position = { 8, 138 };
2015 text = "Console Application", hotKey = altC, option = OPTION(console);
2018 BoolOptionBox compress
2020 this, position = { 8, 162 };
2021 text = "Compress", hotKey = altW, option = OPTION(compress);
2024 Label labelLibraryDirs { libraryDirs.editor, labeledWindow = libraryDirs, position = { 0, 6 }; };
2025 DirsArrayOptionBox libraryDirs
2027 this, size = { 290, 22 }, anchor = { left = 8, top = 182, right = 8, bottom = 8 };
2028 text = "Additional Library Directories", hotKey = altY, option = OPTION(libraryDirs);
2033 ((BuildTab)master).SelectNode(project.topNode, true);
2040 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2041 if(eClass_IsDerived(ob._class, class(OptionBox)))
2043 compress.disabled = (config && config.options && config.options.debug == true) || project.topNode.options.debug == true;
2045 if(activeChild && activeChild.active)
2047 Window control = activeChild;
2048 control.Deactivate();
2054 class BuilderTab : Tab
2056 background = activeBorder;
2059 Label labelPrebuildCommands { prebuildCommands.editor, labeledWindow = prebuildCommands, position = { 0, 6 }; };
2060 StringsArrayOptionBox prebuildCommands
2062 this, size = { 290, 100 }, anchor = { left = 8, top = 52, right = 8 };
2063 text = "Pre-build Commands", hotKey = altE, option = OPTION(prebuildCommands);
2066 Label labelPostbuildCommands { postbuildCommands.editor, labeledWindow = postbuildCommands, position = { 0, 6 }; };
2067 StringsArrayOptionBox postbuildCommands
2069 this, size = { 290, 100 }, anchor = { left = 8, top = 160, right = 8 };
2070 text = "Post-build Commands", hotKey = altT, option = OPTION(postbuildCommands);
2075 bool disabled = strlen(((BuildTab)master).selectedPlatformName) > 0;
2077 for(ob = (OptionBox)firstSlave; ob; ob = (OptionBox)ob.nextSlave)
2078 if(eClass_IsDerived(ob._class, class(OptionBox)))
2081 if(activeChild && activeChild.active)
2083 Window control = activeChild;
2084 control.Deactivate();