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
647 fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" };
649 // For the toolbar button; clients can still override that for the menu item
650 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
652 Window w = activeClient;
654 w.MenuFileSave(null, 0);
658 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
659 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
660 MenuDivider { fileMenu };
663 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
664 bool NotifySelect(MenuItem selection, Modifiers mods)
666 findInFilesDialog.replaceMode = false;
667 findInFilesDialog.Show();
671 MenuItem replaceInFiles
673 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
674 bool NotifySelect(MenuItem selection, Modifiers mods)
676 findInFilesDialog.replaceMode = true;
677 findInFilesDialog.Show();
681 MenuDivider { fileMenu };
682 MenuItem globalSettingsItem
684 fileMenu, $"Global Settings...", g;
685 bool NotifySelect(MenuItem selection, Modifiers mods)
687 globalSettingsDialog.master = this;
688 if(ide.workspace && ide.workspace.compiler)
689 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
690 else if(ideSettings.defaultCompiler)
691 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
692 globalSettingsDialog.Modal();
696 MenuDivider { fileMenu };
697 Menu recentFiles { fileMenu, $"Recent Files", r };
698 Menu recentProjects { fileMenu, $"Recent Projects", p };
699 MenuDivider { fileMenu };
702 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
704 bool NotifySelect(MenuItem selection, Modifiers mods)
706 ideMainFrame.Destroy(0);
711 bool FileRecentFile(MenuItem selection, Modifiers mods)
714 for(file : ideSettings.recentFiles)
716 if(id == selection.id)
718 OpenFile(file, normal, true, null, no, normal);
726 bool FileRecentProject(MenuItem selection, Modifiers mods)
729 for(file : ideSettings.recentProjects)
731 if(id == selection.id)
733 OpenFile(file, normal, true, null, no, normal);
741 MenuPlacement editMenu { menu, $"Edit", e };
743 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
744 MenuItem projectNewItem
746 projectMenu, $"New...", n, Key { n, true, true };
747 bitmap = { ":actions/projNew.png" };
748 bool NotifySelect(MenuItem selection, Modifiers mods)
750 if(!DontTerminateDebugSession($"New Project"))
751 if(MenuWindowCloseAll(null, 0))
753 NewProjectDialog newProjectDialog;
757 projectView.visible = false;
758 if(!projectView.Destroy(0))
762 newProjectDialog = { master = this };
763 newProjectDialog.Modal();
766 ideSettings.AddRecentProject(projectView.fileName);
767 ide.UpdateRecentMenus();
768 settingsContainer.Save();
774 MenuItem projectOpenItem
776 projectMenu, $"Open...", o, Key { o, true, true };
777 bitmap = { ":actions/projOpen.png" };
778 bool NotifySelect(MenuItem selection, Modifiers mods)
780 if(ideSettings.ideProjectFileDialogLocation)
781 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
783 ideProjectFileDialog.text = openProjectFileDialogTitle;
784 if(ideProjectFileDialog.Modal() == ok)
786 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
787 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
792 MenuItem projectQuickItem
794 projectMenu, $"Quick...", q, f7, disabled = true;
795 bool NotifySelect(MenuItem selection, Modifiers mods)
798 QuickProjectDialog{ this }.Modal();
802 MenuItem projectAddItem
804 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
805 bitmap = { ":actions/projAdd.png" };
807 bool NotifySelect(MenuItem selection, Modifiers mods)
809 if(ideSettings.ideProjectFileDialogLocation)
810 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
812 ideProjectFileDialog.text = addProjectFileDialogTitle;
815 if(ideProjectFileDialog.Modal() == ok)
817 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
819 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
820 contents = $"Add a different project?" }.Modal() == no)
831 MenuItem projectCloseItem
833 projectMenu, $"Close", c, disabled = true;
834 bool NotifySelect(MenuItem selection, Modifiers mods)
838 if(!ide.DontTerminateDebugSession($"Project Close"))
840 if(findInFilesDialog)
841 findInFilesDialog.SearchStop();
842 projectView.visible = false;
843 if(projectView.Destroy(0))
844 MenuWindowCloseAll(null, 0);
846 char workingDir[MAX_LOCATION];
847 GetWorkingDir(workingDir, MAX_LOCATION);
848 findInFilesDialog.currentDirectory = workingDir;
849 ideMainFrame.text = titleECEREIDE;
856 MenuDivider { projectMenu };
857 MenuItem activeCompilerItem
859 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
860 bool NotifySelect(MenuItem selection, Modifiers mods)
862 projectView.MenuCompiler(null, mods);
866 MenuItem projectActiveConfigItem
868 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
869 bool NotifySelect(MenuItem selection, Modifiers mods)
871 projectView.MenuConfig(projectView.active ? selection : null, mods);
875 MenuItem projectSettingsItem
877 projectMenu, $"Settings...", s, altF7, disabled = true;
878 bool NotifySelect(MenuItem selection, Modifiers mods)
880 projectView.MenuSettings(projectView.active ? selection : null, mods);
884 MenuDivider { projectMenu };
885 MenuItem projectBrowseFolderItem
887 projectMenu, $"Browse Project Folder", p, disabled = true;
888 bool NotifySelect(MenuItem selection, Modifiers mods)
891 projectView.MenuBrowseFolder(null, mods);
895 MenuDivider { projectMenu };
896 MenuItem projectRunItem
898 projectMenu, $"Run", r, ctrlF5, disabled = true;
899 bitmap = { ":actions/run.png" };
900 bool NotifySelect(MenuItem selection, Modifiers mods)
903 projectView.Run(null, mods);
907 MenuItem projectBuildItem
909 projectMenu, $"Build", b, f7, disabled = true;
910 bitmap = { ":actions/build.png" };
911 bool NotifySelect(MenuItem selection, Modifiers mods)
914 projectView.ProjectBuild(projectView.active ? selection : null, mods);
918 MenuItem projectLinkItem
920 projectMenu, $"Relink", l, disabled = true;
921 bitmap = { ":actions/relink.png" };
922 bool NotifySelect(MenuItem selection, Modifiers mods)
925 projectView.ProjectLink(projectView.active ? selection : null, mods);
929 MenuItem projectRebuildItem
931 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
932 bitmap = { ":actions/rebuild.png" };
933 bool NotifySelect(MenuItem selection, Modifiers mods)
936 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
940 MenuItem projectCleanItem
942 projectMenu, $"Clean", e, disabled = true;
943 bitmap = { ":actions/clean.png" };
944 bool NotifySelect(MenuItem selection, Modifiers mods)
949 projectView.ProjectClean(projectView.active ? selection : null, mods);
954 MenuItem projectRealCleanItem
956 projectMenu, $"Real Clean", disabled = true;
957 bitmap = { ":actions/clean.png" };
958 bool NotifySelect(MenuItem selection, Modifiers mods)
963 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
968 MenuItem projectRegenerateItem
970 projectMenu, $"Regenerate Makefile", m, disabled = true;
971 bitmap = { ":actions/regMakefile.png" };
972 bool NotifySelect(MenuItem selection, Modifiers mods)
975 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
979 MenuItem projectCompileItem;
980 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
981 MenuItem debugStartResumeItem
983 debugMenu, $"Start", s, f5, disabled = true;
984 bitmap = { ":actions/debug.png" };
985 NotifySelect = MenuDebugStart;
987 bool MenuDebugStart(MenuItem selection, Modifiers mods)
991 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
992 if(!projectView.DebugStart())
993 debugStartResumeItem.disabled = false; // same exception
997 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1000 projectView.DebugResume();
1003 MenuItem debugRestartItem
1005 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1006 bitmap = { ":actions/restart.png" };
1007 bool NotifySelect(MenuItem selection, Modifiers mods)
1010 projectView.DebugRestart();
1014 MenuItem debugBreakItem
1016 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1017 bitmap = { ":actions/pause.png" };
1018 bool NotifySelect(MenuItem selection, Modifiers mods)
1021 projectView.DebugBreak();
1025 MenuItem debugStopItem
1027 debugMenu, $"Stop", p, shiftF5, disabled = true;
1028 bitmap = { ":actions/stopDebug.png" };
1029 bool NotifySelect(MenuItem selection, Modifiers mods)
1032 projectView.DebugStop();
1036 MenuDivider { debugMenu };
1037 MenuItem debugStepIntoItem
1039 debugMenu, $"Step Into", i, f11, disabled = true;
1040 bitmap = { ":actions/stepInto.png" };
1041 bool NotifySelect(MenuItem selection, Modifiers mods)
1044 projectView.DebugStepInto();
1048 MenuItem debugStepOverItem
1050 debugMenu, $"Step Over", v, f10, disabled = true;
1051 bitmap = { ":actions/stepOver.png" };
1052 bool NotifySelect(MenuItem selection, Modifiers mods)
1055 projectView.DebugStepOver(false);
1059 MenuItem debugStepOutItem
1061 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1062 bitmap = { ":actions/stepOut.png" };
1063 bool NotifySelect(MenuItem selection, Modifiers mods)
1066 projectView.DebugStepOut(false);
1070 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1071 MenuItem debugSkipStepOverItem
1073 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1074 bool NotifySelect(MenuItem selection, Modifiers mods)
1077 projectView.DebugStepOver(true);
1081 MenuItem debugSkipStepOutItem
1083 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1084 bitmap = { ":actions/skipBreaks.png" };
1085 bool NotifySelect(MenuItem selection, Modifiers mods)
1088 projectView.DebugStepOut(true);
1092 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1093 //MenuDivider { debugMenu };
1094 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1095 MenuPlacement imageMenu { menu, $"Image", i };
1096 Menu viewMenu { menu, $"View", v };
1097 MenuItem viewProjectItem
1099 viewMenu, $"Project View", j, alt0, disabled = true;
1100 bool NotifySelect(MenuItem selection, Modifiers mods)
1104 projectView.visible = true;
1105 projectView.Activate();
1110 MenuPlacement { viewMenu, $"View Designer" };
1111 MenuPlacement { viewMenu, $"View Code" };
1112 MenuPlacement { viewMenu, $"View Properties" };
1113 MenuPlacement { viewMenu, $"View Methods" };
1114 MenuItem viewDesignerItem
1116 viewMenu, $"View Designer", d, f8;
1117 bool NotifySelect(MenuItem selection, Modifiers mods)
1119 Window client = activeClient;
1120 Class dataType = client._class;
1121 if(!strcmp(dataType.name, "Designer"))
1123 client.visible = true;
1127 ((CodeEditor)client).ViewDesigner();
1131 MenuItem viewCodeItem
1133 viewMenu, $"View Code", c, f8;
1134 bool NotifySelect(MenuItem selection, Modifiers mods)
1136 Window client = activeClient;
1137 Class dataType = client._class;
1138 if(!strcmp(dataType.name, "Designer"))
1139 client = ((Designer)client).codeEditor;
1142 // Do this after so the caret isn't moved yet...
1143 client.visible = true;
1147 MenuItem viewPropertiesItem
1149 viewMenu, $"View Properties", p, f4;
1150 bool NotifySelect(MenuItem selection, Modifiers mods)
1152 sheet.visible = true;
1153 sheet.sheetSelected = properties;
1158 MenuItem viewMethodsItem
1160 viewMenu, $"View Methods", m, f4;
1161 bool NotifySelect(MenuItem selection, Modifiers mods)
1163 sheet.visible = true;
1164 sheet.sheetSelected = methods;
1169 MenuItem viewToolBoxItem
1171 viewMenu, $"View Toolbox", x, f12;
1172 bool NotifySelect(MenuItem selection, Modifiers mods)
1174 toolBox.visible = true;
1179 MenuItem viewOutputItem
1181 viewMenu, $"Output", o, alt2;
1182 bool NotifySelect(MenuItem selection, Modifiers mods)
1188 MenuItem viewWatchesItem
1190 viewMenu, $"Watches", w, alt3;
1191 bool NotifySelect(MenuItem selection, Modifiers mods)
1197 MenuItem viewThreadsItem
1199 viewMenu, $"Threads", t, alt4;
1200 bool NotifySelect(MenuItem selection, Modifiers mods)
1206 MenuItem viewBreakpointsItem
1208 viewMenu, $"Breakpoints", b, alt5;
1209 bool NotifySelect(MenuItem selection, Modifiers mods)
1211 breakpointsView.Show();
1215 MenuItem viewCallStackItem
1217 viewMenu, $"Call Stack", s, alt7;
1218 bool NotifySelect(MenuItem selection, Modifiers mods)
1220 callStackView.Show();
1224 MenuItem viewAllDebugViews
1226 viewMenu, $"All Debug Views", a, alt9;
1227 bool NotifySelect(MenuItem selection, Modifiers mods)
1232 callStackView.Show();
1233 breakpointsView.Show();
1237 #ifdef GDB_DEBUG_GUI
1238 MenuDivider { viewMenu };
1239 MenuItem viewGDBItem
1241 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1242 bool NotifySelect(MenuItem selection, Modifiers mods)
1249 MenuDivider { viewMenu };
1250 MenuItem viewColorPicker
1252 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1253 bool NotifySelect(MenuItem selection, Modifiers mods)
1255 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1256 colorPicker.Create();
1260 MenuDivider { viewMenu };
1264 viewMenu, "Full Screen", f, checkable = true;
1266 bool NotifySelect(MenuItem selection, Modifiers mods)
1268 app.fullScreen ^= true;
1270 anchor = { 0, 0, 0, 0 };
1275 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1276 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1277 Menu windowMenu { menu, $"Window", w };
1278 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1279 MenuDivider { windowMenu };
1280 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1281 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1282 MenuDivider { windowMenu };
1283 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1284 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1285 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1286 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1287 MenuDivider { windowMenu };
1288 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1289 Menu helpMenu { menu, $"Help", h };
1292 helpMenu, $"API Reference", r, f1;
1293 bool NotifySelect(MenuItem selection, Modifiers mods)
1295 Execute("documentor");
1299 MenuDivider { helpMenu };
1302 helpMenu, $"About...", a;
1303 bool NotifySelect(MenuItem selection, Modifiers mods)
1305 AboutIDE { master = this }.Modal();
1310 property ToolBox toolBox
1312 get { return toolBox; }
1315 property Sheet sheet
1317 get { return sheet; }
1320 property Project project
1322 get { return projectView ? projectView.project : null; }
1325 property Workspace workspace
1327 get { return projectView ? projectView.workspace : null; }
1330 FindInFilesDialog findInFilesDialog
1332 master = this, parent = this;
1333 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1337 #ifdef GDB_DEBUG_GUI
1340 master = this, parent = this;
1341 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1343 void OnCommand(char * string)
1346 ide.debugger.SendGDBCommand(string);
1351 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1353 //app.driver = app.drivers[selection.id];
1355 app.driver = selection.id ? "OpenGL" : "X";
1357 app.driver = selection.id ? "OpenGL" : "GDI";
1359 delete ideSettings.displayDriver;
1360 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1362 settingsContainer.Save();
1363 //SetDriverAndSkin();
1367 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1369 app.skin = app.skins[selection.id];
1374 void SetDriverAndSkin()
1377 for(c = 0; c < app.numSkins; c++)
1378 if(!strcmp(app.skins[c], app.skin))
1380 skinItems[c].checked = true;
1383 for(c = 0; c < app.numDrivers; c++)
1384 if(!strcmp(app.drivers[c], app.driver))
1386 driverItems[c].checked = true;
1391 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1393 Project project = workspace.projects.firstIterator.data;
1394 projectView = ProjectView
1397 fileName = fileName;
1399 void NotifyDestroyed(Window window, DialogResult result)
1402 text = titleECEREIDE;
1407 projectView.Create();
1408 RepositionWindows(false);
1410 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1411 projectView.workspace = workspace;
1412 projectView.project = project;
1413 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1417 ide.breakpointsView.LoadFromWorkspace();
1418 ide.watchesView.LoadFromWorkspace();
1420 findInFilesDialog.projectNodeField.userData = projectView;
1423 char fileName[MAX_LOCATION];
1424 strcpy(fileName, project.topNode.path);
1425 PathCat(fileName, project.topNode.name);
1430 bool GetDebugMenusDisabled()
1434 Project project = projectView.project;
1436 if(project.GetTargetType(project.config) == executable)
1443 void RepositionWindows(bool expand)
1448 bool inDebugMode = debugger.isActive;
1449 bool callStackVisible = expand ? false : callStackView.visible;
1450 bool threadsVisible = expand ? false : threadsView.visible;
1451 bool watchesVisible = expand ? false : watchesView.visible;
1452 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1453 bool toolBoxVisible = toolBox.visible;
1454 bool outputVisible = expand ? false : outputView.visible;
1455 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1456 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1458 for(child = firstChild; child; child = child.next)
1460 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1461 child._class == class(Sheet) || child._class == class(ProjectView))
1463 Anchor anchor = child.anchor;
1464 anchor.top = topDistance;
1465 anchor.bottom = bottomDistance;
1466 if(child._class == class(CodeEditor) || child._class == class(Designer))
1468 anchor.right = toolBoxVisible ? 150 : 0;
1470 child.anchor = anchor;
1474 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1475 child._class == class(BreakpointsView))
1476 child.visible = false;
1479 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1484 bool ShowCodeEditor()
1487 activeClient.Activate();
1488 else if(projectView)
1490 projectView.visible = true;
1491 projectView.Activate();
1495 sheet.visible = true;
1501 bool ShouldStopBuild()
1503 return projectView.stopBuild;
1506 void DocumentSaved(Window document, char * fileName)
1508 ideSettings.AddRecentFile(fileName);
1509 ide.UpdateRecentMenus();
1510 ide.AdjustFileMenus();
1511 settingsContainer.Save();
1514 bool Window::OnFileModified(FileChange fileChange, char * param)
1517 sprintf(temp, $"The document %s was modified by another application.\n"
1518 "Would you like to reload it and lose your changes?", this.fileName);
1519 if(MessageBox { type = yesNo, master = this/*.parent*/,
1520 text = $"Document has been modified", contents = temp }.Modal() == yes)
1522 char * fileName = CopyString(this.fileName);
1523 WindowState state = this.state;
1524 Anchor anchor = this.anchor;
1525 Size size = this.size;
1527 this.modifiedDocument = false;
1529 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1532 this.anchor = anchor;
1534 this.SetState(state, true, 0);
1542 void UpdateMakefiles()
1546 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1547 projectView.ShowOutputBuildLog(true);
1548 projectView.DisplayCompiler(compiler, false);
1549 for(prj : workspace.projects)
1550 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1557 bool unavailable = !project;
1559 projectAddItem.disabled = unavailable;
1560 toolBar.buttonAddProject.disabled = unavailable;
1562 activeCompilerItem.disabled = unavailable;
1563 projectActiveConfigItem.disabled = unavailable;
1564 projectSettingsItem.disabled = unavailable;
1566 projectBrowseFolderItem.disabled = unavailable;
1568 viewProjectItem.disabled = unavailable;
1575 property bool hasOpenedCodeEditors
1580 for(w = firstChild; w; w = w.next)
1581 if(w._class == class(CodeEditor) &&
1582 w.isDocument && !w.closing && w.visible && w.created &&
1583 w.fileName && w.fileName[0])
1589 void AdjustFileMenus()
1591 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1593 projectQuickItem.disabled = unavailable;
1596 void AdjustBuildMenus()
1598 bool unavailable = project && projectView.buildInProgress;
1600 projectNewItem.disabled = unavailable;
1601 toolBar.buttonNewProject.disabled = unavailable;
1602 projectOpenItem.disabled = unavailable;
1603 toolBar.buttonOpenProject.disabled = unavailable;
1605 unavailable = !project || projectView.buildInProgress;
1607 projectCloseItem.disabled = unavailable;
1608 // toolBar.buttonCloseProject.disabled = unavailable;
1610 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1611 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1612 projectBuildItem.disabled = unavailable;
1613 toolBar.buttonBuild.disabled = unavailable;
1614 projectLinkItem.disabled = unavailable;
1615 toolBar.buttonReLink.disabled = unavailable;
1616 projectRebuildItem.disabled = unavailable;
1617 toolBar.buttonRebuild.disabled = unavailable;
1618 projectCleanItem.disabled = unavailable;
1619 toolBar.buttonClean.disabled = unavailable;
1620 projectRealCleanItem.disabled = unavailable;
1621 // toolBar.buttonRealClean.disabled = unavailable;
1622 projectRegenerateItem.disabled = unavailable;
1623 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1624 projectCompileItem.disabled = unavailable;
1626 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1629 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0); if(menu) menu.disabled = unavailable;
1630 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
1631 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
1632 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
1633 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
1634 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1635 projectView.popupMenu.Update(null);
1639 void AdjustDebugMenus()
1641 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1642 projectView.buildInProgress == buildingMainProject;
1643 bool active = ide.debugger.isActive;
1644 bool executing = ide.debugger.state == running;
1645 //bool holding = ide.debugger.state == stopped;
1647 debugStartResumeItem.disabled = unavailable || executing;
1648 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1649 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1652 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1653 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1656 debugBreakItem.disabled = unavailable || !executing;
1657 debugStopItem.disabled = unavailable || !active;
1658 debugRestartItem.disabled = unavailable || !active;
1661 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1662 toolBar.buttonDebugStop.disabled = unavailable || !active;
1663 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1666 debugStepIntoItem.disabled = unavailable || executing;
1667 debugStepOverItem.disabled = unavailable || executing;
1668 debugStepOutItem.disabled = unavailable || executing || !active;
1669 debugSkipStepOverItem.disabled = unavailable || executing;
1670 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1673 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1674 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1675 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1676 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1677 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1679 if((Designer)GetActiveDesigner())
1681 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1684 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1685 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1690 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1692 char tempString[MAX_LOCATION];
1693 strcpy(tempString, directory);
1694 if(saveSettings && !projectView)
1696 ideSettings.ideFileDialogLocation = directory;
1697 settingsContainer.Save();
1700 ideFileDialog.currentDirectory = tempString;
1701 codeEditorFileDialog.currentDirectory = tempString;
1702 codeEditorFormFileDialog.currentDirectory = tempString;
1705 void ChangeProjectFileDialogDirectory(char * directory)
1707 ideSettings.ideProjectFileDialogLocation = directory;
1708 settingsContainer.Save();
1711 Window FindWindow(char * filePath)
1713 Window document = null;
1715 // TOCHECK: Do we need to change slashes here?
1716 for(document = firstChild; document; document = document.next)
1718 char * fileName = document.fileName;
1719 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1721 document.visible = true;
1722 document.Activate();
1729 bool DontTerminateDebugSession(char * title)
1731 if(debugger.isActive)
1733 if(MessageBox { type = yesNo, master = ide,
1734 contents = $"Do you want to terminate the debugging session in progress?",
1735 text = title }.Modal() == no)
1738 MessageBox msg { type = yesNo, master = ide,
1739 contents = "Do you want to terminate the debugging session in progress?",
1741 if(msg.Modal() == no)
1753 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1755 char extension[MAX_EXTENSION] = "";
1756 Window document = null;
1757 bool isProject = false;
1758 bool needFileModified = true;
1759 char winFilePath[MAX_LOCATION];
1760 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1764 GetExtension(filePath, extension);
1768 strcpy(extension, type);
1770 if(strcmp(extension, ProjectExtension))
1772 for(document = firstChild; document; document = document.next)
1774 char * fileName = document.fileName;
1775 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1777 document.visible = true;
1779 document.Activate();
1785 if(createIfFails == whatever)
1787 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1789 needFileModified = false;
1790 if(openMethod == normal)
1792 if(DontTerminateDebugSession($"Open Project"))
1795 if(MenuWindowCloseAll(null, 0))
1799 projectView.visible = false;
1800 projectView.Destroy(0);
1801 // Where did this come from? projectView = null;
1808 Workspace workspace = null;
1810 if(FileExists(filePath))
1812 if(!strcmp(extension, ProjectExtension))
1814 char workspaceFile[MAX_LOCATION];
1815 strcpy(workspaceFile, filePath);
1816 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1817 workspace = LoadWorkspace(workspaceFile, filePath);
1819 else if(!strcmp(extension, WorkspaceExtension))
1820 workspace = LoadWorkspace(filePath, null);
1823 //project = LoadProject(filePath);
1828 char absolutePath[MAX_LOCATION];
1829 CreateProjectView(workspace, filePath);
1830 document = projectView;
1832 workspace.DropInvalidBreakpoints();
1835 ide.projectView.ShowOutputBuildLog(true);
1837 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1838 ide.projectView.DisplayCompiler(compiler, false);
1843 char newWorkingDir[MAX_LOCATION];
1844 StripLastDirectory(filePath, newWorkingDir);
1845 ChangeFileDialogsDirectory(newWorkingDir, false);
1848 document.fileName = filePath;
1850 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1852 // this crashes on starting ide with epj file, solution please?
1853 // app.UpdateDisplay();
1855 workspace.holdTracking = true;
1856 for(ofi : workspace.openedFiles)
1858 if(ofi.state != closed)
1860 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1863 char fileName[MAX_LOCATION];
1865 GetLastDirectory(ofi.path, fileName);
1866 node = projectView.project.topNode.Find(fileName, true);
1868 node.EnsureVisible();
1872 workspace.holdTracking = false;
1874 workspace.timer.Start();
1876 findInFilesDialog.mode = FindInFilesMode::project;
1877 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1880 char location[MAX_LOCATION];
1881 StripLastDirectory(ide.project.topNode.path, location);
1882 ChangeProjectFileDialogDirectory(location);
1886 if(projectView.debugger)
1887 projectView.debugger.EvaluateWatches();
1894 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1896 ideProjectFileDialog.text = openProjectFileDialogTitle;
1897 if(ideProjectFileDialog.Modal() == cancel)
1899 filePath = ideProjectFileDialog.filePath;
1900 GetExtension(filePath, extension);
1911 else if(openMethod == add)
1916 char slashFilePath[MAX_LOCATION];
1917 GetSlashPathBuffer(slashFilePath, filePath);
1918 for(p : workspace.projects)
1920 if(!fstrcmp(p.filePath, slashFilePath))
1928 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1929 contents = $"This project is already present in workspace." }.Modal();
1933 prj = LoadProject(filePath);
1936 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1937 prj.StartMonitoring();
1938 workspace.projects.Add(prj);
1940 projectView.AddNode(prj.topNode, null);
1941 workspace.modified = true;
1943 findInFilesDialog.AddProjectItem(prj);
1944 projectView.ShowOutputBuildLog(true);
1945 projectView.DisplayCompiler(compiler, false);
1946 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1950 char location[MAX_LOCATION];
1951 StripLastDirectory(prj.topNode.path, location);
1952 ChangeProjectFileDialogDirectory(location);
1955 // projectView is associated with the main project and not with the one just added but
1956 return projectView; // just to let the caller know something was opened
1964 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1965 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1966 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1968 if(FileExists(filePath))
1969 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1970 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1971 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1974 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1977 else if(!strcmp(extension, "3ds"))
1979 if(FileExists(filePath))
1980 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1981 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1982 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1986 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1989 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1990 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1991 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1992 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1993 !strcmp(extension, "js"))
1995 CodeEditor editor { parent = this, state = state, visible = false };
1996 editor.updatingCode = true;
1997 if(editor.LoadFile(filePath))
2000 editor.visible = true;
2004 needFileModified = false;
2008 CodeEditor editor { parent = this, state = state, visible = false };
2009 if(editor.LoadFile(filePath))
2012 editor.visible = true;
2016 needFileModified = false;
2019 if(document && (document._class == class(PictureEdit) ||
2020 document._class == class(ModelView)))
2025 document.fileName = filePath;
2026 if(workspace && !workspace.holdTracking)
2027 workspace.UpdateOpenedFileInfo(filePath, opened);
2031 if(!document && createIfFails != no)
2033 if(createIfFails != yes && !needFileModified &&
2034 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2035 createIfFails = yes;
2036 if(createIfFails == yes || createIfFails == whatever)
2038 document = (Window)NewCodeEditor(this, state, true);
2040 document.fileName = filePath;
2046 if(projectView && document._class == class(CodeEditor) && workspace)
2048 int lineNumber, position;
2050 CodeEditor editor = (CodeEditor)document;
2051 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2052 editor.openedFileInfo.holdTracking = true;
2053 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2054 position = Max(editor.openedFileInfo.position - 1, 0);
2055 editor.editBox.GoToLineNum(lineNumber);
2056 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2057 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2058 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2059 editor.editBox.scroll = scroll;
2060 editor.openedFileInfo.holdTracking = false;
2063 if(needFileModified)
2064 document.OnFileModified = OnFileModified;
2065 document.NotifySaved = DocumentSaved;
2068 ideSettings.AddRecentProject(document.fileName);
2070 ideSettings.AddRecentFile(document.fileName);
2071 ide.UpdateRecentMenus();
2072 ide.AdjustFileMenus();
2073 settingsContainer.Save();
2081 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2082 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2084 if(!parentClosing && ide.workspace)
2085 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2088 bool ModelView::ModelViewOnClose(bool parentClosing)
2090 if(!parentClosing && ide.workspace)
2091 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2094 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2096 if(!parentClosing && ide.workspace)
2097 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2102 void OnUnloadGraphics(Window window)
2104 display.ClearMaterials();
2105 display.ClearTextures();
2106 display.ClearMeshes();
2110 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2112 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2113 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2117 bool OnKeyDown(Key key, unichar ch)
2122 projectView.Update(null);
2125 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2128 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2134 void GoToError(const char * line)
2137 projectView.GoToError(line);
2140 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2143 char *colon = strchr(text, ':');
2144 char filePath[MAX_LOCATION];
2145 char completePath[MAX_LOCATION];
2146 int line = 0, col = 0;
2151 char * close = strchr(text, ')');
2155 strncpy(name, &text[4], close - text - 4);
2156 name[close - text - 4] = '\0';
2157 for(p : ide.workspace.projects)
2159 if(!strcmp(p.name, name))
2169 prj = project ? project : (dir ? null : ide.project);
2170 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2172 path = (colon - 1 > path) ? colon - 1 : path;
2173 colon = strstr(colon + 1, ":");
2175 while(isspace(*path)) path++;
2178 strncpy(filePath, path, colon - path);
2179 filePath[colon - path] = '\0';
2180 line = atoi(colon + 1);
2181 colon = strstr(colon + 1, ":");
2183 col = atoi(colon + 1);
2185 else if(path - 1 >= path && *(path - 1) == '\"')
2187 colon = strchr(path, '\"');
2190 strncpy(filePath, path, colon - path);
2191 filePath[colon - path] = '\0';
2196 strcpy(completePath, prj.topNode.path);
2197 else if(dir && dir[0])
2198 strcpy(completePath, dir);
2200 completePath[0] = '\0';
2201 PathCat(completePath, filePath);
2203 if(FileExists(completePath).isFile)
2205 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2206 if(codeEditor && line)
2208 EditBox editBox = codeEditor.editBox;
2209 editBox.GoToLineNum(line - 1);
2210 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2215 void OnRedraw(Surface surface)
2217 Bitmap bitmap = back.bitmap;
2219 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2222 void SheetSelected(SheetType sheetSelected)
2224 if(activeChild == sheet)
2226 if(sheetSelected == methods)
2228 viewPropertiesItem.accelerator = f4;
2229 viewPropertiesItem.parent = viewMenu;
2230 viewMethodsItem.parent = null;
2234 viewMethodsItem.accelerator = f4;
2235 viewMethodsItem.parent = viewMenu;
2236 viewPropertiesItem.parent = null;
2241 viewMethodsItem.parent = viewMenu;
2242 viewPropertiesItem.parent = viewMenu;
2243 if(sheetSelected == methods)
2245 viewMethodsItem.accelerator = f4;
2246 viewPropertiesItem.accelerator = 0;
2250 viewMethodsItem.accelerator = 0;
2251 viewPropertiesItem.accelerator = f4;
2256 void OnActivateClient(Window client, Window previous)
2258 //if(!client || client != previous)
2261 if(!client || client != previous)
2264 dataType = previous._class;
2265 if(previous && !strcmp(dataType.name, "CodeEditor"))
2267 ((CodeEditor)previous).UpdateFormCode();
2269 else if(previous && !strcmp(dataType.name, "Designer"))
2271 ((Designer)previous).codeEditor.UpdateFormCode();
2276 dataType = client._class;
2277 if(client && !strcmp(dataType.name, "CodeEditor"))
2279 CodeEditor codeEditor = (CodeEditor)client;
2280 SetPrivateModule(codeEditor.privateModule);
2281 SetCurrentContext(codeEditor.globalContext);
2282 SetTopContext(codeEditor.globalContext);
2283 SetGlobalContext(codeEditor.globalContext);
2285 SetDefines(&codeEditor.defines);
2286 SetImports(&codeEditor.imports);
2288 SetActiveDesigner(codeEditor.designer);
2290 sheet.codeEditor = codeEditor;
2291 toolBox.codeEditor = codeEditor;
2293 viewDesignerItem.parent = viewMenu;
2294 if(activeChild != codeEditor)
2296 viewCodeItem.parent = viewMenu;
2297 viewDesignerItem.accelerator = 0;
2298 viewCodeItem.accelerator = f8;
2302 viewCodeItem.parent = null;
2303 viewDesignerItem.accelerator = f8;
2306 else if(client && !strcmp(dataType.name, "Designer"))
2308 CodeEditor codeEditor = ((Designer)client).codeEditor;
2311 SetPrivateModule(codeEditor.privateModule);
2312 SetCurrentContext(codeEditor.globalContext);
2313 SetTopContext(codeEditor.globalContext);
2314 SetGlobalContext(codeEditor.globalContext);
2315 SetDefines(&codeEditor.defines);
2316 SetImports(&codeEditor.imports);
2320 SetPrivateModule(null);
2321 SetCurrentContext(null);
2322 SetTopContext(null);
2323 SetGlobalContext(null);
2328 SetActiveDesigner((Designer)client);
2330 sheet.codeEditor = codeEditor;
2331 toolBox.codeEditor = codeEditor;
2333 viewCodeItem.parent = viewMenu;
2334 if(activeChild != client)
2336 viewDesignerItem.parent = viewMenu;
2337 viewDesignerItem.accelerator = f8;
2338 viewCodeItem.accelerator = 0;
2342 viewDesignerItem.parent = null;
2343 viewCodeItem.accelerator = f8;
2349 sheet.codeEditor = null;
2350 toolBox.codeEditor = null;
2351 SetActiveDesigner(null);
2353 viewDesignerItem.parent = null;
2354 viewCodeItem.parent = null;
2357 SheetSelected(sheet.sheetSelected);
2360 projectCompileItem = null;
2365 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2367 CodeEditor codeEditor = (CodeEditor)client;
2368 EditBox editBox = codeEditor.editBox;
2370 statusBar.AddField(pos);
2372 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2373 statusBar.AddField(caps);
2375 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2376 statusBar.AddField(ovr);
2378 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2379 statusBar.AddField(num);
2381 //statusBar.text = "Ready";
2383 if(projectView && projectView.project)
2385 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2389 sprintf(name, $"Compile %s", node.name);
2390 projectCompileItem =
2392 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2394 bool NotifySelect(MenuItem selection, Modifiers mods)
2398 bool result = false;
2399 ProjectNode node = null;
2400 for(p : ide.workspace.projects)
2402 node = projectView.GetNodeFromWindow(activeClient, p);
2403 if(node && projectView.Compile(node))
2410 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2415 projectMenu.AddDynamic(projectCompileItem, ide, false);
2421 caps = ovr = num = null;
2426 bool OnClose(bool parentClosing)
2428 //return !projectView.buildInProgress;
2429 if(projectView && projectView.buildInProgress)
2431 if(DontTerminateDebugSession($"Close IDE"))
2433 if(findInFilesDialog)
2434 findInFilesDialog.SearchStop();
2437 workspace.timer.Stop();
2440 ideMainFrame.Destroy(0);
2447 for(c = 1; c<app.argc; c++)
2449 char fullPath[MAX_LOCATION];
2450 char parentPath[MAX_LOCATION];
2451 char ext[MAX_EXTENSION];
2453 FileAttribs dirAttribs;
2454 GetWorkingDir(fullPath, MAX_LOCATION);
2455 PathCat(fullPath, app.argv[c]);
2456 StripLastDirectory(fullPath, parentPath);
2457 GetExtension(app.argv[c], ext);
2458 isProject = !strcmpi(ext, "epj");
2460 if(isProject && c > 1) continue;
2462 // Create directory for projects (only)
2463 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2465 if(isProject && !FileExists(fullPath))
2467 // The NewProject will handle directory creation
2468 /*if(!dirAttribs.isDirectory)
2470 MakeDir(parentPath);
2471 dirAttribs = FileExists(parentPath);
2473 if(dirAttribs.isDirectory)*/
2475 char name[MAX_LOCATION];
2476 NewProjectDialog newProjectDialog;
2480 projectView.visible = false;
2481 if(!projectView.Destroy(0))
2485 newProjectDialog = { master = this };
2487 strcpy(name, app.argv[c]);
2488 StripExtension(name);
2489 GetLastDirectory(name, name);
2490 newProjectDialog.projectName.contents = name;
2491 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2492 newProjectDialog.locationEditBox.path = parentPath;
2493 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2495 newProjectDialog.Modal();
2498 ideSettings.AddRecentProject(projectView.fileName);
2499 ide.UpdateRecentMenus();
2500 settingsContainer.Save();
2503 // Open only one project
2507 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2515 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2518 projectView.visible = false;
2519 projectView.Destroy(0);
2522 #ifdef GDB_DEBUG_GUI
2523 gdbDialog.Destroy(0);
2528 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2532 char * oldPaths[128];
2533 String oldList = new char[maxPathLen];
2534 Array<String> newExePaths { };
2535 //Map<String, bool> exePathExists { };
2537 #if defined(__unix__) || defined(__APPLE__)
2538 Array<String> newLibPaths { };
2539 Map<String, bool> libPathExists { };
2544 for(prj : workspace.projects)
2546 DirExpression targetDirExp;
2548 // SKIP FIRST PROJECT...
2549 if(prj == workspace.projects.firstIterator.data) continue;
2551 // NOTE: Right now the additional project config dir will be
2552 // obtained when the debugger is started, so toggling it
2553 // while building will change which library gets used.
2554 // To go with the initial state, e.g. when F5 was pressed,
2555 // we nould need to keep a list of all project's active
2556 // config upon startup.
2557 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2559 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2563 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2564 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2568 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2569 if(cfg.targetType == sharedLibrary && cfg.debug)
2573 if(targetDirExp.dir)
2575 char buffer[MAX_LOCATION];
2576 #if defined(__WIN32__)
2577 Array<String> paths = newExePaths;
2579 Array<String> paths = newLibPaths;
2581 GetSystemPathBuffer(buffer, prj.topNode.path);
2582 PathCat(buffer, targetDirExp.dir);
2585 if(!fstrcmp(p, buffer))
2592 paths.Add(CopyString(buffer));
2594 delete targetDirExp;
2598 for(item : compiler.executableDirs)
2601 for(p : newExePaths)
2603 if(!fstrcmp(p, item))
2610 newExePaths.Add(CopySystemPath(item));
2613 GetEnvironment("PATH", oldList, maxPathLen);
2615 printf("Old value of PATH: %s\n", oldList);
2617 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2618 for(c = 0; c < count; c++)
2621 for(p : newExePaths)
2623 if(!fstrcmp(p, oldPaths[c]))
2630 newExePaths.Add(CopySystemPath(oldPaths[c]));
2634 for(path : newExePaths)
2635 len += strlen(path) + 1;
2636 newList = new char[len + 1];
2638 for(path : newExePaths)
2640 strcat(newList, path);
2641 strcat(newList, pathListSep);
2643 newList[len - 1] = '\0';
2644 SetEnvironment("PATH", newList);
2646 printf("New value of PATH: %s\n", newList);
2653 #if defined(__unix__) || defined(__APPLE__)
2655 for(item : compiler.libraryDirs)
2657 if(!libPathExists[item]) // fstrcmp should be used
2659 newLibPaths.Add(item);
2660 libPathExists[item] = true;
2664 #if defined(__APPLE__)
2665 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2667 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2670 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2672 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2673 for(c = 0; c < count; c++)
2675 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2677 newLibPaths.Add(oldPaths[c]);
2678 libPathExists[oldPaths[c]] = true;
2683 for(path : newLibPaths)
2684 len += strlen(path) + 1;
2685 newList = new char[len + 1];
2687 for(path : newLibPaths)
2689 strcat(newList, path);
2690 strcat(newList, pathListSep);
2692 newList[len - 1] = '\0';
2693 #if defined(__APPLE__)
2694 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2696 SetEnvironment("LD_LIBRARY_PATH", newList);
2699 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2704 delete libPathExists;
2707 if(compiler.distccEnabled && compiler.distccHosts)
2708 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2713 void DestroyTemporaryProjectDir()
2715 if(tmpPrjDir && tmpPrjDir[0])
2717 if(FileExists(tmpPrjDir).isDirectory)
2718 DestroyDir(tmpPrjDir);
2719 property::tmpPrjDir = null;
2725 // Graphics Driver Menu
2729 app.currentSkin.selectionColor = selectionColor;
2730 app.currentSkin.selectionText = selectionText;
2734 driverItems = new MenuItem[app.numDrivers];
2735 for(c = 0; c < app.numDrivers; c++)
2737 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2738 driverItems[c].id = c;
2739 driverItems[c].isRadio = true;
2742 driverItems = new MenuItem[2];
2743 #if defined(__unix__)
2744 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2745 driverItems[0].id = 0;
2746 driverItems[0].isRadio = true;
2748 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2749 driverItems[0].id = 0;
2750 driverItems[0].isRadio = true;
2752 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2753 driverItems[1].id = 1;
2754 driverItems[1].isRadio = true;
2756 /* skinItems = new MenuItem[app.numSkins];
2757 for(c = 0; c < app.numSkins; c++)
2759 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2760 skinItems[c].id = c;
2761 skinItems[c].isRadio = true;
2764 ideFileDialog.master = this;
2765 ideProjectFileDialog.master = this;
2767 //SetDriverAndSkin();
2771 void UpdateRecentMenus()
2774 Menu fileMenu = menu.FindMenu($"File");
2775 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2776 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2777 char itemName[MAX_LOCATION + 4];
2780 recentFiles.Clear();
2783 for(recent : ideSettings.recentFiles)
2785 sprintf(itemName, "%d %s", 1 + c, recent);
2786 MakeSystemPath(itemName);
2787 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2791 recentProjects.Clear();
2793 for(recent : ideSettings.recentProjects)
2795 sprintf(itemName, "%d %s", 1 + c, recent);
2796 MakeSystemPath(itemName);
2797 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2810 void DestroyDir(char * path)
2812 RecursiveDeleteFolderFSI fsi { };
2817 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2819 bool preserveRootFolder;
2821 void OutFolder(char * folderPath, bool isRoot)
2823 if(!(preserveRootFolder && isRoot))
2824 RemoveDir(folderPath);
2827 bool OnFile(char * filePath)
2829 DeleteFile(filePath);
2834 class IDEApp : GuiApplication
2836 //driver = "Win32Console";
2837 // driver = "OpenGL";
2842 SetLoggingMode(stdOut, null);
2843 //SetLoggingMode(debug, null);
2845 settingsContainer.Load();
2846 #if defined(__unix__) || defined(__APPLE__)
2847 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2849 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2851 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2855 desktop.text = titleECEREIDE;
2858 for(c = 1; c<app.argc; c++)
2860 char fullPath[MAX_LOCATION];
2861 GetWorkingDir(fullPath, MAX_LOCATION);
2862 PathCat(fullPath, app.argv[c]);
2863 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2870 IDEMainFrame ideMainFrame { };
2872 define app = ((IDEApp)__thisModule);
2874 define titleECEREIDE = $"ECERE IDE (Debug)";
2876 define titleECEREIDE = $"ECERE IDE";