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.UpdateCompilerConfigs();
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(IsPathInsideOf(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 if(mods.ctrl) // Menu::OnLeftButtonUp -> modifiers.ctrl == true, modifiers == 18
719 // Menu::MenuItemSelection -> key.ctrl == false, key.modifiers.ctrl == false, key == 18
720 // removing the (Key) cast from Modifiers when calling MenuItemSelection in OnLeftButtonUp didn't help
722 // it never gets in here!!!
723 char * command = PrintString("ide ", file);
728 OpenFile(file, normal, true, null, no, normal);
736 bool FileRecentProject(MenuItem selection, Modifiers mods)
739 for(file : ideSettings.recentProjects)
741 if(id == selection.id)
743 if(mods.ctrl) // Menu::OnLeftButtonUp -> modifiers.ctrl == true, modifiers == 18
744 // Menu::MenuItemSelection -> key.ctrl == false, key.modifiers.ctrl == false, key == 18
745 // removing the (Key) cast from Modifiers when calling MenuItemSelection in OnLeftButtonUp didn't help
747 // it never gets in here!!!
748 char * command = PrintString("ide ", file);
753 OpenFile(file, normal, true, null, no, normal);
761 MenuPlacement editMenu { menu, $"Edit", e };
763 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
764 MenuItem projectNewItem
766 projectMenu, $"New...", n, Key { n, true, true };
767 bitmap = { ":actions/projNew.png" };
768 bool NotifySelect(MenuItem selection, Modifiers mods)
770 if(!DontTerminateDebugSession($"New Project"))
771 if(MenuWindowCloseAll(null, 0))
773 NewProjectDialog newProjectDialog;
777 projectView.visible = false;
778 if(!projectView.Destroy(0))
782 newProjectDialog = { master = this };
783 newProjectDialog.Modal();
786 ideSettings.AddRecentProject(projectView.fileName);
787 ide.UpdateRecentMenus();
788 settingsContainer.Save();
794 MenuItem projectOpenItem
796 projectMenu, $"Open...", o, Key { o, true, true };
797 bitmap = { ":actions/projOpen.png" };
798 bool NotifySelect(MenuItem selection, Modifiers mods)
800 if(ideSettings.ideProjectFileDialogLocation)
801 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
803 ideProjectFileDialog.text = openProjectFileDialogTitle;
804 if(ideProjectFileDialog.Modal() == ok)
806 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
807 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
812 MenuItem projectQuickItem
814 projectMenu, $"Quick...", q, f7, disabled = true;
815 bool NotifySelect(MenuItem selection, Modifiers mods)
818 QuickProjectDialog{ this }.Modal();
822 MenuItem projectAddItem
824 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
825 bitmap = { ":actions/projAdd.png" };
827 bool NotifySelect(MenuItem selection, Modifiers mods)
829 if(ideSettings.ideProjectFileDialogLocation)
830 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
832 ideProjectFileDialog.text = addProjectFileDialogTitle;
835 if(ideProjectFileDialog.Modal() == ok)
837 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
839 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
840 contents = $"Add a different project?" }.Modal() == no)
851 MenuItem projectCloseItem
853 projectMenu, $"Close", c, disabled = true;
854 bool NotifySelect(MenuItem selection, Modifiers mods)
858 if(!ide.DontTerminateDebugSession($"Project Close"))
860 if(findInFilesDialog)
861 findInFilesDialog.SearchStop();
862 projectView.visible = false;
863 if(projectView.Destroy(0))
864 MenuWindowCloseAll(null, 0);
866 char workingDir[MAX_LOCATION];
867 GetWorkingDir(workingDir, MAX_LOCATION);
868 findInFilesDialog.currentDirectory = workingDir;
869 ideMainFrame.text = titleECEREIDE;
876 MenuDivider { projectMenu };
877 MenuItem activeCompilerItem
879 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
880 bool NotifySelect(MenuItem selection, Modifiers mods)
882 projectView.MenuCompiler(null, mods);
886 MenuItem projectActiveConfigItem
888 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
889 bool NotifySelect(MenuItem selection, Modifiers mods)
891 projectView.MenuConfig(projectView.active ? selection : null, mods);
895 MenuItem projectSettingsItem
897 projectMenu, $"Settings...", s, altF7, disabled = true;
898 bool NotifySelect(MenuItem selection, Modifiers mods)
900 projectView.MenuSettings(projectView.active ? selection : null, mods);
904 MenuDivider { projectMenu };
905 MenuItem projectBrowseFolderItem
907 projectMenu, $"Browse Project Folder", p, disabled = true;
908 bool NotifySelect(MenuItem selection, Modifiers mods)
911 projectView.MenuBrowseFolder(null, mods);
915 MenuDivider { projectMenu };
916 MenuItem projectRunItem
918 projectMenu, $"Run", r, ctrlF5, disabled = true;
919 bitmap = { ":actions/run.png" };
920 bool NotifySelect(MenuItem selection, Modifiers mods)
923 projectView.Run(null, mods);
927 MenuItem projectBuildItem
929 projectMenu, $"Build", b, f7, disabled = true;
930 bitmap = { ":actions/build.png" };
931 bool NotifySelect(MenuItem selection, Modifiers mods)
934 projectView.ProjectBuild(projectView.active ? selection : null, mods);
938 MenuItem projectLinkItem
940 projectMenu, $"Relink", l, disabled = true;
941 bitmap = { ":actions/relink.png" };
942 bool NotifySelect(MenuItem selection, Modifiers mods)
945 projectView.ProjectLink(projectView.active ? selection : null, mods);
949 MenuItem projectRebuildItem
951 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
952 bitmap = { ":actions/rebuild.png" };
953 bool NotifySelect(MenuItem selection, Modifiers mods)
956 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
960 MenuItem projectCleanItem
962 projectMenu, $"Clean", e, disabled = true;
963 bitmap = { ":actions/clean.png" };
964 bool NotifySelect(MenuItem selection, Modifiers mods)
969 projectView.ProjectClean(projectView.active ? selection : null, mods);
974 MenuItem projectRealCleanItem
976 projectMenu, $"Real Clean", disabled = true;
977 bitmap = { ":actions/clean.png" };
978 bool NotifySelect(MenuItem selection, Modifiers mods)
983 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
988 MenuItem projectRegenerateItem
990 projectMenu, $"Regenerate Makefile", m, disabled = true;
991 bitmap = { ":actions/regMakefile.png" };
992 bool NotifySelect(MenuItem selection, Modifiers mods)
995 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
999 MenuItem projectCompileItem;
1000 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
1001 MenuItem debugStartResumeItem
1003 debugMenu, $"Start", s, f5, disabled = true;
1004 bitmap = { ":actions/debug.png" };
1005 NotifySelect = MenuDebugStart;
1007 bool MenuDebugStart(MenuItem selection, Modifiers mods)
1011 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
1012 if(!projectView.DebugStart())
1013 debugStartResumeItem.disabled = false; // same exception
1017 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1020 projectView.DebugResume();
1023 MenuItem debugRestartItem
1025 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1026 bitmap = { ":actions/restart.png" };
1027 bool NotifySelect(MenuItem selection, Modifiers mods)
1030 projectView.DebugRestart();
1034 MenuItem debugBreakItem
1036 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1037 bitmap = { ":actions/pause.png" };
1038 bool NotifySelect(MenuItem selection, Modifiers mods)
1041 projectView.DebugBreak();
1045 MenuItem debugStopItem
1047 debugMenu, $"Stop", p, shiftF5, disabled = true;
1048 bitmap = { ":actions/stopDebug.png" };
1049 bool NotifySelect(MenuItem selection, Modifiers mods)
1052 projectView.DebugStop();
1056 MenuDivider { debugMenu };
1057 MenuItem debugStepIntoItem
1059 debugMenu, $"Step Into", i, f11, disabled = true;
1060 bitmap = { ":actions/stepInto.png" };
1061 bool NotifySelect(MenuItem selection, Modifiers mods)
1064 projectView.DebugStepInto();
1068 MenuItem debugStepOverItem
1070 debugMenu, $"Step Over", v, f10, disabled = true;
1071 bitmap = { ":actions/stepOver.png" };
1072 bool NotifySelect(MenuItem selection, Modifiers mods)
1075 projectView.DebugStepOver(false);
1079 MenuItem debugStepOutItem
1081 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1082 bitmap = { ":actions/stepOut.png" };
1083 bool NotifySelect(MenuItem selection, Modifiers mods)
1086 projectView.DebugStepOut(false);
1090 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1091 MenuItem debugSkipStepOverItem
1093 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1094 bool NotifySelect(MenuItem selection, Modifiers mods)
1097 projectView.DebugStepOver(true);
1101 MenuItem debugSkipStepOutItem
1103 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1104 bitmap = { ":actions/skipBreaks.png" };
1105 bool NotifySelect(MenuItem selection, Modifiers mods)
1108 projectView.DebugStepOut(true);
1112 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1113 //MenuDivider { debugMenu };
1114 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1115 MenuPlacement imageMenu { menu, $"Image", i };
1116 Menu viewMenu { menu, $"View", v };
1117 MenuItem viewProjectItem
1119 viewMenu, $"Project View", j, alt0, disabled = true;
1120 bool NotifySelect(MenuItem selection, Modifiers mods)
1124 projectView.visible = true;
1125 projectView.Activate();
1130 MenuPlacement { viewMenu, $"View Designer" };
1131 MenuPlacement { viewMenu, $"View Code" };
1132 MenuPlacement { viewMenu, $"View Properties" };
1133 MenuPlacement { viewMenu, $"View Methods" };
1134 MenuItem viewDesignerItem
1136 viewMenu, $"View Designer", d, f8;
1137 bool NotifySelect(MenuItem selection, Modifiers mods)
1139 Window client = activeClient;
1140 Class dataType = client._class;
1141 if(!strcmp(dataType.name, "Designer"))
1143 client.visible = true;
1147 ((CodeEditor)client).ViewDesigner();
1151 MenuItem viewCodeItem
1153 viewMenu, $"View Code", c, f8;
1154 bool NotifySelect(MenuItem selection, Modifiers mods)
1156 Window client = activeClient;
1157 Class dataType = client._class;
1158 if(!strcmp(dataType.name, "Designer"))
1159 client = ((Designer)client).codeEditor;
1162 // Do this after so the caret isn't moved yet...
1163 client.visible = true;
1167 MenuItem viewPropertiesItem
1169 viewMenu, $"View Properties", p, f4;
1170 bool NotifySelect(MenuItem selection, Modifiers mods)
1172 sheet.visible = true;
1173 sheet.sheetSelected = properties;
1178 MenuItem viewMethodsItem
1180 viewMenu, $"View Methods", m, f4;
1181 bool NotifySelect(MenuItem selection, Modifiers mods)
1183 sheet.visible = true;
1184 sheet.sheetSelected = methods;
1189 MenuItem viewToolBoxItem
1191 viewMenu, $"View Toolbox", x, f12;
1192 bool NotifySelect(MenuItem selection, Modifiers mods)
1194 toolBox.visible = true;
1199 MenuItem viewOutputItem
1201 viewMenu, $"Output", o, alt2;
1202 bool NotifySelect(MenuItem selection, Modifiers mods)
1208 MenuItem viewWatchesItem
1210 viewMenu, $"Watches", w, alt3;
1211 bool NotifySelect(MenuItem selection, Modifiers mods)
1217 MenuItem viewThreadsItem
1219 viewMenu, $"Threads", t, alt4;
1220 bool NotifySelect(MenuItem selection, Modifiers mods)
1226 MenuItem viewBreakpointsItem
1228 viewMenu, $"Breakpoints", b, alt5;
1229 bool NotifySelect(MenuItem selection, Modifiers mods)
1231 breakpointsView.Show();
1235 MenuItem viewCallStackItem
1237 viewMenu, $"Call Stack", s, alt7;
1238 bool NotifySelect(MenuItem selection, Modifiers mods)
1240 callStackView.Show();
1244 MenuItem viewAllDebugViews
1246 viewMenu, $"All Debug Views", a, alt9;
1247 bool NotifySelect(MenuItem selection, Modifiers mods)
1252 callStackView.Show();
1253 breakpointsView.Show();
1257 #ifdef GDB_DEBUG_GUI
1258 MenuDivider { viewMenu };
1259 MenuItem viewGDBItem
1261 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1262 bool NotifySelect(MenuItem selection, Modifiers mods)
1269 MenuDivider { viewMenu };
1270 MenuItem viewColorPicker
1272 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1273 bool NotifySelect(MenuItem selection, Modifiers mods)
1275 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1276 colorPicker.Create();
1280 MenuDivider { viewMenu };
1284 viewMenu, "Full Screen", f, checkable = true;
1286 bool NotifySelect(MenuItem selection, Modifiers mods)
1288 app.fullScreen ^= true;
1290 anchor = { 0, 0, 0, 0 };
1295 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1296 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1297 Menu windowMenu { menu, $"Window", w };
1298 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1299 MenuDivider { windowMenu };
1300 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1301 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1302 MenuDivider { windowMenu };
1303 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1304 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1305 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1306 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1307 MenuDivider { windowMenu };
1308 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1309 Menu helpMenu { menu, $"Help", h };
1312 helpMenu, $"API Reference", r, f1;
1313 bool NotifySelect(MenuItem selection, Modifiers mods)
1315 Execute("documentor");
1319 MenuDivider { helpMenu };
1322 helpMenu, $"About...", a;
1323 bool NotifySelect(MenuItem selection, Modifiers mods)
1325 AboutIDE { master = this }.Modal();
1330 property ToolBox toolBox
1332 get { return toolBox; }
1335 property Sheet sheet
1337 get { return sheet; }
1340 property Project project
1342 get { return projectView ? projectView.project : null; }
1345 property Workspace workspace
1347 get { return projectView ? projectView.workspace : null; }
1350 FindInFilesDialog findInFilesDialog
1352 master = this, parent = this;
1353 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1357 #ifdef GDB_DEBUG_GUI
1360 master = this, parent = this;
1361 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1363 void OnCommand(char * string)
1366 ide.debugger.SendGDBCommand(string);
1371 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1373 //app.driver = app.drivers[selection.id];
1375 app.driver = selection.id ? "OpenGL" : "X";
1377 app.driver = selection.id ? "OpenGL" : "GDI";
1379 delete ideSettings.displayDriver;
1380 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1382 settingsContainer.Save();
1383 //SetDriverAndSkin();
1387 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1389 app.skin = app.skins[selection.id];
1394 void SetDriverAndSkin()
1397 for(c = 0; c < app.numSkins; c++)
1398 if(!strcmp(app.skins[c], app.skin))
1400 skinItems[c].checked = true;
1403 for(c = 0; c < app.numDrivers; c++)
1404 if(!strcmp(app.drivers[c], app.driver))
1406 driverItems[c].checked = true;
1411 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1413 Project project = workspace.projects.firstIterator.data;
1414 projectView = ProjectView
1417 fileName = fileName;
1419 void NotifyDestroyed(Window window, DialogResult result)
1422 text = titleECEREIDE;
1427 projectView.Create();
1428 RepositionWindows(false);
1430 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1431 projectView.workspace = workspace;
1432 projectView.project = project;
1433 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1437 ide.breakpointsView.LoadFromWorkspace();
1438 ide.watchesView.LoadFromWorkspace();
1440 findInFilesDialog.projectNodeField.userData = projectView;
1443 char fileName[MAX_LOCATION];
1444 strcpy(fileName, project.topNode.path);
1445 PathCat(fileName, project.topNode.name);
1450 bool GetDebugMenusDisabled()
1454 Project project = projectView.project;
1456 if(project.GetTargetType(project.config) == executable)
1463 void RepositionWindows(bool expand)
1468 bool inDebugMode = debugger.isActive;
1469 bool callStackVisible = expand ? false : callStackView.visible;
1470 bool threadsVisible = expand ? false : threadsView.visible;
1471 bool watchesVisible = expand ? false : watchesView.visible;
1472 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1473 bool toolBoxVisible = toolBox.visible;
1474 bool outputVisible = expand ? false : outputView.visible;
1475 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1476 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1478 for(child = firstChild; child; child = child.next)
1480 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1481 child._class == class(Sheet) || child._class == class(ProjectView))
1483 Anchor anchor = child.anchor;
1484 anchor.top = topDistance;
1485 anchor.bottom = bottomDistance;
1486 if(child._class == class(CodeEditor) || child._class == class(Designer))
1488 anchor.right = toolBoxVisible ? 150 : 0;
1490 child.anchor = anchor;
1494 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1495 child._class == class(BreakpointsView))
1496 child.visible = false;
1499 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1504 bool ShowCodeEditor()
1507 activeClient.Activate();
1508 else if(projectView)
1510 projectView.visible = true;
1511 projectView.Activate();
1515 sheet.visible = true;
1521 bool ShouldStopBuild()
1523 return projectView.stopBuild;
1526 void DocumentSaved(Window document, char * fileName)
1528 ideSettings.AddRecentFile(fileName);
1529 ide.UpdateRecentMenus();
1530 ide.AdjustFileMenus();
1531 settingsContainer.Save();
1534 bool Window::OnFileModified(FileChange fileChange, char * param)
1537 sprintf(temp, $"The document %s was modified by another application.\n"
1538 "Would you like to reload it and lose your changes?", this.fileName);
1539 if(MessageBox { type = yesNo, master = this/*.parent*/,
1540 text = $"Document has been modified", contents = temp }.Modal() == yes)
1542 char * fileName = CopyString(this.fileName);
1543 WindowState state = this.state;
1544 Anchor anchor = this.anchor;
1545 Size size = this.size;
1547 this.modifiedDocument = false;
1549 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1552 this.anchor = anchor;
1554 this.SetState(state, true, 0);
1562 void UpdateMakefiles()
1566 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1567 for(prj : workspace.projects)
1568 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1573 void UpdateCompilerConfigs()
1577 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1578 projectView.ShowOutputBuildLog(true);
1579 projectView.DisplayCompiler(compiler, false);
1580 for(prj : workspace.projects)
1581 projectView.ProjectPrepareCompiler(prj, compiler);
1588 bool unavailable = !project;
1590 projectAddItem.disabled = unavailable;
1591 toolBar.buttonAddProject.disabled = unavailable;
1593 activeCompilerItem.disabled = unavailable;
1594 projectActiveConfigItem.disabled = unavailable;
1595 projectSettingsItem.disabled = unavailable;
1597 projectBrowseFolderItem.disabled = unavailable;
1599 viewProjectItem.disabled = unavailable;
1606 property bool hasOpenedCodeEditors
1611 for(w = firstChild; w; w = w.next)
1612 if(w._class == class(CodeEditor) &&
1613 w.isDocument && !w.closing && w.visible && w.created &&
1614 w.fileName && w.fileName[0])
1620 void AdjustFileMenus()
1622 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1624 projectQuickItem.disabled = unavailable;
1627 void AdjustBuildMenus()
1629 bool unavailable = project && projectView.buildInProgress;
1631 projectNewItem.disabled = unavailable;
1632 toolBar.buttonNewProject.disabled = unavailable;
1633 projectOpenItem.disabled = unavailable;
1634 toolBar.buttonOpenProject.disabled = unavailable;
1636 unavailable = !project || projectView.buildInProgress;
1638 projectCloseItem.disabled = unavailable;
1639 // toolBar.buttonCloseProject.disabled = unavailable;
1641 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1642 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1643 projectBuildItem.disabled = unavailable;
1644 toolBar.buttonBuild.disabled = unavailable;
1645 projectLinkItem.disabled = unavailable;
1646 toolBar.buttonReLink.disabled = unavailable;
1647 projectRebuildItem.disabled = unavailable;
1648 toolBar.buttonRebuild.disabled = unavailable;
1649 projectCleanItem.disabled = unavailable;
1650 toolBar.buttonClean.disabled = unavailable;
1651 projectRealCleanItem.disabled = unavailable;
1652 // toolBar.buttonRealClean.disabled = unavailable;
1653 projectRegenerateItem.disabled = unavailable;
1654 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1655 projectCompileItem.disabled = unavailable;
1657 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1660 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0); if(menu) menu.disabled = unavailable;
1661 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
1662 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
1663 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
1664 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
1665 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1666 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable;
1667 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable;
1668 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable;
1669 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable;
1670 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable;
1671 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable;
1672 projectView.popupMenu.Update(null);
1676 void AdjustDebugMenus()
1678 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1679 projectView.buildInProgress == buildingMainProject;
1680 bool active = ide.debugger.isActive;
1681 bool executing = ide.debugger.state == running;
1682 //bool holding = ide.debugger.state == stopped;
1684 debugStartResumeItem.disabled = unavailable || executing;
1685 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1686 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1689 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1690 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1693 debugBreakItem.disabled = unavailable || !executing;
1694 debugStopItem.disabled = unavailable || !active;
1695 debugRestartItem.disabled = unavailable || !active;
1698 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1699 toolBar.buttonDebugStop.disabled = unavailable || !active;
1700 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1703 debugStepIntoItem.disabled = unavailable || executing;
1704 debugStepOverItem.disabled = unavailable || executing;
1705 debugStepOutItem.disabled = unavailable || executing || !active;
1706 debugSkipStepOverItem.disabled = unavailable || executing;
1707 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1710 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1711 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1712 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1713 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1714 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1716 if((Designer)GetActiveDesigner())
1718 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1721 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1722 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1727 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1729 char tempString[MAX_LOCATION];
1730 strcpy(tempString, directory);
1731 if(saveSettings && !projectView)
1733 ideSettings.ideFileDialogLocation = directory;
1734 settingsContainer.Save();
1737 ideFileDialog.currentDirectory = tempString;
1738 codeEditorFileDialog.currentDirectory = tempString;
1739 codeEditorFormFileDialog.currentDirectory = tempString;
1742 void ChangeProjectFileDialogDirectory(char * directory)
1744 ideSettings.ideProjectFileDialogLocation = directory;
1745 settingsContainer.Save();
1748 Window FindWindow(char * filePath)
1750 Window document = null;
1752 // TOCHECK: Do we need to change slashes here?
1753 for(document = firstChild; document; document = document.next)
1755 char * fileName = document.fileName;
1756 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1758 document.visible = true;
1759 document.Activate();
1766 bool DontTerminateDebugSession(char * title)
1768 if(debugger.isActive)
1770 if(MessageBox { type = yesNo, master = ide,
1771 contents = $"Do you want to terminate the debugging session in progress?",
1772 text = title }.Modal() == no)
1775 MessageBox msg { type = yesNo, master = ide,
1776 contents = "Do you want to terminate the debugging session in progress?",
1778 if(msg.Modal() == no)
1790 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1792 char extension[MAX_EXTENSION] = "";
1793 Window document = null;
1794 bool isProject = false;
1795 bool needFileModified = true;
1796 char winFilePath[MAX_LOCATION];
1797 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1801 GetExtension(filePath, extension);
1805 strcpy(extension, type);
1807 if(strcmp(extension, ProjectExtension))
1809 for(document = firstChild; document; document = document.next)
1811 char * fileName = document.fileName;
1812 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1814 document.visible = true;
1816 document.Activate();
1822 if(createIfFails == whatever)
1824 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1826 needFileModified = false;
1827 if(openMethod == normal)
1829 if(DontTerminateDebugSession($"Open Project"))
1832 if(MenuWindowCloseAll(null, 0))
1836 projectView.visible = false;
1837 projectView.Destroy(0);
1838 // Where did this come from? projectView = null;
1845 Workspace workspace = null;
1847 if(FileExists(filePath))
1849 if(!strcmp(extension, ProjectExtension))
1851 char workspaceFile[MAX_LOCATION];
1852 strcpy(workspaceFile, filePath);
1853 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1854 workspace = LoadWorkspace(workspaceFile, filePath);
1856 else if(!strcmp(extension, WorkspaceExtension))
1857 workspace = LoadWorkspace(filePath, null);
1860 //project = LoadProject(filePath, null);
1865 char absolutePath[MAX_LOCATION];
1866 CreateProjectView(workspace, filePath);
1867 document = projectView;
1869 workspace.DropInvalidBreakpoints();
1872 ide.projectView.ShowOutputBuildLog(true);
1874 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1875 ide.projectView.DisplayCompiler(compiler, false);
1878 UpdateCompilerConfigs();
1881 char newWorkingDir[MAX_LOCATION];
1882 StripLastDirectory(filePath, newWorkingDir);
1883 ChangeFileDialogsDirectory(newWorkingDir, false);
1886 document.fileName = filePath;
1888 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1890 // this crashes on starting ide with epj file, solution please?
1891 // app.UpdateDisplay();
1893 workspace.holdTracking = true;
1894 for(ofi : workspace.openedFiles)
1896 if(ofi.state != closed)
1898 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1901 char fileName[MAX_LOCATION];
1903 GetLastDirectory(ofi.path, fileName);
1904 node = projectView.project.topNode.Find(fileName, true);
1906 node.EnsureVisible();
1910 workspace.holdTracking = false;
1912 workspace.timer.Start();
1914 findInFilesDialog.mode = FindInFilesMode::project;
1915 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1918 char location[MAX_LOCATION];
1919 StripLastDirectory(ide.project.topNode.path, location);
1920 ChangeProjectFileDialogDirectory(location);
1924 if(projectView.debugger)
1925 projectView.debugger.EvaluateWatches();
1932 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1934 ideProjectFileDialog.text = openProjectFileDialogTitle;
1935 if(ideProjectFileDialog.Modal() == cancel)
1937 filePath = ideProjectFileDialog.filePath;
1938 GetExtension(filePath, extension);
1949 else if(openMethod == add)
1954 char slashFilePath[MAX_LOCATION];
1955 GetSlashPathBuffer(slashFilePath, filePath);
1956 for(p : workspace.projects)
1958 if(!fstrcmp(p.filePath, slashFilePath))
1966 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1967 contents = $"This project is already present in workspace." }.Modal();
1971 prj = LoadProject(filePath, null);
1974 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1975 prj.StartMonitoring();
1976 workspace.projects.Add(prj);
1978 projectView.AddNode(prj.topNode, null);
1979 workspace.modified = true;
1981 findInFilesDialog.AddProjectItem(prj);
1982 projectView.ShowOutputBuildLog(true);
1983 projectView.DisplayCompiler(compiler, false);
1984 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1988 char location[MAX_LOCATION];
1989 StripLastDirectory(prj.topNode.path, location);
1990 ChangeProjectFileDialogDirectory(location);
1993 // projectView is associated with the main project and not with the one just added but
1994 return projectView; // just to let the caller know something was opened
2002 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2003 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2004 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2006 if(FileExists(filePath))
2007 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2008 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2009 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2012 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2015 else if(!strcmp(extension, "3ds"))
2017 if(FileExists(filePath))
2018 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2019 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2020 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2024 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2027 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2028 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2029 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2030 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2031 !strcmp(extension, "js"))
2033 CodeEditor editor { parent = this, state = state, visible = false };
2034 editor.updatingCode = true;
2035 if(editor.LoadFile(filePath))
2038 editor.visible = true;
2042 needFileModified = false;
2046 CodeEditor editor { parent = this, state = state, visible = false };
2047 if(editor.LoadFile(filePath))
2050 editor.visible = true;
2054 needFileModified = false;
2057 if(document && (document._class == class(PictureEdit) ||
2058 document._class == class(ModelView)))
2063 document.fileName = filePath;
2064 if(workspace && !workspace.holdTracking)
2065 workspace.UpdateOpenedFileInfo(filePath, opened);
2069 if(!document && createIfFails != no)
2071 if(createIfFails != yes && !needFileModified &&
2072 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2073 createIfFails = yes;
2074 if(createIfFails == yes || createIfFails == whatever)
2076 document = (Window)NewCodeEditor(this, state, true);
2078 document.fileName = filePath;
2084 if(projectView && document._class == class(CodeEditor) && workspace)
2086 int lineNumber, position;
2088 CodeEditor editor = (CodeEditor)document;
2089 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2090 editor.openedFileInfo.holdTracking = true;
2091 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2092 position = Max(editor.openedFileInfo.position - 1, 0);
2093 editor.editBox.GoToLineNum(lineNumber);
2094 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2095 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2096 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2097 editor.editBox.scroll = scroll;
2098 editor.openedFileInfo.holdTracking = false;
2101 if(needFileModified)
2102 document.OnFileModified = OnFileModified;
2103 document.NotifySaved = DocumentSaved;
2106 ideSettings.AddRecentProject(document.fileName);
2108 ideSettings.AddRecentFile(document.fileName);
2109 ide.UpdateRecentMenus();
2110 ide.AdjustFileMenus();
2111 settingsContainer.Save();
2119 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2120 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2122 if(!parentClosing && ide.workspace)
2123 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2126 bool ModelView::ModelViewOnClose(bool parentClosing)
2128 if(!parentClosing && ide.workspace)
2129 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2132 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2134 if(!parentClosing && ide.workspace)
2135 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2140 void OnUnloadGraphics(Window window)
2142 display.ClearMaterials();
2143 display.ClearTextures();
2144 display.ClearMeshes();
2148 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2150 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2151 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2155 bool OnKeyDown(Key key, unichar ch)
2160 projectView.Update(null);
2163 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2166 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2172 void GoToError(const char * line)
2175 projectView.GoToError(line);
2178 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2181 char *colon = strchr(text, ':');
2182 char filePath[MAX_LOCATION];
2183 char completePath[MAX_LOCATION];
2184 int line = 0, col = 0;
2186 FileAttribs fileAttribs;
2188 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2190 path = (colon - 1 > path) ? colon - 1 : path;
2191 colon = strstr(colon + 1, ":");
2193 while(isspace(*path)) path++;
2196 char * close = strchr(path, ')');
2200 strncpy(name, path+1, close - path - 1);
2201 name[close - path - 1] = '\0';
2202 for(p : ide.workspace.projects)
2204 if(!strcmp(p.name, name))
2214 prj = project ? project : (dir ? null : ide.project);
2217 strncpy(filePath, path, colon - path);
2218 filePath[colon - path] = '\0';
2219 line = atoi(colon + 1);
2220 colon = strstr(colon + 1, ":");
2222 col = atoi(colon + 1);
2224 else if(path - 1 >= text && *(path - 1) == '\"')
2226 colon = strchr(path, '\"');
2229 strncpy(filePath, path, colon - path);
2230 filePath[colon - path] = '\0';
2233 else if(path && !colon)
2235 strcpy(filePath, path);
2239 strcpy(completePath, prj.topNode.path);
2240 else if(dir && dir[0])
2241 strcpy(completePath, dir);
2243 completePath[0] = '\0';
2244 PathCat(completePath, filePath);
2246 fileAttribs = FileExists(completePath);
2247 if(fileAttribs.isFile)
2249 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2250 if(codeEditor && line)
2252 EditBox editBox = codeEditor.editBox;
2253 editBox.GoToLineNum(line - 1);
2254 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2257 else if(fileAttribs.isDirectory)
2258 ShellOpen(completePath);
2261 void OnRedraw(Surface surface)
2263 Bitmap bitmap = back.bitmap;
2265 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2268 void SheetSelected(SheetType sheetSelected)
2270 if(activeChild == sheet)
2272 if(sheetSelected == methods)
2274 viewPropertiesItem.accelerator = f4;
2275 viewPropertiesItem.parent = viewMenu;
2276 viewMethodsItem.parent = null;
2280 viewMethodsItem.accelerator = f4;
2281 viewMethodsItem.parent = viewMenu;
2282 viewPropertiesItem.parent = null;
2287 viewMethodsItem.parent = viewMenu;
2288 viewPropertiesItem.parent = viewMenu;
2289 if(sheetSelected == methods)
2291 viewMethodsItem.accelerator = f4;
2292 viewPropertiesItem.accelerator = 0;
2296 viewMethodsItem.accelerator = 0;
2297 viewPropertiesItem.accelerator = f4;
2302 void OnActivateClient(Window client, Window previous)
2304 //if(!client || client != previous)
2307 if(!client || client != previous)
2310 dataType = previous._class;
2311 if(previous && !strcmp(dataType.name, "CodeEditor"))
2313 ((CodeEditor)previous).UpdateFormCode();
2315 else if(previous && !strcmp(dataType.name, "Designer"))
2317 ((Designer)previous).codeEditor.UpdateFormCode();
2322 dataType = client._class;
2323 if(client && !strcmp(dataType.name, "CodeEditor"))
2325 CodeEditor codeEditor = (CodeEditor)client;
2326 SetPrivateModule(codeEditor.privateModule);
2327 SetCurrentContext(codeEditor.globalContext);
2328 SetTopContext(codeEditor.globalContext);
2329 SetGlobalContext(codeEditor.globalContext);
2331 SetDefines(&codeEditor.defines);
2332 SetImports(&codeEditor.imports);
2334 SetActiveDesigner(codeEditor.designer);
2336 sheet.codeEditor = codeEditor;
2337 toolBox.codeEditor = codeEditor;
2339 viewDesignerItem.parent = viewMenu;
2340 if(activeChild != codeEditor)
2342 viewCodeItem.parent = viewMenu;
2343 viewDesignerItem.accelerator = 0;
2344 viewCodeItem.accelerator = f8;
2348 viewCodeItem.parent = null;
2349 viewDesignerItem.accelerator = f8;
2352 else if(client && !strcmp(dataType.name, "Designer"))
2354 CodeEditor codeEditor = ((Designer)client).codeEditor;
2357 SetPrivateModule(codeEditor.privateModule);
2358 SetCurrentContext(codeEditor.globalContext);
2359 SetTopContext(codeEditor.globalContext);
2360 SetGlobalContext(codeEditor.globalContext);
2361 SetDefines(&codeEditor.defines);
2362 SetImports(&codeEditor.imports);
2366 SetPrivateModule(null);
2367 SetCurrentContext(null);
2368 SetTopContext(null);
2369 SetGlobalContext(null);
2374 SetActiveDesigner((Designer)client);
2376 sheet.codeEditor = codeEditor;
2377 toolBox.codeEditor = codeEditor;
2379 viewCodeItem.parent = viewMenu;
2380 if(activeChild != client)
2382 viewDesignerItem.parent = viewMenu;
2383 viewDesignerItem.accelerator = f8;
2384 viewCodeItem.accelerator = 0;
2388 viewDesignerItem.parent = null;
2389 viewCodeItem.accelerator = f8;
2395 sheet.codeEditor = null;
2396 toolBox.codeEditor = null;
2397 SetActiveDesigner(null);
2399 viewDesignerItem.parent = null;
2400 viewCodeItem.parent = null;
2403 SheetSelected(sheet.sheetSelected);
2406 projectCompileItem = null;
2411 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2413 CodeEditor codeEditor = (CodeEditor)client;
2414 EditBox editBox = codeEditor.editBox;
2416 statusBar.AddField(pos);
2418 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2419 statusBar.AddField(caps);
2421 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2422 statusBar.AddField(ovr);
2424 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2425 statusBar.AddField(num);
2427 //statusBar.text = "Ready";
2429 if(projectView && projectView.project)
2431 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2435 sprintf(name, $"Compile %s", node.name);
2436 projectCompileItem =
2438 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2440 bool NotifySelect(MenuItem selection, Modifiers mods)
2444 bool result = false;
2445 ProjectNode node = null;
2446 for(p : ide.workspace.projects)
2448 node = projectView.GetNodeFromWindow(activeClient, p);
2449 //if(node && projectView.Compile(node.project, node, mods.ctrl && mods.shift))
2452 List<ProjectNode> nodes { };
2454 projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, normal);
2462 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2467 projectMenu.AddDynamic(projectCompileItem, ide, false);
2473 caps = ovr = num = null;
2478 bool OnClose(bool parentClosing)
2480 //return !projectView.buildInProgress;
2481 if(projectView && projectView.buildInProgress)
2483 if(DontTerminateDebugSession($"Close IDE"))
2485 if(findInFilesDialog)
2486 findInFilesDialog.SearchStop();
2489 workspace.timer.Stop();
2492 ideMainFrame.Destroy(0);
2499 bool passThrough = false;
2500 bool debugStart = false;
2501 DynamicString passArgs { };
2502 for(c = 1; c<app.argc; c++)
2504 if(!strcmp(app.argv[c], "-debug-start"))
2506 else if(!passThrough && !strcmp(app.argv[c], "-@"))
2508 else if(passThrough)
2510 passArgs.concat(" ");
2511 passArgs.concat(app.argv[c]);
2515 char fullPath[MAX_LOCATION];
2516 char parentPath[MAX_LOCATION];
2517 char ext[MAX_EXTENSION];
2519 FileAttribs dirAttribs;
2520 GetWorkingDir(fullPath, MAX_LOCATION);
2521 PathCat(fullPath, app.argv[c]);
2522 StripLastDirectory(fullPath, parentPath);
2523 GetExtension(app.argv[c], ext);
2524 isProject = !strcmpi(ext, "epj");
2526 if(isProject && c > (debugStart ? 2 : 1)) continue;
2528 // Create directory for projects (only)
2529 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2531 if(isProject && !FileExists(fullPath))
2533 // The NewProject will handle directory creation
2534 /*if(!dirAttribs.isDirectory)
2536 MakeDir(parentPath);
2537 dirAttribs = FileExists(parentPath);
2539 if(dirAttribs.isDirectory)*/
2541 char name[MAX_LOCATION];
2542 NewProjectDialog newProjectDialog;
2546 projectView.visible = false;
2547 if(!projectView.Destroy(0))
2551 newProjectDialog = { master = this };
2553 strcpy(name, app.argv[c]);
2554 StripExtension(name);
2555 GetLastDirectory(name, name);
2556 newProjectDialog.projectName.contents = name;
2557 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2558 newProjectDialog.locationEditBox.path = parentPath;
2559 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2561 newProjectDialog.Modal();
2564 ideSettings.AddRecentProject(projectView.fileName);
2565 ide.UpdateRecentMenus();
2566 settingsContainer.Save();
2569 // Open only one project
2573 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2577 if(passThrough && projectView && projectView.project && workspace)
2578 workspace.commandLineArgs = passArgs;
2581 ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock
2587 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2590 projectView.visible = false;
2591 projectView.Destroy(0);
2594 #ifdef GDB_DEBUG_GUI
2595 gdbDialog.Destroy(0);
2600 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2604 char * oldPaths[128];
2605 String oldList = new char[maxPathLen];
2606 Array<String> newExePaths { };
2607 //Map<String, bool> exePathExists { };
2609 #if defined(__unix__) || defined(__APPLE__)
2610 Array<String> newLibPaths { };
2611 Map<String, bool> libPathExists { };
2616 for(prj : workspace.projects)
2618 DirExpression targetDirExp;
2620 // SKIP FIRST PROJECT...
2621 if(prj == workspace.projects.firstIterator.data) continue;
2623 // NOTE: Right now the additional project config dir will be
2624 // obtained when the debugger is started, so toggling it
2625 // while building will change which library gets used.
2626 // To go with the initial state, e.g. when F5 was pressed,
2627 // we nould need to keep a list of all project's active
2628 // config upon startup.
2629 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2631 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2635 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2636 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2640 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2641 if(cfg.targetType == sharedLibrary && cfg.debug)
2645 if(targetDirExp.dir)
2647 char buffer[MAX_LOCATION];
2648 #if defined(__WIN32__)
2649 Array<String> paths = newExePaths;
2651 Array<String> paths = newLibPaths;
2653 GetSystemPathBuffer(buffer, prj.topNode.path);
2654 PathCat(buffer, targetDirExp.dir);
2657 if(!fstrcmp(p, buffer))
2664 paths.Add(CopyString(buffer));
2666 delete targetDirExp;
2670 for(item : compiler.executableDirs)
2673 for(p : newExePaths)
2675 if(!fstrcmp(p, item))
2682 newExePaths.Add(CopySystemPath(item));
2685 GetEnvironment("PATH", oldList, maxPathLen);
2687 printf("Old value of PATH: %s\n", oldList);
2689 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2690 for(c = 0; c < count; c++)
2693 for(p : newExePaths)
2695 if(!fstrcmp(p, oldPaths[c]))
2702 newExePaths.Add(CopySystemPath(oldPaths[c]));
2706 for(path : newExePaths)
2707 len += strlen(path) + 1;
2708 newList = new char[len + 1];
2710 for(path : newExePaths)
2712 strcat(newList, path);
2713 strcat(newList, pathListSep);
2715 newList[len - 1] = '\0';
2716 SetEnvironment("PATH", newList);
2718 printf("New value of PATH: %s\n", newList);
2725 #if defined(__unix__) || defined(__APPLE__)
2727 for(item : compiler.libraryDirs)
2729 if(!libPathExists[item]) // fstrcmp should be used
2731 newLibPaths.Add(item);
2732 libPathExists[item] = true;
2736 #if defined(__APPLE__)
2737 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2739 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2742 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2744 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2745 for(c = 0; c < count; c++)
2747 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2749 newLibPaths.Add(oldPaths[c]);
2750 libPathExists[oldPaths[c]] = true;
2755 for(path : newLibPaths)
2756 len += strlen(path) + 1;
2757 newList = new char[len + 1];
2759 for(path : newLibPaths)
2761 strcat(newList, path);
2762 strcat(newList, pathListSep);
2764 newList[len - 1] = '\0';
2765 #if defined(__APPLE__)
2766 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2768 SetEnvironment("LD_LIBRARY_PATH", newList);
2771 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2776 delete libPathExists;
2779 if(compiler.distccEnabled && compiler.distccHosts)
2780 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2785 void DestroyTemporaryProjectDir()
2787 if(tmpPrjDir && tmpPrjDir[0])
2789 if(FileExists(tmpPrjDir).isDirectory)
2790 DestroyDir(tmpPrjDir);
2791 property::tmpPrjDir = null;
2797 // Graphics Driver Menu
2801 app.currentSkin.selectionColor = selectionColor;
2802 app.currentSkin.selectionText = selectionText;
2806 driverItems = new MenuItem[app.numDrivers];
2807 for(c = 0; c < app.numDrivers; c++)
2809 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2810 driverItems[c].id = c;
2811 driverItems[c].isRadio = true;
2814 driverItems = new MenuItem[2];
2815 #if defined(__unix__)
2816 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2817 driverItems[0].id = 0;
2818 driverItems[0].isRadio = true;
2820 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2821 driverItems[0].id = 0;
2822 driverItems[0].isRadio = true;
2824 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2825 driverItems[1].id = 1;
2826 driverItems[1].isRadio = true;
2828 /* skinItems = new MenuItem[app.numSkins];
2829 for(c = 0; c < app.numSkins; c++)
2831 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2832 skinItems[c].id = c;
2833 skinItems[c].isRadio = true;
2836 ideFileDialog.master = this;
2837 ideProjectFileDialog.master = this;
2839 //SetDriverAndSkin();
2843 void UpdateRecentMenus()
2846 Menu fileMenu = menu.FindMenu($"File");
2847 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2848 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2849 char itemName[MAX_LOCATION + 4];
2852 recentFiles.Clear();
2855 for(recent : ideSettings.recentFiles)
2857 sprintf(itemName, "%d %s", 1 + c, recent);
2858 MakeSystemPath(itemName);
2859 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2863 recentProjects.Clear();
2865 for(recent : ideSettings.recentProjects)
2867 sprintf(itemName, "%d %s", 1 + c, recent);
2868 MakeSystemPath(itemName);
2869 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2882 void DestroyDir(char * path)
2884 RecursiveDeleteFolderFSI fsi { };
2889 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2891 bool preserveRootFolder;
2893 void OutFolder(char * folderPath, bool isRoot)
2895 if(!(preserveRootFolder && isRoot))
2896 RemoveDir(folderPath);
2899 bool OnFile(char * filePath)
2901 DeleteFile(filePath);
2906 class IDEApp : GuiApplication
2908 //driver = "Win32Console";
2909 // driver = "OpenGL";
2914 SetLoggingMode(stdOut, null);
2915 //SetLoggingMode(debug, null);
2917 settingsContainer.Load();
2918 #if defined(__unix__) || defined(__APPLE__)
2919 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2921 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2923 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2927 desktop.text = titleECEREIDE;
2930 for(c = 1; c<app.argc; c++)
2932 char fullPath[MAX_LOCATION];
2933 GetWorkingDir(fullPath, MAX_LOCATION);
2934 PathCat(fullPath, app.argv[c]);
2935 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2942 IDEMainFrame ideMainFrame { };
2944 define app = ((IDEApp)__thisModule);
2946 define titleECEREIDE = $"ECERE IDE (Debug)";
2948 define titleECEREIDE = $"ECERE IDE";