2 public import static "ecere"
3 public import static "ec"
9 import "GlobalSettingsDialog"
10 import "NewProjectDialog"
11 import "FindInFilesDialog"
12 import "ActiveCompilerDialog"
19 import "ProjectActiveConfig"
20 import "ProjectConfig"
22 import "NodeProperties"
23 import "ProjectSettings"
35 import "BreakpointsView"
36 import "CallStackView"
47 import "FileSystemIterator"
49 #if defined(__WIN32__)
50 define pathListSep = ";";
52 define pathListSep = ":";
55 define maxPathLen = 65 * MAX_LOCATION;
57 class PathBackup : struct
64 oldPath = new char[maxPathLen];
65 oldLDPath = new char[maxPathLen];
67 GetEnvironment("PATH", oldPath, maxPathLen);
68 #if defined(__APPLE__)
69 GetEnvironment("DYLD_LIBRARY_PATH", oldLDPath, maxPathLen);
71 GetEnvironment("LD_LIBRARY_PATH", oldLDPath, maxPathLen);
77 SetEnvironment("PATH", oldPath);
78 #if defined(__APPLE__)
79 SetEnvironment("DYLD_LIBRARY_PATH", oldLDPath);
81 SetEnvironment("LD_LIBRARY_PATH", oldLDPath);
88 enum OpenCreateIfFails { no, yes, something, whatever };
89 enum OpenMethod { normal, add };
91 static Array<FileFilter> fileFilters
93 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
94 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
95 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
96 { $"Text files (*.txt, *.text, *.nfo, *.info)", "txt, text, nfo, info" },
97 { $"Web files (*.html, *.htm, *.xhtml, *.css, *.php, *.js, *.jsi, *.rb, *.xml)", "html, htm, xhtml, css, php, js, jsi, rb, xml" },
98 { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
99 { $"3D Studio Model Files (*.3ds)", "3ds" },
100 { $"All files", null }
103 static Array<FileType> fileTypes
105 { $"Based on extension", null },
108 { $"3D Studio Model", "3ds" }
111 static Array<FileFilter> projectFilters
113 { $"Project Files (*.epj)", ProjectExtension }
116 static Array<FileType> projectTypes
118 { $"Project File", ProjectExtension }
121 static Array<FileFilter> findInFilesFileFilters
123 { $"eC Files (*.ec, *.eh)", "ec, eh" },
124 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
125 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
126 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
127 { $"Text files (*.txt)", "txt" },
128 { $"All files", null }
131 FileDialog ideFileDialog
133 type = multiOpen, text = $"Open";
134 types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
137 define openProjectFileDialogTitle = $"Open Project";
138 define addProjectFileDialogTitle = $"Open Additional Project";
139 FileDialog ideProjectFileDialog
142 types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
145 GlobalSettingsDialog globalSettingsDialog
147 ideSettings = ideSettings;
148 settingsContainer = settingsContainer;
150 void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
152 switch(globalSettingsChange)
157 for(child = ide.firstChild; child; child = child.next)
159 if(child._class == class(CodeEditor))
161 CodeEditor codeEditor = (CodeEditor) child;
162 codeEditor.editBox.freeCaret = ideSettings.useFreeCaret;
163 // codeEditor.editBox.lineNumbers = ideSettings.showLineNumbers;
164 codeEditor.editBox.caretFollowsScrolling = ideSettings.caretFollowsScrolling;
165 codeEditor.OnPostCreate(); // Update editBox margin size
172 case compilerSettings:
174 ide.UpdateMakefiles();
181 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
186 lineY = (line - 1) * lineH;
187 if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
189 Bitmap bitmap = resource.bitmap;
191 surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
196 #define IDEItem(x) (&((IDEWorkSpace)0).x)
198 class IDEToolbar : ToolBar
202 ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) };
204 ToolButton buttonOpenFile { this, toolTip = $"Open file", menuItemPtr = IDEItem(fileOpenItem) };
206 // ToolButton buttonCloseFile { this, toolTip = $"Close file", menuItemPtr = IDEItem(fileCloseItem) };
208 ToolButton buttonSaveFile { this, toolTip = $"Save file", menuItemPtr = IDEItem(fileSaveItem) };
210 ToolButton buttonSaveAllFile { this, toolTip = $"Save all", menuItemPtr = IDEItem(fileSaveAllItem) };
212 ToolSeparator separator1 { this };
221 // ToolSeparator separator2 { this };
223 /* Project options */
225 ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) };
227 ToolButton buttonOpenProject { this, toolTip = $"Open project", menuItemPtr = IDEItem(projectOpenItem) };
228 // Add project to workspace
229 ToolButton buttonAddProject { this, toolTip = $"Add project to workspace", menuItemPtr = IDEItem(projectAddItem), disabled = true; };
231 // ToolButton buttonCloseProject { this, toolTip = $"Close project", menuItemPtr = IDEItem(projectCloseItem), disabled = true; };
233 ToolSeparator separator3 { this };
235 /* Build/Execution options */
237 ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; };
239 ToolButton buttonReLink { this, toolTip = $"Relink project", menuItemPtr = IDEItem(projectLinkItem), disabled = true; };
241 ToolButton buttonRebuild { this, toolTip = $"Rebuild project", menuItemPtr = IDEItem(projectRebuildItem), disabled = true; };
243 ToolButton buttonClean { this, toolTip = $"Clean project", menuItemPtr = IDEItem(projectCleanItem), disabled = true; };
245 // ToolButton buttonRealClean { this, toolTip = $"Real clean project", menuItemPtr = IDEItem(projectRealCleanItem), disabled = true; };
246 // Regenerate Makefile
247 ToolButton buttonRegenerateMakefile { this, toolTip = $"Regenerate Makefile", menuItemPtr = IDEItem(projectRegenerateItem), disabled = true; };
248 // Compile actual file
250 ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
252 ToolSeparator separator4 { this };
256 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
258 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
260 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
262 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
264 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
266 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
268 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
270 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
272 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
275 class IDEMainFrame : Window
277 background = formColor;
278 borderStyle = sizable;
282 minClientSize = { 600, 300 };
284 icon = { ":icon.png" };
285 text = titleECEREIDE;
289 anchor = { top = 0, right = 0, bottom = 0 };
292 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
299 isActiveClient = true;
301 direction = vertical;
302 background = formColor;
303 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
311 ((IDEWorkSpace)master).toolBar = null;
314 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
317 define ide = ideMainFrame.ideWorkSpace;
319 class IDEWorkSpace : Window
321 background = Color { 85, 85, 85 };
324 hasVertScroll = true;
325 hasHorzScroll = true;
327 isActiveClient = true;
328 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
332 MenuItem * driverItems, * skinItems;
333 StatusField pos { width = 150 };
334 StatusField ovr, caps, num;
336 BitmapResource back { ":ecereBack.jpg", window = this };
337 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
338 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
339 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
340 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
341 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
342 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
343 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
344 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
345 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
346 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
348 Debugger debugger { };
350 ProjectView projectView;
352 OutputView outputView
356 void OnGotoError(char * line)
361 void OnCodeLocationParseAndGoTo(char * line)
363 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
366 bool OnKeyDown(Key key, unichar ch)
371 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
372 ide.ShowCodeEditor();
375 ide.projectView.stopBuild = true;
379 OutputView::OnKeyDown(key, ch);
386 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
389 ide.RepositionWindows(false);
393 bool OnClose(bool parentClosing)
397 ide.RepositionWindows(false);
398 return parentClosing;
402 CallStackView callStackView
404 parent = this, font = { panelFont.faceName, panelFont.size };
406 void OnGotoLine(char * line)
409 stackLvl = atoi(line);
410 ide.debugger.GoToStackFrameLine(stackLvl, true);
413 void OnSelectFrame(int lineNumber)
415 ide.debugger.SelectFrame(lineNumber);
418 void OnToggleBreakpoint()
420 Debugger debugger = ide.debugger;
421 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
423 int line = debugger.activeFrame.line;
424 char name[MAX_LOCATION];
426 // TOFIX: Improve on this, don't use only filename, make a function
427 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
428 if(ide && ide.workspace)
430 for(p : ide.workspace.projects)
432 if(p.topNode.Find(name, false))
440 for(p : ide.workspace.projects)
442 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
450 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
453 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
454 if(codeEditor) { codeEditor.Update(null); Activate(); }
459 bool OnKeyDown(Key key, unichar ch)
463 case escape: ide.ShowCodeEditor(); break;
468 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
471 ide.RepositionWindows(false);
475 bool OnClose(bool parentClosing)
479 ide.RepositionWindows(false);
480 return parentClosing;
483 void OnRedraw(Surface surface)
486 int lineCursor, lineTopFrame, activeThread, hitThread;
487 int lineH, scrollY, boxH;
489 Breakpoint bp = null;
490 Debugger debugger = ide.debugger;
491 Frame activeFrame = debugger.activeFrame;
494 scrollY = editBox.scroll.y;
495 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
497 activeThread = debugger.activeThread;
498 hitThread = debugger.hitThread;
499 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
501 if(activeFrame && activeFrame.absoluteFile)
503 for(i : ide.workspace.breakpoints; i.type == user)
505 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
506 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
507 activeFrame.line == i.line)
516 DrawLineMarginIcon(surface,
517 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
518 lineCursor /*1*/, lineH, scrollY, boxH);
521 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
522 DrawLineMarginIcon(surface,
523 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
524 1, lineH, scrollY, boxH);
526 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
527 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
528 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
530 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
531 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
532 if(editBox.horzScroll && editBox.horzScroll.visible)
534 surface.SetBackground(control);
535 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
540 WatchesView watchesView { parent = this };
541 ThreadsView threadsView
543 parent = this, font = { panelFont.faceName, panelFont.size };
545 bool OnKeyDown(Key key, unichar ch)
549 case escape: ide.ShowCodeEditor(); break;
554 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
557 ide.RepositionWindows(false);
561 bool OnClose(bool parentClosing)
565 ide.RepositionWindows(false);
566 return parentClosing;
569 void OnSelectThread(int threadId)
572 ide.debugger.SelectThread(threadId);
575 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
578 Debugger debugger = ide.debugger;
579 *activeThread = debugger.activeThread;
580 *hitThread = debugger.hitThread;
581 *signalThread = debugger.signalThread;
586 BreakpointsView breakpointsView { parent = this };
588 ToolBox toolBox { parent = this };
589 Sheet sheet { parent = this };
592 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
594 Menu fileMenu { menu, $"File", f, hasMargin = true };
597 fileMenu, $"New", n, ctrlN;
598 bitmap = { ":actions/docNew.png" };
599 bool NotifySelect(MenuItem selection, Modifiers mods)
601 Window document = (Window)NewCodeEditor(this, normal, false);
602 document.NotifySaved = DocumentSaved;
606 MenuItem fileOpenItem
608 fileMenu, $"Open...", o, ctrlO;
609 bitmap = { ":actions/docOpen.png" };
610 bool NotifySelect(MenuItem selection, Modifiers mods)
612 if(!projectView && ideSettings.ideFileDialogLocation)
613 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
616 if(ideFileDialog.Modal() == ok)
618 bool gotWhatWeWant = false;
620 int numSelections = ideFileDialog.numSelections;
621 char ** multiFilePaths = ideFileDialog.multiFilePaths;
623 for(c = 0; c < numSelections; c++)
625 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
626 gotWhatWeWant = true;
629 MessageBox { type = yesNo, master = this, text = $"Error opening file",
630 contents = $"Open a different file?" }.Modal() == no)
632 if(!projectView && gotWhatWeWant)
633 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
643 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
644 MenuDivider { fileMenu };
645 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" } };
646 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
647 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
648 MenuDivider { fileMenu };
651 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
652 bool NotifySelect(MenuItem selection, Modifiers mods)
654 findInFilesDialog.replaceMode = false;
655 findInFilesDialog.Show();
659 MenuItem replaceInFiles
661 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
662 bool NotifySelect(MenuItem selection, Modifiers mods)
664 findInFilesDialog.replaceMode = true;
665 findInFilesDialog.Show();
669 MenuDivider { fileMenu };
670 MenuItem globalSettingsItem
672 fileMenu, $"Global Settings...", g;
673 bool NotifySelect(MenuItem selection, Modifiers mods)
675 globalSettingsDialog.master = this;
676 if(ide.workspace && ide.workspace.compiler)
677 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
678 else if(ideSettings.defaultCompiler)
679 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
680 globalSettingsDialog.Modal();
684 MenuDivider { fileMenu };
685 Menu recentFiles { fileMenu, $"Recent Files", r };
686 Menu recentProjects { fileMenu, $"Recent Projects", p };
687 MenuDivider { fileMenu };
690 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
692 bool NotifySelect(MenuItem selection, Modifiers mods)
694 ideMainFrame.Destroy(0);
699 bool FileRecentFile(MenuItem selection, Modifiers mods)
702 for(file : ideSettings.recentFiles)
704 if(id == selection.id)
706 OpenFile(file, normal, true, null, no, normal);
714 bool FileRecentProject(MenuItem selection, Modifiers mods)
717 for(file : ideSettings.recentProjects)
719 if(id == selection.id)
721 OpenFile(file, normal, true, null, no, normal);
729 MenuPlacement editMenu { menu, $"Edit", e };
731 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
732 MenuItem projectNewItem
734 projectMenu, $"New...", n, Key { n, true, true };
735 bitmap = { ":actions/projNew.png" };
736 bool NotifySelect(MenuItem selection, Modifiers mods)
738 if(!DontTerminateDebugSession($"New Project"))
739 if(MenuWindowCloseAll(null, 0))
741 NewProjectDialog newProjectDialog;
745 projectView.visible = false;
746 if(!projectView.Destroy(0))
750 newProjectDialog = { master = this };
751 newProjectDialog.Modal();
754 ideSettings.AddRecentProject(projectView.fileName);
755 ide.UpdateRecentMenus();
756 settingsContainer.Save();
762 MenuItem projectOpenItem
764 projectMenu, $"Open...", o, Key { o, true, true };
765 bitmap = { ":actions/projOpen.png" };
766 bool NotifySelect(MenuItem selection, Modifiers mods)
768 if(ideSettings.ideProjectFileDialogLocation)
769 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
771 ideProjectFileDialog.text = openProjectFileDialogTitle;
772 if(ideProjectFileDialog.Modal() == ok)
774 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
775 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
780 MenuItem projectQuickItem
782 projectMenu, $"Quick...", q, f7, disabled = true;
783 bool NotifySelect(MenuItem selection, Modifiers mods)
786 QuickProjectDialog{ this }.Modal();
790 MenuItem projectAddItem
792 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
793 bitmap = { ":actions/projAdd.png" };
795 bool NotifySelect(MenuItem selection, Modifiers mods)
797 if(ideSettings.ideProjectFileDialogLocation)
798 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
800 ideProjectFileDialog.text = addProjectFileDialogTitle;
803 if(ideProjectFileDialog.Modal() == ok)
805 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
807 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
808 contents = $"Add a different project?" }.Modal() == no)
819 MenuItem projectCloseItem
821 projectMenu, $"Close", c, disabled = true;
822 bool NotifySelect(MenuItem selection, Modifiers mods)
826 if(!ide.DontTerminateDebugSession($"Project Close"))
828 if(findInFilesDialog)
829 findInFilesDialog.SearchStop();
830 projectView.visible = false;
831 if(projectView.Destroy(0))
832 MenuWindowCloseAll(null, 0);
834 char workingDir[MAX_LOCATION];
835 GetWorkingDir(workingDir, MAX_LOCATION);
836 findInFilesDialog.currentDirectory = workingDir;
837 ideMainFrame.text = titleECEREIDE;
844 MenuDivider { projectMenu };
845 MenuItem activeCompilerItem
847 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
848 bool NotifySelect(MenuItem selection, Modifiers mods)
850 projectView.MenuCompiler(null, mods);
854 MenuItem projectActiveConfigItem
856 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
857 bool NotifySelect(MenuItem selection, Modifiers mods)
859 projectView.MenuConfig(projectView.active ? selection : null, mods);
863 MenuItem projectSettingsItem
865 projectMenu, $"Settings...", s, altF7, disabled = true;
866 bool NotifySelect(MenuItem selection, Modifiers mods)
868 projectView.MenuSettings(projectView.active ? selection : null, mods);
872 MenuDivider { projectMenu };
873 MenuItem projectBrowseFolderItem
875 projectMenu, $"Browse Project Folder", p, disabled = true;
876 bool NotifySelect(MenuItem selection, Modifiers mods)
879 projectView.MenuBrowseFolder(null, mods);
883 MenuDivider { projectMenu };
884 MenuItem projectRunItem
886 projectMenu, $"Run", r, ctrlF5, disabled = true;
887 bitmap = { ":actions/run.png" };
888 bool NotifySelect(MenuItem selection, Modifiers mods)
891 projectView.Run(null, mods);
895 MenuItem projectBuildItem
897 projectMenu, $"Build", b, f7, disabled = true;
898 bitmap = { ":actions/build.png" };
899 bool NotifySelect(MenuItem selection, Modifiers mods)
902 projectView.ProjectBuild(projectView.active ? selection : null, mods);
906 MenuItem projectLinkItem
908 projectMenu, $"Relink", l, disabled = true;
909 bitmap = { ":actions/relink.png" };
910 bool NotifySelect(MenuItem selection, Modifiers mods)
913 projectView.ProjectLink(projectView.active ? selection : null, mods);
917 MenuItem projectRebuildItem
919 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
920 bitmap = { ":actions/rebuild.png" };
921 bool NotifySelect(MenuItem selection, Modifiers mods)
924 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
928 MenuItem projectCleanItem
930 projectMenu, $"Clean", e, disabled = true;
931 bitmap = { ":actions/clean.png" };
932 bool NotifySelect(MenuItem selection, Modifiers mods)
937 projectView.ProjectClean(projectView.active ? selection : null, mods);
942 MenuItem projectRealCleanItem
944 projectMenu, $"Real Clean", disabled = true;
945 bitmap = { ":actions/clean.png" };
946 bool NotifySelect(MenuItem selection, Modifiers mods)
951 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
956 MenuItem projectRegenerateItem
958 projectMenu, $"Regenerate Makefile", m, disabled = true;
959 bitmap = { ":actions/regMakefile.png" };
960 bool NotifySelect(MenuItem selection, Modifiers mods)
963 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
967 MenuItem projectCompileItem;
968 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
969 MenuItem debugStartResumeItem
971 debugMenu, $"Start", s, f5, disabled = true;
972 bitmap = { ":actions/debug.png" };
973 NotifySelect = MenuDebugStart;
975 bool MenuDebugStart(MenuItem selection, Modifiers mods)
979 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
980 if(!projectView.DebugStart())
981 debugStartResumeItem.disabled = false; // same exception
985 bool MenuDebugResume(MenuItem selection, Modifiers mods)
988 projectView.DebugResume();
991 MenuItem debugRestartItem
993 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
994 bitmap = { ":actions/restart.png" };
995 bool NotifySelect(MenuItem selection, Modifiers mods)
998 projectView.DebugRestart();
1002 MenuItem debugBreakItem
1004 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1005 bitmap = { ":actions/pause.png" };
1006 bool NotifySelect(MenuItem selection, Modifiers mods)
1009 projectView.DebugBreak();
1013 MenuItem debugStopItem
1015 debugMenu, $"Stop", p, shiftF5, disabled = true;
1016 bitmap = { ":actions/stopDebug.png" };
1017 bool NotifySelect(MenuItem selection, Modifiers mods)
1020 projectView.DebugStop();
1024 MenuDivider { debugMenu };
1025 MenuItem debugStepIntoItem
1027 debugMenu, $"Step Into", i, f11, disabled = true;
1028 bitmap = { ":actions/stepInto.png" };
1029 bool NotifySelect(MenuItem selection, Modifiers mods)
1032 projectView.DebugStepInto();
1036 MenuItem debugStepOverItem
1038 debugMenu, $"Step Over", v, f10, disabled = true;
1039 bitmap = { ":actions/stepOver.png" };
1040 bool NotifySelect(MenuItem selection, Modifiers mods)
1043 projectView.DebugStepOver(false);
1047 MenuItem debugStepOutItem
1049 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1050 bitmap = { ":actions/stepOut.png" };
1051 bool NotifySelect(MenuItem selection, Modifiers mods)
1054 projectView.DebugStepOut(false);
1058 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1059 MenuItem debugSkipStepOverItem
1061 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1062 bool NotifySelect(MenuItem selection, Modifiers mods)
1065 projectView.DebugStepOver(true);
1069 MenuItem debugSkipStepOutItem
1071 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1072 bitmap = { ":actions/skipBreaks.png" };
1073 bool NotifySelect(MenuItem selection, Modifiers mods)
1076 projectView.DebugStepOut(true);
1080 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1081 //MenuDivider { debugMenu };
1082 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1083 MenuPlacement imageMenu { menu, $"Image", i };
1084 Menu viewMenu { menu, $"View", v };
1085 MenuItem viewProjectItem
1087 viewMenu, $"Project View", j, alt0, disabled = true;
1088 bool NotifySelect(MenuItem selection, Modifiers mods)
1092 projectView.visible = true;
1093 projectView.Activate();
1098 MenuPlacement { viewMenu, $"View Designer" };
1099 MenuPlacement { viewMenu, $"View Code" };
1100 MenuPlacement { viewMenu, $"View Properties" };
1101 MenuPlacement { viewMenu, $"View Methods" };
1102 MenuItem viewDesignerItem
1104 viewMenu, $"View Designer", d, f8;
1105 bool NotifySelect(MenuItem selection, Modifiers mods)
1107 Window client = activeClient;
1108 Class dataType = client._class;
1109 if(!strcmp(dataType.name, "Designer"))
1111 client.visible = true;
1115 ((CodeEditor)client).ViewDesigner();
1119 MenuItem viewCodeItem
1121 viewMenu, $"View Code", c, f8;
1122 bool NotifySelect(MenuItem selection, Modifiers mods)
1124 Window client = activeClient;
1125 Class dataType = client._class;
1126 if(!strcmp(dataType.name, "Designer"))
1127 client = ((Designer)client).codeEditor;
1130 // Do this after so the caret isn't moved yet...
1131 client.visible = true;
1135 MenuItem viewPropertiesItem
1137 viewMenu, $"View Properties", p, f4;
1138 bool NotifySelect(MenuItem selection, Modifiers mods)
1140 sheet.visible = true;
1141 sheet.sheetSelected = properties;
1146 MenuItem viewMethodsItem
1148 viewMenu, $"View Methods", m, f4;
1149 bool NotifySelect(MenuItem selection, Modifiers mods)
1151 sheet.visible = true;
1152 sheet.sheetSelected = methods;
1157 MenuItem viewToolBoxItem
1159 viewMenu, $"View Toolbox", x, f12;
1160 bool NotifySelect(MenuItem selection, Modifiers mods)
1162 toolBox.visible = true;
1167 MenuItem viewOutputItem
1169 viewMenu, $"Output", o, alt2;
1170 bool NotifySelect(MenuItem selection, Modifiers mods)
1176 MenuItem viewWatchesItem
1178 viewMenu, $"Watches", w, alt3;
1179 bool NotifySelect(MenuItem selection, Modifiers mods)
1185 MenuItem viewThreadsItem
1187 viewMenu, $"Threads", t, alt4;
1188 bool NotifySelect(MenuItem selection, Modifiers mods)
1194 MenuItem viewBreakpointsItem
1196 viewMenu, $"Breakpoints", b, alt5;
1197 bool NotifySelect(MenuItem selection, Modifiers mods)
1199 breakpointsView.Show();
1203 MenuItem viewCallStackItem
1205 viewMenu, $"Call Stack", s, alt7;
1206 bool NotifySelect(MenuItem selection, Modifiers mods)
1208 callStackView.Show();
1212 MenuItem viewAllDebugViews
1214 viewMenu, $"All Debug Views", a, alt9;
1215 bool NotifySelect(MenuItem selection, Modifiers mods)
1220 callStackView.Show();
1221 breakpointsView.Show();
1225 #ifdef GDB_DEBUG_GUI
1226 MenuDivider { viewMenu };
1227 MenuItem viewGDBItem
1229 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1230 bool NotifySelect(MenuItem selection, Modifiers mods)
1237 MenuDivider { viewMenu };
1238 MenuItem viewColorPicker
1240 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1241 bool NotifySelect(MenuItem selection, Modifiers mods)
1243 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1244 colorPicker.Create();
1248 MenuDivider { viewMenu };
1252 viewMenu, "Full Screen", f, checkable = true;
1254 bool NotifySelect(MenuItem selection, Modifiers mods)
1256 app.fullScreen ^= true;
1258 anchor = { 0, 0, 0, 0 };
1263 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1264 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1265 Menu windowMenu { menu, $"Window", w };
1266 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1267 MenuDivider { windowMenu };
1268 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1269 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1270 MenuDivider { windowMenu };
1271 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1272 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1273 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1274 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1275 MenuDivider { windowMenu };
1276 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1277 Menu helpMenu { menu, $"Help", h };
1280 helpMenu, $"API Reference", r, f1;
1281 bool NotifySelect(MenuItem selection, Modifiers mods)
1283 Execute("documentor");
1287 MenuDivider { helpMenu };
1290 helpMenu, $"About...", a;
1291 bool NotifySelect(MenuItem selection, Modifiers mods)
1293 AboutIDE { master = this }.Modal();
1298 property ToolBox toolBox
1300 get { return toolBox; }
1303 property Sheet sheet
1305 get { return sheet; }
1308 property Project project
1310 get { return projectView ? projectView.project : null; }
1313 property Workspace workspace
1315 get { return projectView ? projectView.workspace : null; }
1318 FindInFilesDialog findInFilesDialog
1320 master = this, parent = this;
1321 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1325 #ifdef GDB_DEBUG_GUI
1328 master = this, parent = this;
1329 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1331 void OnCommand(char * string)
1334 ide.debugger.SendGDBCommand(string);
1339 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1341 //app.driver = app.drivers[selection.id];
1343 app.driver = selection.id ? "OpenGL" : "X";
1345 app.driver = selection.id ? "OpenGL" : "GDI";
1347 delete ideSettings.displayDriver;
1348 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1350 settingsContainer.Save();
1351 //SetDriverAndSkin();
1355 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1357 app.skin = app.skins[selection.id];
1362 void SetDriverAndSkin()
1365 for(c = 0; c < app.numSkins; c++)
1366 if(!strcmp(app.skins[c], app.skin))
1368 skinItems[c].checked = true;
1371 for(c = 0; c < app.numDrivers; c++)
1372 if(!strcmp(app.drivers[c], app.driver))
1374 driverItems[c].checked = true;
1379 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1381 Project project = workspace.projects.firstIterator.data;
1382 projectView = ProjectView
1385 fileName = fileName;
1387 void NotifyDestroyed(Window window, DialogResult result)
1390 text = titleECEREIDE;
1395 projectView.Create();
1396 RepositionWindows(false);
1398 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1399 projectView.workspace = workspace;
1400 projectView.project = project;
1401 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1405 ide.breakpointsView.LoadFromWorkspace();
1406 ide.watchesView.LoadFromWorkspace();
1408 findInFilesDialog.projectNodeField.userData = projectView;
1411 char fileName[MAX_LOCATION];
1412 strcpy(fileName, project.topNode.path);
1413 PathCat(fileName, project.topNode.name);
1418 bool GetDebugMenusDisabled()
1422 Project project = projectView.project;
1424 if(project.GetTargetType(project.config) == executable)
1431 void RepositionWindows(bool expand)
1436 bool inDebugMode = debugger.isActive;
1437 bool callStackVisible = expand ? false : callStackView.visible;
1438 bool threadsVisible = expand ? false : threadsView.visible;
1439 bool watchesVisible = expand ? false : watchesView.visible;
1440 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1441 bool toolBoxVisible = toolBox.visible;
1442 bool outputVisible = expand ? false : outputView.visible;
1443 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1444 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1446 for(child = firstChild; child; child = child.next)
1448 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1449 child._class == class(Sheet) || child._class == class(ProjectView))
1451 Anchor anchor = child.anchor;
1452 anchor.top = topDistance;
1453 anchor.bottom = bottomDistance;
1454 if(child._class == class(CodeEditor) || child._class == class(Designer))
1456 anchor.right = toolBoxVisible ? 150 : 0;
1458 child.anchor = anchor;
1462 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1463 child._class == class(BreakpointsView))
1464 child.visible = false;
1467 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1472 bool ShowCodeEditor()
1475 activeClient.Activate();
1476 else if(projectView)
1478 projectView.visible = true;
1479 projectView.Activate();
1483 sheet.visible = true;
1489 bool ShouldStopBuild()
1491 return projectView.stopBuild;
1494 void DocumentSaved(Window document, char * fileName)
1496 ideSettings.AddRecentFile(fileName);
1497 ide.UpdateRecentMenus();
1498 ide.AdjustFileMenus();
1499 settingsContainer.Save();
1502 bool Window::OnFileModified(FileChange fileChange, char * param)
1505 sprintf(temp, $"The document %s was modified by another application.\n"
1506 "Would you like to reload it and lose your changes?", this.fileName);
1507 if(MessageBox { type = yesNo, master = this/*.parent*/,
1508 text = $"Document has been modified", contents = temp }.Modal() == yes)
1510 char * fileName = CopyString(this.fileName);
1511 WindowState state = this.state;
1512 Anchor anchor = this.anchor;
1513 Size size = this.size;
1515 this.modifiedDocument = false;
1517 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1520 this.anchor = anchor;
1522 this.SetState(state, true, 0);
1530 void UpdateMakefiles()
1534 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1535 projectView.ShowOutputBuildLog(true);
1536 projectView.DisplayCompiler(compiler, false);
1537 for(prj : workspace.projects)
1538 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1545 bool unavailable = !project;
1547 projectAddItem.disabled = unavailable;
1548 toolBar.buttonAddProject.disabled = unavailable;
1550 activeCompilerItem.disabled = unavailable;
1551 projectActiveConfigItem.disabled = unavailable;
1552 projectSettingsItem.disabled = unavailable;
1554 projectBrowseFolderItem.disabled = unavailable;
1556 viewProjectItem.disabled = unavailable;
1563 property bool hasOpenedCodeEditors
1568 for(w = firstChild; w; w = w.next)
1569 if(w._class == class(CodeEditor) &&
1570 w.isDocument && !w.closing && w.visible && w.created &&
1571 w.fileName && w.fileName[0])
1577 void AdjustFileMenus()
1579 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1581 projectQuickItem.disabled = unavailable;
1584 void AdjustBuildMenus()
1586 bool unavailable = project && projectView.buildInProgress;
1588 projectNewItem.disabled = unavailable;
1589 toolBar.buttonNewProject.disabled = unavailable;
1590 projectOpenItem.disabled = unavailable;
1591 toolBar.buttonOpenProject.disabled = unavailable;
1593 unavailable = !project || projectView.buildInProgress;
1595 projectCloseItem.disabled = unavailable;
1596 // toolBar.buttonCloseProject.disabled = unavailable;
1598 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1599 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1600 projectBuildItem.disabled = unavailable;
1601 toolBar.buttonBuild.disabled = unavailable;
1602 projectLinkItem.disabled = unavailable;
1603 toolBar.buttonReLink.disabled = unavailable;
1604 projectRebuildItem.disabled = unavailable;
1605 toolBar.buttonRebuild.disabled = unavailable;
1606 projectCleanItem.disabled = unavailable;
1607 toolBar.buttonClean.disabled = unavailable;
1608 projectRealCleanItem.disabled = unavailable;
1609 // toolBar.buttonRealClean.disabled = unavailable;
1610 projectRegenerateItem.disabled = unavailable;
1611 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1612 projectCompileItem.disabled = unavailable;
1614 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1617 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0); if(menu) menu.disabled = unavailable;
1618 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
1619 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
1620 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
1621 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
1622 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1623 projectView.popupMenu.Update(null);
1627 void AdjustDebugMenus()
1629 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1630 projectView.buildInProgress == buildingMainProject;
1631 bool active = ide.debugger.isActive;
1632 bool executing = ide.debugger.state == running;
1633 //bool holding = ide.debugger.state == stopped;
1635 debugStartResumeItem.disabled = unavailable || executing;
1636 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1637 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1640 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1641 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1644 debugBreakItem.disabled = unavailable || !executing;
1645 debugStopItem.disabled = unavailable || !active;
1646 debugRestartItem.disabled = unavailable || !active;
1649 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1650 toolBar.buttonDebugStop.disabled = unavailable || !active;
1651 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1654 debugStepIntoItem.disabled = unavailable || executing;
1655 debugStepOverItem.disabled = unavailable || executing;
1656 debugStepOutItem.disabled = unavailable || executing || !active;
1657 debugSkipStepOverItem.disabled = unavailable || executing;
1658 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1661 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1662 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1663 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1664 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1665 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1667 if((Designer)GetActiveDesigner())
1669 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1672 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1673 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1678 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1680 char tempString[MAX_LOCATION];
1681 strcpy(tempString, directory);
1682 if(saveSettings && !projectView)
1684 ideSettings.ideFileDialogLocation = directory;
1685 settingsContainer.Save();
1688 ideFileDialog.currentDirectory = tempString;
1689 codeEditorFileDialog.currentDirectory = tempString;
1690 codeEditorFormFileDialog.currentDirectory = tempString;
1693 void ChangeProjectFileDialogDirectory(char * directory)
1695 ideSettings.ideProjectFileDialogLocation = directory;
1696 settingsContainer.Save();
1699 Window FindWindow(char * filePath)
1701 Window document = null;
1703 // TOCHECK: Do we need to change slashes here?
1704 for(document = firstChild; document; document = document.next)
1706 char * fileName = document.fileName;
1707 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1709 document.visible = true;
1710 document.Activate();
1717 bool DontTerminateDebugSession(char * title)
1719 if(debugger.isActive)
1721 if(MessageBox { type = yesNo, master = ide,
1722 contents = $"Do you want to terminate the debugging session in progress?",
1723 text = title }.Modal() == no)
1726 MessageBox msg { type = yesNo, master = ide,
1727 contents = "Do you want to terminate the debugging session in progress?",
1729 if(msg.Modal() == no)
1741 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1743 char extension[MAX_EXTENSION] = "";
1744 Window document = null;
1745 bool isProject = false;
1746 bool needFileModified = true;
1747 char winFilePath[MAX_LOCATION];
1748 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1752 GetExtension(filePath, extension);
1756 strcpy(extension, type);
1758 if(strcmp(extension, ProjectExtension))
1760 for(document = firstChild; document; document = document.next)
1762 char * fileName = document.fileName;
1763 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1765 document.visible = true;
1767 document.Activate();
1773 if(createIfFails == whatever)
1775 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1777 if(openMethod == normal)
1779 if(DontTerminateDebugSession($"Open Project"))
1782 if(MenuWindowCloseAll(null, 0))
1786 projectView.visible = false;
1787 projectView.Destroy(0);
1788 // Where did this come from? projectView = null;
1795 Workspace workspace = null;
1797 if(FileExists(filePath))
1799 if(!strcmp(extension, ProjectExtension))
1801 char workspaceFile[MAX_LOCATION];
1802 strcpy(workspaceFile, filePath);
1803 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1804 workspace = LoadWorkspace(workspaceFile, filePath);
1806 else if(!strcmp(extension, WorkspaceExtension))
1807 workspace = LoadWorkspace(filePath, null);
1810 //project = LoadProject(filePath);
1815 char absolutePath[MAX_LOCATION];
1816 CreateProjectView(workspace, filePath);
1817 document = projectView;
1819 workspace.DropInvalidBreakpoints();
1822 ide.projectView.ShowOutputBuildLog(true);
1824 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1825 ide.projectView.DisplayCompiler(compiler, false);
1830 char newWorkingDir[MAX_LOCATION];
1831 StripLastDirectory(filePath, newWorkingDir);
1832 ChangeFileDialogsDirectory(newWorkingDir, false);
1835 document.fileName = filePath;
1837 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1839 // this crashes on starting ide with epj file, solution please?
1840 // app.UpdateDisplay();
1842 workspace.holdTracking = true;
1843 for(ofi : workspace.openedFiles)
1845 if(ofi.state != closed)
1847 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1850 char fileName[MAX_LOCATION];
1852 GetLastDirectory(ofi.path, fileName);
1853 node = projectView.project.topNode.Find(fileName, true);
1855 node.EnsureVisible();
1859 workspace.holdTracking = false;
1861 workspace.timer.Start();
1863 findInFilesDialog.mode = FindInFilesMode::project;
1864 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1867 char location[MAX_LOCATION];
1868 StripLastDirectory(ide.project.topNode.path, location);
1869 ChangeProjectFileDialogDirectory(location);
1873 if(projectView.debugger)
1874 projectView.debugger.EvaluateWatches();
1881 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1883 ideProjectFileDialog.text = openProjectFileDialogTitle;
1884 if(ideProjectFileDialog.Modal() == cancel)
1886 filePath = ideProjectFileDialog.filePath;
1887 GetExtension(filePath, extension);
1898 else if(openMethod == add)
1903 char slashFilePath[MAX_LOCATION];
1904 GetSlashPathBuffer(slashFilePath, filePath);
1905 for(p : workspace.projects)
1907 if(!fstrcmp(p.filePath, slashFilePath))
1915 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1916 contents = $"This project is already present in workspace." }.Modal();
1920 prj = LoadProject(filePath);
1923 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1924 workspace.projects.Add(prj);
1926 projectView.AddNode(prj.topNode, null);
1927 workspace.modified = true;
1929 findInFilesDialog.AddProjectItem(prj);
1930 projectView.ShowOutputBuildLog(true);
1931 projectView.DisplayCompiler(compiler, false);
1932 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1936 char location[MAX_LOCATION];
1937 StripLastDirectory(prj.topNode.path, location);
1938 ChangeProjectFileDialogDirectory(location);
1941 // projectView is associated with the main project and not with the one just added but
1942 return projectView; // just to let the caller know something was opened
1950 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1951 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1952 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1954 if(FileExists(filePath))
1955 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1956 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1957 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1960 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1963 else if(!strcmp(extension, "3ds"))
1965 if(FileExists(filePath))
1966 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1967 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1968 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1972 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1975 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1976 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1977 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1978 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1979 !strcmp(extension, "js"))
1981 CodeEditor editor { parent = this, state = state, visible = false };
1982 editor.updatingCode = true;
1983 if(editor.LoadFile(filePath))
1986 editor.visible = true;
1990 needFileModified = false;
1994 CodeEditor editor { parent = this, state = state, visible = false };
1995 if(editor.LoadFile(filePath))
1998 editor.visible = true;
2002 needFileModified = false;
2005 if(document && (document._class == class(PictureEdit) ||
2006 document._class == class(ModelView)))
2011 document.fileName = filePath;
2012 if(workspace && !workspace.holdTracking)
2013 workspace.UpdateOpenedFileInfo(filePath, opened);
2017 if(!document && createIfFails != no)
2019 if(createIfFails != yes && !needFileModified &&
2020 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2021 createIfFails = yes;
2022 if(createIfFails == yes || createIfFails == whatever)
2024 document = (Window)NewCodeEditor(this, state, true);
2026 document.fileName = filePath;
2032 if(projectView && document._class == class(CodeEditor) && workspace)
2034 int lineNumber, position;
2036 CodeEditor editor = (CodeEditor)document;
2037 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2038 editor.openedFileInfo.holdTracking = true;
2039 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2040 position = Max(editor.openedFileInfo.position - 1, 0);
2041 editor.editBox.GoToLineNum(lineNumber);
2042 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2043 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2044 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2045 editor.editBox.scroll = scroll;
2046 editor.openedFileInfo.holdTracking = false;
2049 if(needFileModified)
2050 document.OnFileModified = OnFileModified;
2051 document.NotifySaved = DocumentSaved;
2054 ideSettings.AddRecentProject(document.fileName);
2056 ideSettings.AddRecentFile(document.fileName);
2057 ide.UpdateRecentMenus();
2058 ide.AdjustFileMenus();
2059 settingsContainer.Save();
2067 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2068 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2070 if(!parentClosing && ide.workspace)
2071 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2074 bool ModelView::ModelViewOnClose(bool parentClosing)
2076 if(!parentClosing && ide.workspace)
2077 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2080 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2082 if(!parentClosing && ide.workspace)
2083 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2088 void OnUnloadGraphics(Window window)
2090 display.ClearMaterials();
2091 display.ClearTextures();
2092 display.ClearMeshes();
2096 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2098 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2099 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2103 bool OnKeyDown(Key key, unichar ch)
2108 projectView.Update(null);
2111 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2114 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2120 void GoToError(const char * line)
2123 projectView.GoToError(line);
2126 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2129 char *colon = strchr(text, ':');
2130 char filePath[MAX_LOCATION];
2131 char completePath[MAX_LOCATION];
2132 int line = 0, col = 0;
2137 char * close = strchr(text, ')');
2141 strncpy(name, &text[4], close - text - 4);
2142 name[close - text - 4] = '\0';
2143 for(p : ide.workspace.projects)
2145 if(!strcmp(p.name, name))
2155 prj = project ? project : (dir ? null : ide.project);
2156 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2158 path = (colon - 1 > path) ? colon - 1 : path;
2159 colon = strstr(colon + 1, ":");
2161 while(isspace(*path)) path++;
2164 strncpy(filePath, path, colon - path);
2165 filePath[colon - path] = '\0';
2166 line = atoi(colon + 1);
2167 colon = strstr(colon + 1, ":");
2169 col = atoi(colon + 1);
2171 else if(path - 1 >= path && *(path - 1) == '\"')
2173 colon = strchr(path, '\"');
2176 strncpy(filePath, path, colon - path);
2177 filePath[colon - path] = '\0';
2182 strcpy(completePath, prj.topNode.path);
2183 else if(dir && dir[0])
2184 strcpy(completePath, dir);
2186 completePath[0] = '\0';
2187 PathCat(completePath, filePath);
2189 if(FileExists(completePath).isFile)
2191 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2192 if(codeEditor && line)
2194 EditBox editBox = codeEditor.editBox;
2195 editBox.GoToLineNum(line - 1);
2196 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2201 void OnRedraw(Surface surface)
2203 Bitmap bitmap = back.bitmap;
2205 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2208 void SheetSelected(SheetType sheetSelected)
2210 if(activeChild == sheet)
2212 if(sheetSelected == methods)
2214 viewPropertiesItem.accelerator = f4;
2215 viewPropertiesItem.parent = viewMenu;
2216 viewMethodsItem.parent = null;
2220 viewMethodsItem.accelerator = f4;
2221 viewMethodsItem.parent = viewMenu;
2222 viewPropertiesItem.parent = null;
2227 viewMethodsItem.parent = viewMenu;
2228 viewPropertiesItem.parent = viewMenu;
2229 if(sheetSelected == methods)
2231 viewMethodsItem.accelerator = f4;
2232 viewPropertiesItem.accelerator = 0;
2236 viewMethodsItem.accelerator = 0;
2237 viewPropertiesItem.accelerator = f4;
2242 void OnActivateClient(Window client, Window previous)
2244 //if(!client || client != previous)
2247 if(!client || client != previous)
2250 dataType = previous._class;
2251 if(previous && !strcmp(dataType.name, "CodeEditor"))
2253 ((CodeEditor)previous).UpdateFormCode();
2255 else if(previous && !strcmp(dataType.name, "Designer"))
2257 ((Designer)previous).codeEditor.UpdateFormCode();
2262 dataType = client._class;
2263 if(client && !strcmp(dataType.name, "CodeEditor"))
2265 CodeEditor codeEditor = (CodeEditor)client;
2266 SetPrivateModule(codeEditor.privateModule);
2267 SetCurrentContext(codeEditor.globalContext);
2268 SetTopContext(codeEditor.globalContext);
2269 SetGlobalContext(codeEditor.globalContext);
2271 SetDefines(&codeEditor.defines);
2272 SetImports(&codeEditor.imports);
2274 SetActiveDesigner(codeEditor.designer);
2276 sheet.codeEditor = codeEditor;
2277 toolBox.codeEditor = codeEditor;
2279 viewDesignerItem.parent = viewMenu;
2280 if(activeChild != codeEditor)
2282 viewCodeItem.parent = viewMenu;
2283 viewDesignerItem.accelerator = 0;
2284 viewCodeItem.accelerator = f8;
2288 viewCodeItem.parent = null;
2289 viewDesignerItem.accelerator = f8;
2292 else if(client && !strcmp(dataType.name, "Designer"))
2294 CodeEditor codeEditor = ((Designer)client).codeEditor;
2297 SetPrivateModule(codeEditor.privateModule);
2298 SetCurrentContext(codeEditor.globalContext);
2299 SetTopContext(codeEditor.globalContext);
2300 SetGlobalContext(codeEditor.globalContext);
2301 SetDefines(&codeEditor.defines);
2302 SetImports(&codeEditor.imports);
2306 SetPrivateModule(null);
2307 SetCurrentContext(null);
2308 SetTopContext(null);
2309 SetGlobalContext(null);
2314 SetActiveDesigner((Designer)client);
2316 sheet.codeEditor = codeEditor;
2317 toolBox.codeEditor = codeEditor;
2319 viewCodeItem.parent = viewMenu;
2320 if(activeChild != client)
2322 viewDesignerItem.parent = viewMenu;
2323 viewDesignerItem.accelerator = f8;
2324 viewCodeItem.accelerator = 0;
2328 viewDesignerItem.parent = null;
2329 viewCodeItem.accelerator = f8;
2335 sheet.codeEditor = null;
2336 toolBox.codeEditor = null;
2337 SetActiveDesigner(null);
2339 viewDesignerItem.parent = null;
2340 viewCodeItem.parent = null;
2343 SheetSelected(sheet.sheetSelected);
2346 projectCompileItem = null;
2351 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2353 CodeEditor codeEditor = (CodeEditor)client;
2354 EditBox editBox = codeEditor.editBox;
2356 statusBar.AddField(pos);
2358 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2359 statusBar.AddField(caps);
2361 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2362 statusBar.AddField(ovr);
2364 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2365 statusBar.AddField(num);
2367 //statusBar.text = "Ready";
2369 if(projectView && projectView.project)
2371 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2375 sprintf(name, $"Compile %s", node.name);
2376 projectCompileItem =
2378 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2380 bool NotifySelect(MenuItem selection, Modifiers mods)
2384 bool result = false;
2385 ProjectNode node = null;
2386 for(p : ide.workspace.projects)
2388 node = projectView.GetNodeFromWindow(activeClient, p);
2389 if(node && projectView.Compile(node))
2396 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2401 projectMenu.AddDynamic(projectCompileItem, ide, false);
2407 caps = ovr = num = null;
2412 bool OnClose(bool parentClosing)
2414 //return !projectView.buildInProgress;
2415 if(projectView && projectView.buildInProgress)
2417 if(DontTerminateDebugSession($"Close IDE"))
2419 if(findInFilesDialog)
2420 findInFilesDialog.SearchStop();
2423 workspace.timer.Stop();
2426 ideMainFrame.Destroy(0);
2433 for(c = 1; c<app.argc; c++)
2435 char fullPath[MAX_LOCATION];
2436 char parentPath[MAX_LOCATION];
2437 char ext[MAX_EXTENSION];
2439 FileAttribs dirAttribs;
2440 GetWorkingDir(fullPath, MAX_LOCATION);
2441 PathCat(fullPath, app.argv[c]);
2442 StripLastDirectory(fullPath, parentPath);
2443 GetExtension(app.argv[c], ext);
2444 isProject = !strcmpi(ext, "epj");
2446 if(isProject && c > 1) continue;
2448 // Create directory for projects (only)
2449 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2451 if(isProject && !FileExists(fullPath))
2453 // The NewProject will handle directory creation
2454 /*if(!dirAttribs.isDirectory)
2456 MakeDir(parentPath);
2457 dirAttribs = FileExists(parentPath);
2459 if(dirAttribs.isDirectory)*/
2461 char name[MAX_LOCATION];
2462 NewProjectDialog newProjectDialog;
2466 projectView.visible = false;
2467 if(!projectView.Destroy(0))
2471 newProjectDialog = { master = this };
2473 strcpy(name, app.argv[c]);
2474 StripExtension(name);
2475 GetLastDirectory(name, name);
2476 newProjectDialog.projectName.contents = name;
2477 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2478 newProjectDialog.locationEditBox.path = parentPath;
2479 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2481 newProjectDialog.Modal();
2484 ideSettings.AddRecentProject(projectView.fileName);
2485 ide.UpdateRecentMenus();
2486 settingsContainer.Save();
2489 // Open only one project
2493 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2501 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2504 projectView.visible = false;
2505 projectView.Destroy(0);
2508 #ifdef GDB_DEBUG_GUI
2509 gdbDialog.Destroy(0);
2514 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2518 char * oldPaths[128];
2519 String oldList = new char[maxPathLen];
2520 Array<String> newExePaths { };
2521 //Map<String, bool> exePathExists { };
2523 #if defined(__unix__) || defined(__APPLE__)
2524 Array<String> newLibPaths { };
2525 Map<String, bool> libPathExists { };
2530 for(prj : workspace.projects)
2532 DirExpression targetDirExp;
2534 // SKIP FIRST PROJECT...
2535 if(prj == workspace.projects.firstIterator.data) continue;
2537 // NOTE: Right now the additional project config dir will be
2538 // obtained when the debugger is started, so toggling it
2539 // while building will change which library gets used.
2540 // To go with the initial state, e.g. when F5 was pressed,
2541 // we nould need to keep a list of all project's active
2542 // config upon startup.
2543 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2545 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2549 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2550 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2554 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2555 if(cfg.targetType == sharedLibrary && cfg.debug)
2559 if(targetDirExp.dir)
2561 char buffer[MAX_LOCATION];
2562 #if defined(__WIN32__)
2563 Array<String> paths = newExePaths;
2565 Array<String> paths = newLibPaths;
2567 GetSystemPathBuffer(buffer, prj.topNode.path);
2568 PathCat(buffer, targetDirExp.dir);
2571 if(!fstrcmp(p, buffer))
2578 paths.Add(CopyString(buffer));
2580 delete targetDirExp;
2584 for(item : compiler.executableDirs)
2587 for(p : newExePaths)
2589 if(!fstrcmp(p, item))
2596 newExePaths.Add(CopySystemPath(item));
2599 GetEnvironment("PATH", oldList, maxPathLen);
2601 printf("Old value of PATH: %s\n", oldList);
2603 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2604 for(c = 0; c < count; c++)
2607 for(p : newExePaths)
2609 if(!fstrcmp(p, oldPaths[c]))
2616 newExePaths.Add(CopySystemPath(oldPaths[c]));
2620 for(path : newExePaths)
2621 len += strlen(path) + 1;
2622 newList = new char[len + 1];
2624 for(path : newExePaths)
2626 strcat(newList, path);
2627 strcat(newList, pathListSep);
2629 newList[len - 1] = '\0';
2630 SetEnvironment("PATH", newList);
2632 printf("New value of PATH: %s\n", newList);
2639 #if defined(__unix__) || defined(__APPLE__)
2641 for(item : compiler.libraryDirs)
2643 if(!libPathExists[item]) // fstrcmp should be used
2645 newLibPaths.Add(item);
2646 libPathExists[item] = true;
2650 #if defined(__APPLE__)
2651 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2653 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2656 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2658 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2659 for(c = 0; c < count; c++)
2661 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2663 newLibPaths.Add(oldPaths[c]);
2664 libPathExists[oldPaths[c]] = true;
2669 for(path : newLibPaths)
2670 len += strlen(path) + 1;
2671 newList = new char[len + 1];
2673 for(path : newLibPaths)
2675 strcat(newList, path);
2676 strcat(newList, pathListSep);
2678 newList[len - 1] = '\0';
2679 #if defined(__APPLE__)
2680 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2682 SetEnvironment("LD_LIBRARY_PATH", newList);
2685 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2690 delete libPathExists;
2693 if(compiler.distccEnabled && compiler.distccHosts)
2694 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2699 void DestroyTemporaryProjectDir()
2701 if(tmpPrjDir && tmpPrjDir[0])
2703 if(FileExists(tmpPrjDir).isDirectory)
2704 DestroyDir(tmpPrjDir);
2705 property::tmpPrjDir = null;
2711 // Graphics Driver Menu
2715 app.currentSkin.selectionColor = selectionColor;
2716 app.currentSkin.selectionText = selectionText;
2720 driverItems = new MenuItem[app.numDrivers];
2721 for(c = 0; c < app.numDrivers; c++)
2723 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2724 driverItems[c].id = c;
2725 driverItems[c].isRadio = true;
2728 driverItems = new MenuItem[2];
2729 #if defined(__unix__)
2730 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2731 driverItems[0].id = 0;
2732 driverItems[0].isRadio = true;
2734 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2735 driverItems[0].id = 0;
2736 driverItems[0].isRadio = true;
2738 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2739 driverItems[1].id = 1;
2740 driverItems[1].isRadio = true;
2742 /* skinItems = new MenuItem[app.numSkins];
2743 for(c = 0; c < app.numSkins; c++)
2745 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2746 skinItems[c].id = c;
2747 skinItems[c].isRadio = true;
2750 ideFileDialog.master = this;
2751 ideProjectFileDialog.master = this;
2753 //SetDriverAndSkin();
2757 void UpdateRecentMenus()
2760 Menu fileMenu = menu.FindMenu($"File");
2761 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2762 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2763 char itemName[MAX_LOCATION + 4];
2766 recentFiles.Clear();
2769 for(recent : ideSettings.recentFiles)
2771 sprintf(itemName, "%d %s", 1 + c, recent);
2772 MakeSystemPath(itemName);
2773 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2777 recentProjects.Clear();
2779 for(recent : ideSettings.recentProjects)
2781 sprintf(itemName, "%d %s", 1 + c, recent);
2782 MakeSystemPath(itemName);
2783 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2796 void DestroyDir(char * path)
2798 RecursiveDeleteFolderFSI fsi { };
2803 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2805 bool preserveRootFolder;
2807 void OutFolder(char * folderPath, bool isRoot)
2809 if(!(preserveRootFolder && isRoot))
2810 RemoveDir(folderPath);
2813 bool OnFile(char * filePath)
2815 DeleteFile(filePath);
2820 class IDEApp : GuiApplication
2822 //driver = "Win32Console";
2823 // driver = "OpenGL";
2828 SetLoggingMode(stdOut, null);
2829 //SetLoggingMode(debug, null);
2831 settingsContainer.Load();
2832 #if defined(__unix__) || defined(__APPLE__)
2833 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2835 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2837 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2841 desktop.text = titleECEREIDE;
2844 for(c = 1; c<app.argc; c++)
2846 char fullPath[MAX_LOCATION];
2847 GetWorkingDir(fullPath, MAX_LOCATION);
2848 PathCat(fullPath, app.argv[c]);
2849 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2856 IDEMainFrame ideMainFrame { };
2858 define app = ((IDEApp)__thisModule);
2860 define titleECEREIDE = $"ECERE IDE (Debug)";
2862 define titleECEREIDE = $"ECERE IDE";