2 public import static "ecere"
3 public import static "ec"
9 import "GlobalSettingsDialog"
10 import "NewProjectDialog"
11 import "FindInFilesDialog"
18 import "ProjectConfig"
20 import "NodeProperties"
21 import "ProjectSettings"
33 import "BreakpointsView"
34 import "CallStackView"
45 import "FileSystemIterator"
47 #if defined(__WIN32__)
48 define pathListSep = ";";
50 define pathListSep = ":";
53 define maxPathLen = 65 * MAX_LOCATION;
55 class PathBackup : struct
62 oldPath = new char[maxPathLen];
63 oldLDPath = new char[maxPathLen];
65 GetEnvironment("PATH", oldPath, maxPathLen);
66 #if defined(__APPLE__)
67 GetEnvironment("DYLD_LIBRARY_PATH", oldLDPath, maxPathLen);
69 GetEnvironment("LD_LIBRARY_PATH", oldLDPath, maxPathLen);
75 SetEnvironment("PATH", oldPath);
76 #if defined(__APPLE__)
77 SetEnvironment("DYLD_LIBRARY_PATH", oldLDPath);
79 SetEnvironment("LD_LIBRARY_PATH", oldLDPath);
86 enum OpenCreateIfFails { no, yes, something, whatever };
87 enum OpenMethod { normal, add };
89 static Array<FileFilter> fileFilters
91 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
92 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
93 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
94 { $"Text files (*.txt, *.text, *.nfo, *.info)", "txt, text, nfo, info" },
95 { $"Web files (*.html, *.htm, *.xhtml, *.css, *.php, *.js, *.jsi, *.rb, *.xml)", "html, htm, xhtml, css, php, js, jsi, rb, xml" },
96 { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
97 { $"3D Studio Model Files (*.3ds)", "3ds" },
98 { $"All files", null }
101 static Array<FileType> fileTypes
103 { $"Based on extension", null },
106 { $"3D Studio Model", "3ds" }
109 static Array<FileFilter> projectFilters
111 { $"Project Files (*.epj)", ProjectExtension }
114 static Array<FileType> projectTypes
116 { $"Project File", ProjectExtension }
119 static Array<FileFilter> findInFilesFileFilters
121 { $"eC Files (*.ec, *.eh)", "ec, eh" },
122 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
123 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
124 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
125 { $"Text files (*.txt)", "txt" },
126 { $"All files", null }
129 FileDialog ideFileDialog
131 type = multiOpen, text = $"Open";
132 types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
135 define openProjectFileDialogTitle = $"Open Project";
136 define addProjectFileDialogTitle = $"Open Additional Project";
137 FileDialog ideProjectFileDialog
140 types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
143 GlobalSettingsDialog globalSettingsDialog
145 ideSettings = ideSettings;
146 settingsContainer = settingsContainer;
148 void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
150 switch(globalSettingsChange)
155 for(child = ide.firstChild; child; child = child.next)
157 if(child._class == class(CodeEditor))
159 CodeEditor codeEditor = (CodeEditor) child;
160 codeEditor.editBox.freeCaret = ideSettings.useFreeCaret;
161 // codeEditor.editBox.lineNumbers = ideSettings.showLineNumbers;
162 codeEditor.editBox.caretFollowsScrolling = ideSettings.caretFollowsScrolling;
163 codeEditor.OnPostCreate(); // Update editBox margin size
170 case compilerSettings:
172 ide.UpdateCompilerConfigs();
179 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
184 lineY = (line - 1) * lineH;
185 if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
187 Bitmap bitmap = resource.bitmap;
189 surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
194 #define IDEItem(x) (&((IDEWorkSpace)0).x)
196 class IDEToolbar : ToolBar
200 ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) };
202 ToolButton buttonOpenFile { this, toolTip = $"Open file", menuItemPtr = IDEItem(fileOpenItem) };
204 // ToolButton buttonCloseFile { this, toolTip = $"Close file", menuItemPtr = IDEItem(fileCloseItem) };
206 ToolButton buttonSaveFile { this, toolTip = $"Save file", menuItemPtr = IDEItem(fileSaveItem) };
208 ToolButton buttonSaveAllFile { this, toolTip = $"Save all", menuItemPtr = IDEItem(fileSaveAllItem) };
210 ToolSeparator separator1 { this };
219 // ToolSeparator separator2 { this };
221 /* Project options */
223 ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) };
225 ToolButton buttonOpenProject { this, toolTip = $"Open project", menuItemPtr = IDEItem(projectOpenItem) };
226 // Add project to workspace
227 ToolButton buttonAddProject { this, toolTip = $"Add project to workspace", menuItemPtr = IDEItem(projectAddItem), disabled = true; };
229 // ToolButton buttonCloseProject { this, toolTip = $"Close project", menuItemPtr = IDEItem(projectCloseItem), disabled = true; };
231 ToolSeparator separator3 { this };
233 /* Build/Execution options */
235 ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; };
237 ToolButton buttonReLink { this, toolTip = $"Relink project", menuItemPtr = IDEItem(projectLinkItem), disabled = true; };
239 ToolButton buttonRebuild { this, toolTip = $"Rebuild project", menuItemPtr = IDEItem(projectRebuildItem), disabled = true; };
241 ToolButton buttonClean { this, toolTip = $"Clean project", menuItemPtr = IDEItem(projectCleanItem), disabled = true; };
243 // ToolButton buttonRealClean { this, toolTip = $"Real clean project", menuItemPtr = IDEItem(projectRealCleanItem), disabled = true; };
244 // Regenerate Makefile
245 ToolButton buttonRegenerateMakefile { this, toolTip = $"Regenerate Makefile", menuItemPtr = IDEItem(projectRegenerateItem), disabled = true; };
246 // Compile actual file
248 ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
250 ToolSeparator separator4 { this };
254 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
256 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
258 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
260 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
262 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
264 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
266 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
268 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
270 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
272 ToolSeparator separator5 { this };
274 Window spacer5 { this, size = { 4 } };
278 this, toolTip = $"Active Configuration(s)", size = { 160 };
279 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
283 for(prj : ide.workspace.projects)
285 for(cfg : prj.configurations)
287 if(cfg.name && !strcmp(cfg.name, row.string))
294 ide.UpdateToolBarActiveConfigs(true);
295 ide.projectView.Update(null);
301 Window spacer6 { this, size = { 4 } };
303 DropBox activeCompiler
305 this, toolTip = $"Active Compiler", size = { 160 };
306 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
308 if(row && strcmp(row.string, ide.workspace.compiler))
310 CompilerConfig compiler = ideSettings.GetCompilerConfig(row.string);
311 ide.workspace.compiler = row.string;
312 ide.projectView.ShowOutputBuildLog(true);
313 ide.projectView.DisplayCompiler(compiler, false);
314 for(prj : ide.workspace.projects)
315 ide.projectView.ProjectPrepareCompiler(prj, compiler);
317 ide.workspace.Save();
323 Window spacer7 { this, size = { 4 } };
327 class IDEMainFrame : Window
329 background = formColor;
330 borderStyle = sizable;
334 minClientSize = { 600, 300 };
336 icon = { ":icon.png" };
337 text = titleECEREIDE;
341 anchor = { top = 0, right = 0, bottom = 0 };
344 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
351 isActiveClient = true;
353 direction = vertical;
354 background = formColor;
355 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
363 ((IDEWorkSpace)master).toolBar = null;
366 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
369 define ide = ideMainFrame.ideWorkSpace;
371 class IDEWorkSpace : Window
373 background = Color { 85, 85, 85 };
376 hasVertScroll = true;
377 hasHorzScroll = true;
379 isActiveClient = true;
380 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
384 MenuItem * driverItems, * skinItems;
385 StatusField pos { width = 150 };
386 StatusField ovr, caps, num;
388 BitmapResource back { ":ecereBack.jpg", window = this };
389 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
390 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
391 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
392 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
393 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
394 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
395 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
396 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
397 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
398 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
400 Debugger debugger { };
402 ProjectView projectView;
404 OutputView outputView
408 void OnGotoError(char * line)
413 void OnCodeLocationParseAndGoTo(char * line)
415 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
418 bool OnKeyDown(Key key, unichar ch)
423 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
424 ide.ShowCodeEditor();
427 ide.projectView.stopBuild = true;
431 OutputView::OnKeyDown(key, ch);
438 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
441 ide.RepositionWindows(false);
445 bool OnClose(bool parentClosing)
449 ide.RepositionWindows(false);
450 return parentClosing;
454 CallStackView callStackView
456 parent = this, font = { panelFont.faceName, panelFont.size };
458 void OnGotoLine(char * line)
461 stackLvl = atoi(line);
462 ide.debugger.GoToStackFrameLine(stackLvl, true);
465 void OnSelectFrame(int lineNumber)
467 ide.debugger.SelectFrame(lineNumber);
470 void OnToggleBreakpoint()
472 Debugger debugger = ide.debugger;
473 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
475 int line = debugger.activeFrame.line;
476 char name[MAX_LOCATION];
478 // TOFIX: Improve on this, don't use only filename, make a function
479 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
480 if(ide && ide.workspace)
482 for(p : ide.workspace.projects)
484 if(p.topNode.Find(name, false))
492 for(p : ide.workspace.projects)
494 if(IsPathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
502 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
505 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
506 if(codeEditor) { codeEditor.Update(null); Activate(); }
511 bool OnKeyDown(Key key, unichar ch)
515 case escape: ide.ShowCodeEditor(); break;
520 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
523 ide.RepositionWindows(false);
527 bool OnClose(bool parentClosing)
531 ide.RepositionWindows(false);
532 return parentClosing;
535 void OnRedraw(Surface surface)
537 Debugger debugger = ide.debugger;
538 Frame activeFrame = debugger.activeFrame;
542 int lineCursor, lineTopFrame, activeThread, hitThread;
543 int lineH, scrollY, boxH;
545 Breakpoint bp = null;
548 scrollY = editBox.scroll.y;
549 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
550 activeThread = debugger.activeThread;
551 hitThread = debugger.hitThread;
552 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
554 // TODO: improve bp drawing... it should be visible even if it's not on the activeFrame
555 if(activeFrame.absoluteFile)
557 for(i : ide.workspace.breakpoints; i.type == user)
559 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
560 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
561 activeFrame.line == i.line)
569 DrawLineMarginIcon(surface,
570 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
571 lineCursor /*1*/, lineH, scrollY, boxH);
573 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
574 DrawLineMarginIcon(surface,
575 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
576 1, lineH, scrollY, boxH);
578 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
579 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
580 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
582 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
583 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
585 if(editBox.horzScroll && editBox.horzScroll.visible)
587 surface.SetBackground(control);
588 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
593 WatchesView watchesView { parent = this };
594 ThreadsView threadsView
596 parent = this, font = { panelFont.faceName, panelFont.size };
598 bool OnKeyDown(Key key, unichar ch)
602 case escape: ide.ShowCodeEditor(); break;
607 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
610 ide.RepositionWindows(false);
614 bool OnClose(bool parentClosing)
618 ide.RepositionWindows(false);
619 return parentClosing;
622 void OnSelectThread(int threadId)
625 ide.debugger.SelectThread(threadId);
628 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
631 Debugger debugger = ide.debugger;
632 *activeThread = debugger.activeThread;
633 *hitThread = debugger.hitThread;
634 *signalThread = debugger.signalThread;
639 BreakpointsView breakpointsView { parent = this };
641 ToolBox toolBox { parent = this };
642 Sheet sheet { parent = this };
645 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
647 Menu fileMenu { menu, $"File", f, hasMargin = true };
650 fileMenu, $"New", n, ctrlN;
651 bitmap = { ":actions/docNew.png" };
652 bool NotifySelect(MenuItem selection, Modifiers mods)
654 Window document = (Window)NewCodeEditor(this, normal, false);
655 document.NotifySaved = DocumentSaved;
659 MenuItem fileOpenItem
661 fileMenu, $"Open...", o, ctrlO;
662 bitmap = { ":actions/docOpen.png" };
663 bool NotifySelect(MenuItem selection, Modifiers mods)
665 if(!projectView && ideSettings.ideFileDialogLocation)
666 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
669 if(ideFileDialog.Modal() == ok)
671 bool gotWhatWeWant = false;
673 int numSelections = ideFileDialog.numSelections;
674 char ** multiFilePaths = ideFileDialog.multiFilePaths;
676 for(c = 0; c < numSelections; c++)
678 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
679 gotWhatWeWant = true;
682 MessageBox { type = yesNo, master = this, text = $"Error opening file",
683 contents = $"Open a different file?" }.Modal() == no)
685 if(!projectView && gotWhatWeWant)
686 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
696 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
697 MenuDivider { fileMenu };
698 MenuItem fileSaveItem
700 fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" };
702 // For the toolbar button; clients can still override that for the menu item
703 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
705 Window w = activeClient;
707 w.MenuFileSave(null, 0);
711 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
712 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
713 MenuDivider { fileMenu };
716 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
717 bool NotifySelect(MenuItem selection, Modifiers mods)
719 findInFilesDialog.replaceMode = false;
720 findInFilesDialog.Show();
724 MenuItem replaceInFiles
726 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
727 bool NotifySelect(MenuItem selection, Modifiers mods)
729 findInFilesDialog.replaceMode = true;
730 findInFilesDialog.Show();
734 MenuDivider { fileMenu };
735 MenuItem globalSettingsItem
737 fileMenu, $"Global Settings...", g;
738 bool NotifySelect(MenuItem selection, Modifiers mods)
740 globalSettingsDialog.master = this;
741 if(ide.workspace && ide.workspace.compiler)
742 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
743 else if(ideSettings.defaultCompiler)
744 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
745 globalSettingsDialog.Modal();
749 MenuDivider { fileMenu };
750 Menu recentFiles { fileMenu, $"Recent Files", r };
751 Menu recentProjects { fileMenu, $"Recent Projects", p };
752 MenuDivider { fileMenu };
755 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
757 bool NotifySelect(MenuItem selection, Modifiers mods)
759 ideMainFrame.Destroy(0);
764 bool FileRecentFile(MenuItem selection, Modifiers mods)
767 for(file : ideSettings.recentFiles)
769 if(id == selection.id)
771 if(mods.ctrl) // Menu::OnLeftButtonUp -> modifiers.ctrl == true, modifiers == 18
772 // Menu::MenuItemSelection -> key.ctrl == false, key.modifiers.ctrl == false, key == 18
773 // removing the (Key) cast from Modifiers when calling MenuItemSelection in OnLeftButtonUp didn't help
775 // it never gets in here!!!
776 char * command = PrintString("ide ", file);
781 OpenFile(file, normal, true, null, no, normal);
789 bool FileRecentProject(MenuItem selection, Modifiers mods)
792 for(file : ideSettings.recentProjects)
794 if(id == selection.id)
796 if(mods.ctrl) // Menu::OnLeftButtonUp -> modifiers.ctrl == true, modifiers == 18
797 // Menu::MenuItemSelection -> key.ctrl == false, key.modifiers.ctrl == false, key == 18
798 // removing the (Key) cast from Modifiers when calling MenuItemSelection in OnLeftButtonUp didn't help
800 // it never gets in here!!!
801 char * command = PrintString("ide ", file);
806 OpenFile(file, normal, true, null, no, normal);
814 MenuPlacement editMenu { menu, $"Edit", e };
816 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
817 MenuItem projectNewItem
819 projectMenu, $"New...", n, Key { n, true, true };
820 bitmap = { ":actions/projNew.png" };
821 bool NotifySelect(MenuItem selection, Modifiers mods)
823 if(!DontTerminateDebugSession($"New Project"))
824 if(MenuWindowCloseAll(null, 0))
826 NewProjectDialog newProjectDialog;
830 projectView.visible = false;
831 if(!projectView.Destroy(0))
835 newProjectDialog = { master = this };
836 newProjectDialog.Modal();
839 ideSettings.AddRecentProject(projectView.fileName);
840 ide.UpdateRecentMenus();
841 settingsContainer.Save();
847 MenuItem projectOpenItem
849 projectMenu, $"Open...", o, Key { o, true, true };
850 bitmap = { ":actions/projOpen.png" };
851 bool NotifySelect(MenuItem selection, Modifiers mods)
853 if(ideSettings.ideProjectFileDialogLocation)
854 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
856 ideProjectFileDialog.text = openProjectFileDialogTitle;
857 if(ideProjectFileDialog.Modal() == ok)
859 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
860 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
865 MenuItem projectQuickItem
867 projectMenu, $"Quick...", q, f7, disabled = true;
868 bool NotifySelect(MenuItem selection, Modifiers mods)
871 QuickProjectDialog { this }.Modal();
875 MenuItem projectAddItem
877 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
878 bitmap = { ":actions/projAdd.png" };
880 bool NotifySelect(MenuItem selection, Modifiers mods)
882 if(ideSettings.ideProjectFileDialogLocation)
883 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
885 ideProjectFileDialog.text = addProjectFileDialogTitle;
888 if(ideProjectFileDialog.Modal() == ok)
890 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
892 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
893 contents = $"Add a different project?" }.Modal() == no)
904 MenuItem projectCloseItem
906 projectMenu, $"Close", c, disabled = true;
907 bool NotifySelect(MenuItem selection, Modifiers mods)
911 if(!ide.DontTerminateDebugSession($"Project Close"))
913 if(findInFilesDialog)
914 findInFilesDialog.SearchStop();
915 projectView.visible = false;
916 if(projectView.Destroy(0))
917 MenuWindowCloseAll(null, 0);
919 char workingDir[MAX_LOCATION];
920 GetWorkingDir(workingDir, MAX_LOCATION);
921 findInFilesDialog.currentDirectory = workingDir;
922 ideMainFrame.text = titleECEREIDE;
929 MenuDivider { projectMenu };
930 MenuItem projectSettingsItem
932 projectMenu, $"Settings...", s, altF7, disabled = true;
933 bool NotifySelect(MenuItem selection, Modifiers mods)
935 projectView.MenuSettings(projectView.active ? selection : null, mods);
939 MenuDivider { projectMenu };
940 MenuItem projectBrowseFolderItem
942 projectMenu, $"Browse Project Folder", p, disabled = true;
943 bool NotifySelect(MenuItem selection, Modifiers mods)
946 projectView.MenuBrowseFolder(null, mods);
950 MenuDivider { projectMenu };
951 MenuItem projectRunItem
953 projectMenu, $"Run", r, ctrlF5, disabled = true;
954 bitmap = { ":actions/run.png" };
955 bool NotifySelect(MenuItem selection, Modifiers mods)
958 projectView.Run(null, mods);
962 MenuItem projectBuildItem
964 projectMenu, $"Build", b, f7, disabled = true;
965 bitmap = { ":actions/build.png" };
966 bool NotifySelect(MenuItem selection, Modifiers mods)
969 projectView.ProjectBuild(projectView.active ? selection : null, mods);
973 MenuItem projectLinkItem
975 projectMenu, $"Relink", l, disabled = true;
976 bitmap = { ":actions/relink.png" };
977 bool NotifySelect(MenuItem selection, Modifiers mods)
980 projectView.ProjectLink(projectView.active ? selection : null, mods);
984 MenuItem projectRebuildItem
986 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
987 bitmap = { ":actions/rebuild.png" };
988 bool NotifySelect(MenuItem selection, Modifiers mods)
991 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
995 MenuItem projectCleanItem
997 projectMenu, $"Clean", e, disabled = true;
998 bitmap = { ":actions/clean.png" };
999 bool NotifySelect(MenuItem selection, Modifiers mods)
1004 projectView.ProjectClean(projectView.active ? selection : null, mods);
1009 MenuItem projectRealCleanItem
1011 projectMenu, $"Real Clean", disabled = true;
1012 bitmap = { ":actions/clean.png" };
1013 bool NotifySelect(MenuItem selection, Modifiers mods)
1018 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
1023 MenuItem projectRegenerateItem
1025 projectMenu, $"Regenerate Makefile", m, disabled = true;
1026 bitmap = { ":actions/regMakefile.png" };
1027 bool NotifySelect(MenuItem selection, Modifiers mods)
1030 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
1034 MenuItem projectCompileItem;
1035 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
1036 MenuItem debugStartResumeItem
1038 debugMenu, $"Start", s, f5, disabled = true;
1039 bitmap = { ":actions/debug.png" };
1040 NotifySelect = MenuDebugStart;
1042 bool MenuDebugStart(MenuItem selection, Modifiers mods)
1046 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
1047 if(!projectView.DebugStart())
1048 debugStartResumeItem.disabled = false; // same exception
1052 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1055 projectView.DebugResume();
1058 MenuItem debugRestartItem
1060 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1061 bitmap = { ":actions/restart.png" };
1062 bool NotifySelect(MenuItem selection, Modifiers mods)
1065 projectView.DebugRestart();
1069 MenuItem debugBreakItem
1071 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1072 bitmap = { ":actions/pause.png" };
1073 bool NotifySelect(MenuItem selection, Modifiers mods)
1076 projectView.DebugBreak();
1080 MenuItem debugStopItem
1082 debugMenu, $"Stop", p, shiftF5, disabled = true;
1083 bitmap = { ":actions/stopDebug.png" };
1084 bool NotifySelect(MenuItem selection, Modifiers mods)
1087 projectView.DebugStop();
1091 MenuDivider { debugMenu };
1092 MenuItem debugStepIntoItem
1094 debugMenu, $"Step Into", i, f11, disabled = true;
1095 bitmap = { ":actions/stepInto.png" };
1096 bool NotifySelect(MenuItem selection, Modifiers mods)
1099 projectView.DebugStepInto();
1103 MenuItem debugStepOverItem
1105 debugMenu, $"Step Over", v, f10, disabled = true;
1106 bitmap = { ":actions/stepOver.png" };
1107 bool NotifySelect(MenuItem selection, Modifiers mods)
1110 projectView.DebugStepOver(false);
1114 MenuItem debugStepOutItem
1116 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1117 bitmap = { ":actions/stepOut.png" };
1118 bool NotifySelect(MenuItem selection, Modifiers mods)
1121 projectView.DebugStepOut(false);
1125 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1126 MenuItem debugSkipStepOverItem
1128 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1129 bool NotifySelect(MenuItem selection, Modifiers mods)
1132 projectView.DebugStepOver(true);
1136 MenuItem debugSkipStepOutItem
1138 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1139 bitmap = { ":actions/skipBreaks.png" };
1140 bool NotifySelect(MenuItem selection, Modifiers mods)
1143 projectView.DebugStepOut(true);
1147 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1148 //MenuDivider { debugMenu };
1149 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1150 MenuPlacement imageMenu { menu, $"Image", i };
1151 Menu viewMenu { menu, $"View", v };
1152 MenuItem viewProjectItem
1154 viewMenu, $"Project View", j, alt0, disabled = true;
1155 bool NotifySelect(MenuItem selection, Modifiers mods)
1159 projectView.visible = true;
1160 projectView.Activate();
1165 MenuPlacement { viewMenu, $"View Designer" };
1166 MenuPlacement { viewMenu, $"View Code" };
1167 MenuPlacement { viewMenu, $"View Properties" };
1168 MenuPlacement { viewMenu, $"View Methods" };
1169 MenuItem viewDesignerItem
1171 viewMenu, $"View Designer", d, f8;
1172 bool NotifySelect(MenuItem selection, Modifiers mods)
1174 Window client = activeClient;
1175 Class dataType = client._class;
1176 if(!strcmp(dataType.name, "Designer"))
1178 client.visible = true;
1182 ((CodeEditor)client).ViewDesigner();
1186 MenuItem viewCodeItem
1188 viewMenu, $"View Code", c, f8;
1189 bool NotifySelect(MenuItem selection, Modifiers mods)
1191 Window client = activeClient;
1192 Class dataType = client._class;
1193 if(!strcmp(dataType.name, "Designer"))
1194 client = ((Designer)client).codeEditor;
1197 // Do this after so the caret isn't moved yet...
1198 client.visible = true;
1202 MenuItem viewPropertiesItem
1204 viewMenu, $"View Properties", p, f4;
1205 bool NotifySelect(MenuItem selection, Modifiers mods)
1207 sheet.visible = true;
1208 sheet.sheetSelected = properties;
1213 MenuItem viewMethodsItem
1215 viewMenu, $"View Methods", m, f4;
1216 bool NotifySelect(MenuItem selection, Modifiers mods)
1218 sheet.visible = true;
1219 sheet.sheetSelected = methods;
1224 MenuItem viewToolBoxItem
1226 viewMenu, $"View Toolbox", x, f12;
1227 bool NotifySelect(MenuItem selection, Modifiers mods)
1229 toolBox.visible = true;
1234 MenuItem viewOutputItem
1236 viewMenu, $"Output", o, alt2;
1237 bool NotifySelect(MenuItem selection, Modifiers mods)
1243 MenuItem viewWatchesItem
1245 viewMenu, $"Watches", w, alt3;
1246 bool NotifySelect(MenuItem selection, Modifiers mods)
1252 MenuItem viewThreadsItem
1254 viewMenu, $"Threads", t, alt4;
1255 bool NotifySelect(MenuItem selection, Modifiers mods)
1261 MenuItem viewBreakpointsItem
1263 viewMenu, $"Breakpoints", b, alt5;
1264 bool NotifySelect(MenuItem selection, Modifiers mods)
1266 breakpointsView.Show();
1270 MenuItem viewCallStackItem
1272 viewMenu, $"Call Stack", s, alt7;
1273 bool NotifySelect(MenuItem selection, Modifiers mods)
1275 callStackView.Show();
1279 MenuItem viewAllDebugViews
1281 viewMenu, $"All Debug Views", a, alt9;
1282 bool NotifySelect(MenuItem selection, Modifiers mods)
1287 callStackView.Show();
1288 breakpointsView.Show();
1292 #ifdef GDB_DEBUG_GUI
1293 MenuDivider { viewMenu };
1294 MenuItem viewGDBItem
1296 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1297 bool NotifySelect(MenuItem selection, Modifiers mods)
1304 MenuDivider { viewMenu };
1305 MenuItem viewColorPicker
1307 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1308 bool NotifySelect(MenuItem selection, Modifiers mods)
1310 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1311 colorPicker.Create();
1315 MenuDivider { viewMenu };
1319 viewMenu, "Full Screen", f, checkable = true;
1321 bool NotifySelect(MenuItem selection, Modifiers mods)
1323 app.fullScreen ^= true;
1325 anchor = { 0, 0, 0, 0 };
1330 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1331 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1332 Menu windowMenu { menu, $"Window", w };
1333 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1334 MenuDivider { windowMenu };
1335 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1336 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1337 MenuDivider { windowMenu };
1338 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1339 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1340 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1341 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1342 MenuDivider { windowMenu };
1343 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1344 Menu helpMenu { menu, $"Help", h };
1347 helpMenu, $"API Reference", r, f1;
1348 bool NotifySelect(MenuItem selection, Modifiers mods)
1350 Execute("documentor");
1354 MenuDivider { helpMenu };
1357 helpMenu, $"About...", a;
1358 bool NotifySelect(MenuItem selection, Modifiers mods)
1360 AboutIDE { master = this }.Modal();
1365 property ToolBox toolBox
1367 get { return toolBox; }
1370 property Sheet sheet
1372 get { return sheet; }
1375 property Project project
1377 get { return projectView ? projectView.project : null; }
1380 property Workspace workspace
1382 get { return projectView ? projectView.workspace : null; }
1385 FindInFilesDialog findInFilesDialog
1387 master = this, parent = this;
1388 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1392 #ifdef GDB_DEBUG_GUI
1395 master = this, parent = this;
1396 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1398 void OnCommand(char * string)
1401 ide.debugger.SendGDBCommand(string);
1406 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1408 //app.driver = app.drivers[selection.id];
1409 #if defined(__unix__) || defined(__APPLE__)
1410 app.driver = selection.id ? "OpenGL" : "X";
1412 app.driver = selection.id ? "OpenGL" : "GDI";
1414 delete ideSettings.displayDriver;
1415 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1417 settingsContainer.Save();
1418 //SetDriverAndSkin();
1422 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1424 app.skin = app.skins[selection.id];
1429 void SetDriverAndSkin()
1432 for(c = 0; c < app.numSkins; c++)
1433 if(!strcmp(app.skins[c], app.skin))
1435 skinItems[c].checked = true;
1438 for(c = 0; c < app.numDrivers; c++)
1439 if(!strcmp(app.drivers[c], app.driver))
1441 driverItems[c].checked = true;
1446 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1448 Project project = workspace.projects.firstIterator.data;
1449 projectView = ProjectView
1452 fileName = fileName;
1454 void NotifyDestroyed(Window window, DialogResult result)
1457 text = titleECEREIDE;
1462 projectView.Create();
1463 RepositionWindows(false);
1465 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1466 projectView.workspace = workspace;
1467 projectView.project = project;
1468 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1472 ide.breakpointsView.LoadFromWorkspace();
1473 ide.watchesView.LoadFromWorkspace();
1475 findInFilesDialog.projectNodeField.userData = projectView;
1478 char fileName[MAX_LOCATION];
1479 strcpy(fileName, project.topNode.path);
1480 PathCat(fileName, project.topNode.name);
1485 bool GetDebugMenusDisabled()
1489 Project project = projectView.project;
1491 if(project.GetTargetType(project.config) == executable)
1498 void RepositionWindows(bool expand)
1503 bool inDebugMode = debugger.isActive;
1504 bool callStackVisible = expand ? false : callStackView.visible;
1505 bool threadsVisible = expand ? false : threadsView.visible;
1506 bool watchesVisible = expand ? false : watchesView.visible;
1507 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1508 bool toolBoxVisible = toolBox.visible;
1509 bool outputVisible = expand ? false : outputView.visible;
1510 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1511 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1513 for(child = firstChild; child; child = child.next)
1515 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1516 child._class == class(Sheet) || child._class == class(ProjectView))
1518 Anchor anchor = child.anchor;
1519 anchor.top = topDistance;
1520 anchor.bottom = bottomDistance;
1521 if(child._class == class(CodeEditor) || child._class == class(Designer))
1523 anchor.right = toolBoxVisible ? 150 : 0;
1525 child.anchor = anchor;
1529 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1530 child._class == class(BreakpointsView))
1531 child.visible = false;
1534 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1539 bool ShowCodeEditor()
1542 activeClient.Activate();
1543 else if(projectView)
1545 projectView.visible = true;
1546 projectView.Activate();
1550 sheet.visible = true;
1556 bool ShouldStopBuild()
1558 return projectView.stopBuild;
1561 void DocumentSaved(Window document, char * fileName)
1563 ideSettings.AddRecentFile(fileName);
1564 ide.UpdateRecentMenus();
1565 ide.AdjustFileMenus();
1566 settingsContainer.Save();
1569 bool Window::OnFileModified(FileChange fileChange, char * param)
1572 sprintf(temp, $"The document %s was modified by another application.\n"
1573 "Would you like to reload it and lose your changes?", this.fileName);
1574 if(MessageBox { type = yesNo, master = this/*.parent*/,
1575 text = $"Document has been modified", contents = temp }.Modal() == yes)
1577 char * fileName = CopyString(this.fileName);
1578 WindowState state = this.state;
1579 Anchor anchor = this.anchor;
1580 Size size = this.size;
1582 this.modifiedDocument = false;
1584 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1587 this.anchor = anchor;
1589 this.SetState(state, true, 0);
1597 void UpdateMakefiles()
1601 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1602 for(prj : workspace.projects)
1603 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1608 void UpdateCompilerConfigs()
1610 UpdateToolBarActiveCompilers();
1613 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1614 projectView.ShowOutputBuildLog(true);
1615 projectView.DisplayCompiler(compiler, false);
1616 for(prj : workspace.projects)
1617 projectView.ProjectPrepareCompiler(prj, compiler);
1622 void UpdateToolBarActiveCompilers()
1624 toolBar.activeCompiler.Clear();
1625 for(compiler : ideSettings.compilerConfigs)
1627 DataRow row = toolBar.activeCompiler.AddString(compiler.name);
1628 if(workspace && workspace.compiler && !strcmp(compiler.name, workspace.compiler))
1629 toolBar.activeCompiler.currentRow = row;
1631 if(!toolBar.activeCompiler.currentRow)
1632 toolBar.activeCompiler.currentRow = toolBar.activeCompiler.firstRow;
1633 toolBar.activeCompiler.disabled = workspace == null;
1636 void UpdateToolBarActiveConfigs(bool selectionOnly)
1638 bool commonSelected = false;
1639 DataRow row = toolBar.activeConfig.currentRow;
1641 row = toolBar.activeConfig.FindRow(1);
1644 toolBar.activeConfig.Clear();
1645 row = toolBar.activeConfig.AddString("(Mixed)");
1650 char * configName = null;
1653 Map<String, int> configs { }; // TOIMP: just need sort but using map until containers have sort
1654 for(prj : workspace.projects)
1656 for(cfg : prj.configurations)
1659 configs[cfg.name] = 1;
1664 toolBar.activeConfig.AddString(&name);
1668 if(projectView && projectView.project)
1670 for(prj : workspace.projects)
1672 if(prj.config && prj.config.name)
1674 configName = prj.config.name;
1680 commonSelected = true;
1681 for(prj : workspace.projects)
1683 if(prj.config && (!prj.config.name || strcmp(prj.config.name, configName)))
1685 commonSelected = false;
1693 commonSelected = false;
1694 for(row = toolBar.activeConfig.firstRow; row; row = row.next)
1696 if(!strcmp(row.string, configName))
1698 toolBar.activeConfig.currentRow = row;
1699 commonSelected = true;
1706 toolBar.activeConfig.Sort(null, 0);
1708 toolBar.activeConfig.currentRow = row;
1709 toolBar.activeConfig.disabled = workspace == null;
1714 bool unavailable = !project;
1716 projectAddItem.disabled = unavailable;
1717 toolBar.buttonAddProject.disabled = unavailable;
1719 projectSettingsItem.disabled = unavailable;
1721 projectBrowseFolderItem.disabled = unavailable;
1723 viewProjectItem.disabled = unavailable;
1730 property bool hasOpenedCodeEditors
1735 for(w = firstChild; w; w = w.next)
1736 if(w._class == class(CodeEditor) &&
1737 w.isDocument && !w.closing && w.visible && w.created &&
1738 w.fileName && w.fileName[0])
1744 void AdjustFileMenus()
1746 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1748 projectQuickItem.disabled = unavailable;
1751 void AdjustBuildMenus()
1753 bool unavailable = project && projectView.buildInProgress;
1755 projectNewItem.disabled = unavailable;
1756 toolBar.buttonNewProject.disabled = unavailable;
1757 projectOpenItem.disabled = unavailable;
1758 toolBar.buttonOpenProject.disabled = unavailable;
1760 unavailable = !project || projectView.buildInProgress;
1762 projectCloseItem.disabled = unavailable;
1763 // toolBar.buttonCloseProject.disabled = unavailable;
1765 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1766 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1767 projectBuildItem.disabled = unavailable;
1768 toolBar.buttonBuild.disabled = unavailable;
1769 projectLinkItem.disabled = unavailable;
1770 toolBar.buttonReLink.disabled = unavailable;
1771 projectRebuildItem.disabled = unavailable;
1772 toolBar.buttonRebuild.disabled = unavailable;
1773 projectCleanItem.disabled = unavailable;
1774 toolBar.buttonClean.disabled = unavailable;
1775 projectRealCleanItem.disabled = unavailable;
1776 // toolBar.buttonRealClean.disabled = unavailable;
1777 projectRegenerateItem.disabled = unavailable;
1778 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1779 projectCompileItem.disabled = unavailable;
1781 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
1784 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0); if(menu) menu.disabled = unavailable;
1785 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
1786 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
1787 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
1788 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
1789 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
1790 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable;
1791 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable;
1792 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable;
1793 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable;
1794 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable;
1795 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable;
1796 projectView.popupMenu.Update(null);
1800 void AdjustDebugMenus()
1802 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1803 projectView.buildInProgress == buildingMainProject;
1804 bool active = ide.debugger.isActive;
1805 bool executing = ide.debugger.state == running;
1806 //bool holding = ide.debugger.state == stopped;
1808 debugStartResumeItem.disabled = unavailable || executing;
1809 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1810 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1813 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1814 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1817 debugBreakItem.disabled = unavailable || !executing;
1818 debugStopItem.disabled = unavailable || !active;
1819 debugRestartItem.disabled = unavailable || !active;
1822 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1823 toolBar.buttonDebugStop.disabled = unavailable || !active;
1824 toolBar.buttonDebugRestart.disabled = unavailable || !active;
1827 debugStepIntoItem.disabled = unavailable || executing;
1828 debugStepOverItem.disabled = unavailable || executing;
1829 debugStepOutItem.disabled = unavailable || executing || !active;
1830 debugSkipStepOverItem.disabled = unavailable || executing;
1831 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1834 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1835 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1836 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1837 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1838 // toolBar.buttonDebugSkipStepOutItem.disabled = unavailable || executing;
1840 if((Designer)GetActiveDesigner())
1842 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1845 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1846 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1851 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1853 char tempString[MAX_LOCATION];
1854 strcpy(tempString, directory);
1855 if(saveSettings && !projectView)
1857 ideSettings.ideFileDialogLocation = directory;
1858 settingsContainer.Save();
1861 ideFileDialog.currentDirectory = tempString;
1862 codeEditorFileDialog.currentDirectory = tempString;
1863 codeEditorFormFileDialog.currentDirectory = tempString;
1866 void ChangeProjectFileDialogDirectory(char * directory)
1868 ideSettings.ideProjectFileDialogLocation = directory;
1869 settingsContainer.Save();
1872 Window FindWindow(char * filePath)
1874 Window document = null;
1876 // TOCHECK: Do we need to change slashes here?
1877 for(document = firstChild; document; document = document.next)
1879 char * fileName = document.fileName;
1880 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1882 document.visible = true;
1883 document.Activate();
1890 bool DontTerminateDebugSession(char * title)
1892 if(debugger.isActive)
1894 if(MessageBox { type = yesNo, master = ide,
1895 contents = $"Do you want to terminate the debugging session in progress?",
1896 text = title }.Modal() == no)
1899 MessageBox msg { type = yesNo, master = ide,
1900 contents = "Do you want to terminate the debugging session in progress?",
1902 if(msg.Modal() == no)
1914 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1916 char extension[MAX_EXTENSION] = "";
1917 Window document = null;
1918 bool isProject = false;
1919 bool needFileModified = true;
1920 char winFilePath[MAX_LOCATION];
1921 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1925 GetExtension(filePath, extension);
1929 strcpy(extension, type);
1931 if(strcmp(extension, ProjectExtension))
1933 for(document = firstChild; document; document = document.next)
1935 char * fileName = document.fileName;
1936 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1938 document.visible = true;
1940 document.Activate();
1946 if(createIfFails == whatever)
1948 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1950 needFileModified = false;
1951 if(openMethod == normal)
1953 if(DontTerminateDebugSession($"Open Project"))
1956 if(MenuWindowCloseAll(null, 0))
1960 projectView.visible = false;
1961 projectView.Destroy(0);
1962 // Where did this come from? projectView = null;
1969 Workspace workspace = null;
1971 if(FileExists(filePath))
1973 if(!strcmp(extension, ProjectExtension))
1975 char workspaceFile[MAX_LOCATION];
1976 strcpy(workspaceFile, filePath);
1977 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1978 workspace = LoadWorkspace(workspaceFile, filePath);
1980 else if(!strcmp(extension, WorkspaceExtension))
1981 workspace = LoadWorkspace(filePath, null);
1984 //project = LoadProject(filePath, null);
1989 char absolutePath[MAX_LOCATION];
1990 CreateProjectView(workspace, filePath);
1991 document = projectView;
1993 workspace.DropInvalidBreakpoints();
1996 ide.projectView.ShowOutputBuildLog(true);
1998 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1999 ide.projectView.DisplayCompiler(compiler, false);
2002 UpdateCompilerConfigs();
2005 char newWorkingDir[MAX_LOCATION];
2006 StripLastDirectory(filePath, newWorkingDir);
2007 ChangeFileDialogsDirectory(newWorkingDir, false);
2010 document.fileName = filePath;
2012 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
2014 // this crashes on starting ide with epj file, solution please?
2015 // app.UpdateDisplay();
2017 workspace.holdTracking = true;
2018 for(ofi : workspace.openedFiles)
2020 if(ofi.state != closed)
2022 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
2025 char fileName[MAX_LOCATION];
2027 GetLastDirectory(ofi.path, fileName);
2028 node = projectView.project.topNode.Find(fileName, true);
2030 node.EnsureVisible();
2034 workspace.holdTracking = false;
2036 workspace.timer.Start();
2038 findInFilesDialog.mode = FindInFilesMode::project;
2039 findInFilesDialog.currentDirectory = ide.project.topNode.path;
2042 char location[MAX_LOCATION];
2043 StripLastDirectory(ide.project.topNode.path, location);
2044 ChangeProjectFileDialogDirectory(location);
2048 if(projectView.debugger)
2049 projectView.debugger.EvaluateWatches();
2056 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
2058 ideProjectFileDialog.text = openProjectFileDialogTitle;
2059 if(ideProjectFileDialog.Modal() == cancel)
2061 filePath = ideProjectFileDialog.filePath;
2062 GetExtension(filePath, extension);
2073 else if(openMethod == add)
2078 char slashFilePath[MAX_LOCATION];
2079 GetSlashPathBuffer(slashFilePath, filePath);
2080 for(p : workspace.projects)
2082 if(!fstrcmp(p.filePath, slashFilePath))
2090 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
2091 contents = $"This project is already present in workspace." }.Modal();
2095 prj = LoadProject(filePath, null);
2098 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
2099 prj.StartMonitoring();
2100 workspace.projects.Add(prj);
2102 projectView.AddNode(prj.topNode, null);
2103 workspace.modified = true;
2105 findInFilesDialog.AddProjectItem(prj);
2106 projectView.ShowOutputBuildLog(true);
2107 projectView.DisplayCompiler(compiler, false);
2108 projectView.ProjectUpdateMakefileForAllConfigs(prj);
2112 char location[MAX_LOCATION];
2113 StripLastDirectory(prj.topNode.path, location);
2114 ChangeProjectFileDialogDirectory(location);
2117 // projectView is associated with the main project and not with the one just added but
2118 return projectView; // just to let the caller know something was opened
2126 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2127 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2128 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2130 if(FileExists(filePath))
2131 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2132 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2133 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2136 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2139 else if(!strcmp(extension, "3ds"))
2141 if(FileExists(filePath))
2142 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2143 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2144 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2148 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2151 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2152 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2153 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2154 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2155 !strcmp(extension, "js"))
2157 CodeEditor editor { parent = this, state = state, visible = false };
2158 editor.updatingCode = true;
2159 if(editor.LoadFile(filePath))
2162 editor.visible = true;
2166 needFileModified = false;
2170 CodeEditor editor { parent = this, state = state, visible = false };
2171 if(editor.LoadFile(filePath))
2174 editor.visible = true;
2178 needFileModified = false;
2181 if(document && (document._class == class(PictureEdit) ||
2182 document._class == class(ModelView)))
2187 document.fileName = filePath;
2188 if(workspace && !workspace.holdTracking)
2189 workspace.UpdateOpenedFileInfo(filePath, opened);
2193 if(!document && createIfFails != no)
2195 if(createIfFails != yes && !needFileModified &&
2196 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2197 createIfFails = yes;
2198 if(createIfFails == yes || createIfFails == whatever)
2200 document = (Window)NewCodeEditor(this, state, true);
2202 document.fileName = filePath;
2208 if(projectView && document._class == class(CodeEditor) && workspace)
2210 int lineNumber, position;
2212 CodeEditor editor = (CodeEditor)document;
2213 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2214 editor.openedFileInfo.holdTracking = true;
2215 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2216 position = Max(editor.openedFileInfo.position - 1, 0);
2217 editor.editBox.GoToLineNum(lineNumber);
2218 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2219 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2220 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2221 editor.editBox.scroll = scroll;
2222 editor.openedFileInfo.holdTracking = false;
2225 if(needFileModified)
2226 document.OnFileModified = OnFileModified;
2227 document.NotifySaved = DocumentSaved;
2230 ideSettings.AddRecentProject(document.fileName);
2232 ideSettings.AddRecentFile(document.fileName);
2233 ide.UpdateRecentMenus();
2234 ide.AdjustFileMenus();
2235 settingsContainer.Save();
2243 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2244 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2246 if(!parentClosing && ide.workspace)
2247 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2250 bool ModelView::ModelViewOnClose(bool parentClosing)
2252 if(!parentClosing && ide.workspace)
2253 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2256 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2258 if(!parentClosing && ide.workspace)
2259 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2264 void OnUnloadGraphics(Window window)
2266 display.ClearMaterials();
2267 display.ClearTextures();
2268 display.ClearMeshes();
2272 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2274 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2275 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2279 bool OnKeyDown(Key key, unichar ch)
2284 projectView.Update(null);
2287 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2290 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2296 void GoToError(const char * line)
2299 projectView.GoToError(line);
2302 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2305 char *colon = strchr(text, ':');
2306 char filePath[MAX_LOCATION];
2307 char completePath[MAX_LOCATION];
2308 int line = 0, col = 0;
2310 FileAttribs fileAttribs;
2312 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2314 path = (colon - 1 > path) ? colon - 1 : path;
2315 colon = strstr(colon + 1, ":");
2317 while(isspace(*path)) path++;
2320 char * close = strchr(path, ')');
2324 strncpy(name, path+1, close - path - 1);
2325 name[close - path - 1] = '\0';
2326 for(p : ide.workspace.projects)
2328 if(!strcmp(p.name, name))
2338 prj = project ? project : (dir ? null : ide.project);
2341 strncpy(filePath, path, colon - path);
2342 filePath[colon - path] = '\0';
2343 line = atoi(colon + 1);
2344 colon = strstr(colon + 1, ":");
2346 col = atoi(colon + 1);
2348 else if(path - 1 >= text && *(path - 1) == '\"')
2350 colon = strchr(path, '\"');
2353 strncpy(filePath, path, colon - path);
2354 filePath[colon - path] = '\0';
2357 else if(path && !colon)
2359 strcpy(filePath, path);
2363 strcpy(completePath, prj.topNode.path);
2364 else if(dir && dir[0])
2365 strcpy(completePath, dir);
2367 completePath[0] = '\0';
2368 PathCat(completePath, filePath);
2370 fileAttribs = FileExists(completePath);
2371 if(fileAttribs.isFile)
2373 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2374 if(codeEditor && line)
2376 EditBox editBox = codeEditor.editBox;
2377 editBox.GoToLineNum(line - 1);
2378 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2381 else if(fileAttribs.isDirectory)
2382 ShellOpen(completePath);
2385 void OnRedraw(Surface surface)
2387 Bitmap bitmap = back.bitmap;
2389 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2392 void SheetSelected(SheetType sheetSelected)
2394 if(activeChild == sheet)
2396 if(sheetSelected == methods)
2398 viewPropertiesItem.accelerator = f4;
2399 viewPropertiesItem.parent = viewMenu;
2400 viewMethodsItem.parent = null;
2404 viewMethodsItem.accelerator = f4;
2405 viewMethodsItem.parent = viewMenu;
2406 viewPropertiesItem.parent = null;
2411 viewMethodsItem.parent = viewMenu;
2412 viewPropertiesItem.parent = viewMenu;
2413 if(sheetSelected == methods)
2415 viewMethodsItem.accelerator = f4;
2416 viewPropertiesItem.accelerator = 0;
2420 viewMethodsItem.accelerator = 0;
2421 viewPropertiesItem.accelerator = f4;
2426 void OnActivateClient(Window client, Window previous)
2428 //if(!client || client != previous)
2431 if(!client || client != previous)
2434 dataType = previous._class;
2435 if(previous && !strcmp(dataType.name, "CodeEditor"))
2437 ((CodeEditor)previous).UpdateFormCode();
2439 else if(previous && !strcmp(dataType.name, "Designer"))
2441 ((Designer)previous).codeEditor.UpdateFormCode();
2446 dataType = client._class;
2447 if(client && !strcmp(dataType.name, "CodeEditor"))
2449 CodeEditor codeEditor = (CodeEditor)client;
2450 SetPrivateModule(codeEditor.privateModule);
2451 SetCurrentContext(codeEditor.globalContext);
2452 SetTopContext(codeEditor.globalContext);
2453 SetGlobalContext(codeEditor.globalContext);
2455 SetDefines(&codeEditor.defines);
2456 SetImports(&codeEditor.imports);
2458 SetActiveDesigner(codeEditor.designer);
2460 sheet.codeEditor = codeEditor;
2461 toolBox.codeEditor = codeEditor;
2463 viewDesignerItem.parent = viewMenu;
2464 if(activeChild != codeEditor)
2466 viewCodeItem.parent = viewMenu;
2467 viewDesignerItem.accelerator = 0;
2468 viewCodeItem.accelerator = f8;
2472 viewCodeItem.parent = null;
2473 viewDesignerItem.accelerator = f8;
2476 else if(client && !strcmp(dataType.name, "Designer"))
2478 CodeEditor codeEditor = ((Designer)client).codeEditor;
2481 SetPrivateModule(codeEditor.privateModule);
2482 SetCurrentContext(codeEditor.globalContext);
2483 SetTopContext(codeEditor.globalContext);
2484 SetGlobalContext(codeEditor.globalContext);
2485 SetDefines(&codeEditor.defines);
2486 SetImports(&codeEditor.imports);
2490 SetPrivateModule(null);
2491 SetCurrentContext(null);
2492 SetTopContext(null);
2493 SetGlobalContext(null);
2498 SetActiveDesigner((Designer)client);
2500 sheet.codeEditor = codeEditor;
2501 toolBox.codeEditor = codeEditor;
2503 viewCodeItem.parent = viewMenu;
2504 if(activeChild != client)
2506 viewDesignerItem.parent = viewMenu;
2507 viewDesignerItem.accelerator = f8;
2508 viewCodeItem.accelerator = 0;
2512 viewDesignerItem.parent = null;
2513 viewCodeItem.accelerator = f8;
2519 sheet.codeEditor = null;
2520 toolBox.codeEditor = null;
2521 SetActiveDesigner(null);
2523 viewDesignerItem.parent = null;
2524 viewCodeItem.parent = null;
2527 SheetSelected(sheet.sheetSelected);
2530 projectCompileItem = null;
2535 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2537 CodeEditor codeEditor = (CodeEditor)client;
2538 EditBox editBox = codeEditor.editBox;
2540 statusBar.AddField(pos);
2542 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2543 statusBar.AddField(caps);
2545 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2546 statusBar.AddField(ovr);
2548 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2549 statusBar.AddField(num);
2551 //statusBar.text = "Ready";
2553 if(projectView && projectView.project)
2555 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2559 sprintf(name, $"Compile %s", node.name);
2560 projectCompileItem =
2562 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2564 bool NotifySelect(MenuItem selection, Modifiers mods)
2568 bool result = false;
2569 ProjectNode node = null;
2570 for(p : ide.workspace.projects)
2572 node = projectView.GetNodeFromWindow(activeClient, p);
2573 //if(node && projectView.Compile(node.project, node, mods.ctrl && mods.shift))
2576 List<ProjectNode> nodes { };
2578 projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, normal);
2586 ide.outputView.buildBox.Logf($"File %s is excluded from current build configuration.\n", node.name);
2591 projectMenu.AddDynamic(projectCompileItem, ide, false);
2597 caps = ovr = num = null;
2602 bool OnClose(bool parentClosing)
2604 //return !projectView.buildInProgress;
2605 if(projectView && projectView.buildInProgress)
2607 if(DontTerminateDebugSession($"Close IDE"))
2609 if(findInFilesDialog)
2610 findInFilesDialog.SearchStop();
2613 workspace.timer.Stop();
2616 ideMainFrame.Destroy(0);
2623 bool passThrough = false;
2624 bool debugStart = false;
2625 DynamicString passArgs { };
2626 for(c = 1; c<app.argc; c++)
2628 if(!strcmp(app.argv[c], "-debug-start"))
2630 else if(!passThrough && !strcmp(app.argv[c], "-@"))
2632 else if(passThrough)
2634 passArgs.concat(" ");
2635 passArgs.concat(app.argv[c]);
2639 char fullPath[MAX_LOCATION];
2640 char parentPath[MAX_LOCATION];
2641 char ext[MAX_EXTENSION];
2643 FileAttribs dirAttribs;
2644 GetWorkingDir(fullPath, MAX_LOCATION);
2645 PathCat(fullPath, app.argv[c]);
2646 StripLastDirectory(fullPath, parentPath);
2647 GetExtension(app.argv[c], ext);
2648 isProject = !strcmpi(ext, "epj");
2650 if(isProject && c > (debugStart ? 2 : 1)) continue;
2652 // Create directory for projects (only)
2653 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
2655 if(isProject && !FileExists(fullPath))
2657 // The NewProject will handle directory creation
2658 /*if(!dirAttribs.isDirectory)
2660 MakeDir(parentPath);
2661 dirAttribs = FileExists(parentPath);
2663 if(dirAttribs.isDirectory)*/
2665 char name[MAX_LOCATION];
2666 NewProjectDialog newProjectDialog;
2670 projectView.visible = false;
2671 if(!projectView.Destroy(0))
2675 newProjectDialog = { master = this };
2677 strcpy(name, app.argv[c]);
2678 StripExtension(name);
2679 GetLastDirectory(name, name);
2680 newProjectDialog.projectName.contents = name;
2681 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
2682 newProjectDialog.locationEditBox.path = parentPath;
2683 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
2685 newProjectDialog.Modal();
2688 ideSettings.AddRecentProject(projectView.fileName);
2689 ide.UpdateRecentMenus();
2690 settingsContainer.Save();
2693 // Open only one project
2697 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2699 else if(strstr(fullPath, "http://") == fullPath)
2700 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2703 if(passThrough && projectView && projectView.project && workspace)
2704 workspace.commandLineArgs = passArgs;
2707 ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock
2709 UpdateToolBarActiveConfigs(false);
2710 UpdateToolBarActiveCompilers();
2716 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2719 projectView.visible = false;
2720 projectView.Destroy(0);
2723 #ifdef GDB_DEBUG_GUI
2724 gdbDialog.Destroy(0);
2729 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2733 char * oldPaths[128];
2734 String oldList = new char[maxPathLen];
2735 Array<String> newExePaths { };
2736 //Map<String, bool> exePathExists { };
2738 #if defined(__unix__) || defined(__APPLE__)
2739 Array<String> newLibPaths { };
2740 Map<String, bool> libPathExists { };
2745 for(prj : workspace.projects)
2747 DirExpression targetDirExp;
2749 // SKIP FIRST PROJECT...
2750 if(prj == workspace.projects.firstIterator.data) continue;
2752 // NOTE: Right now the additional project config dir will be
2753 // obtained when the debugger is started, so toggling it
2754 // while building will change which library gets used.
2755 // To go with the initial state, e.g. when F5 was pressed,
2756 // we nould need to keep a list of all project's active
2757 // config upon startup.
2758 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2760 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2764 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2765 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2769 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2770 if(cfg.targetType == sharedLibrary && cfg.debug)
2774 if(targetDirExp.dir)
2776 char buffer[MAX_LOCATION];
2777 #if defined(__WIN32__)
2778 Array<String> paths = newExePaths;
2780 Array<String> paths = newLibPaths;
2782 GetSystemPathBuffer(buffer, prj.topNode.path);
2783 PathCat(buffer, targetDirExp.dir);
2786 if(!fstrcmp(p, buffer))
2793 paths.Add(CopyString(buffer));
2795 delete targetDirExp;
2799 for(item : compiler.executableDirs)
2802 for(p : newExePaths)
2804 if(!fstrcmp(p, item))
2811 newExePaths.Add(CopySystemPath(item));
2814 GetEnvironment("PATH", oldList, maxPathLen);
2816 printf("Old value of PATH: %s\n", oldList);
2818 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2819 for(c = 0; c < count; c++)
2822 for(p : newExePaths)
2824 if(!fstrcmp(p, oldPaths[c]))
2831 newExePaths.Add(CopySystemPath(oldPaths[c]));
2835 for(path : newExePaths)
2836 len += strlen(path) + 1;
2837 newList = new char[len + 1];
2839 for(path : newExePaths)
2841 strcat(newList, path);
2842 strcat(newList, pathListSep);
2844 newList[len - 1] = '\0';
2845 SetEnvironment("PATH", newList);
2847 printf("New value of PATH: %s\n", newList);
2854 #if defined(__unix__) || defined(__APPLE__)
2856 for(item : compiler.libraryDirs)
2858 if(!libPathExists[item]) // fstrcmp should be used
2860 newLibPaths.Add(item);
2861 libPathExists[item] = true;
2865 #if defined(__APPLE__)
2866 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2868 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2871 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2873 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2874 for(c = 0; c < count; c++)
2876 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2878 newLibPaths.Add(oldPaths[c]);
2879 libPathExists[oldPaths[c]] = true;
2884 for(path : newLibPaths)
2885 len += strlen(path) + 1;
2886 newList = new char[len + 1];
2888 for(path : newLibPaths)
2890 strcat(newList, path);
2891 strcat(newList, pathListSep);
2893 newList[len - 1] = '\0';
2894 #if defined(__APPLE__)
2895 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2897 SetEnvironment("LD_LIBRARY_PATH", newList);
2900 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2905 delete libPathExists;
2908 if(compiler.distccEnabled && compiler.distccHosts)
2909 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2914 void DestroyTemporaryProjectDir()
2916 if(tmpPrjDir && tmpPrjDir[0])
2918 if(FileExists(tmpPrjDir).isDirectory)
2919 DestroyDir(tmpPrjDir);
2920 property::tmpPrjDir = null;
2926 // Graphics Driver Menu
2930 app.currentSkin.selectionColor = selectionColor;
2931 app.currentSkin.selectionText = selectionText;
2935 driverItems = new MenuItem[app.numDrivers];
2936 for(c = 0; c < app.numDrivers; c++)
2938 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2939 driverItems[c].id = c;
2940 driverItems[c].isRadio = true;
2943 driverItems = new MenuItem[2];
2944 #if defined(__unix__)
2945 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2946 driverItems[0].id = 0;
2947 driverItems[0].isRadio = true;
2949 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2950 driverItems[0].id = 0;
2951 driverItems[0].isRadio = true;
2953 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2954 driverItems[1].id = 1;
2955 driverItems[1].isRadio = true;
2957 /* skinItems = new MenuItem[app.numSkins];
2958 for(c = 0; c < app.numSkins; c++)
2960 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2961 skinItems[c].id = c;
2962 skinItems[c].isRadio = true;
2965 ideFileDialog.master = this;
2966 ideProjectFileDialog.master = this;
2968 //SetDriverAndSkin();
2972 void UpdateRecentMenus()
2975 Menu fileMenu = menu.FindMenu($"File");
2976 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2977 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2978 char itemName[MAX_LOCATION + 4];
2981 recentFiles.Clear();
2984 for(recent : ideSettings.recentFiles)
2986 sprintf(itemName, "%d %s", 1 + c, recent);
2987 MakeSystemPath(itemName);
2988 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2992 recentProjects.Clear();
2994 for(recent : ideSettings.recentProjects)
2996 sprintf(itemName, "%d %s", 1 + c, recent);
2997 MakeSystemPath(itemName);
2998 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
3011 void DestroyDir(char * path)
3013 RecursiveDeleteFolderFSI fsi { };
3018 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
3020 bool preserveRootFolder;
3022 void OutFolder(char * folderPath, bool isRoot)
3024 if(!(preserveRootFolder && isRoot))
3025 RemoveDir(folderPath);
3028 bool OnFile(char * filePath)
3030 DeleteFile(filePath);
3035 class IDEApp : GuiApplication
3037 //driver = "Win32Console";
3038 // driver = "OpenGL";
3043 SetLoggingMode(stdOut, null);
3044 //SetLoggingMode(debug, null);
3046 settingsContainer.Load();
3047 #if defined(__unix__) || defined(__APPLE__)
3048 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
3050 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
3052 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
3056 desktop.text = titleECEREIDE;
3059 for(c = 1; c<app.argc; c++)
3061 char fullPath[MAX_LOCATION];
3062 GetWorkingDir(fullPath, MAX_LOCATION);
3063 PathCat(fullPath, app.argv[c]);
3064 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
3071 IDEMainFrame ideMainFrame { };
3073 define app = ((IDEApp)__thisModule);
3075 define titleECEREIDE = $"ECERE IDE (Debug)";
3077 define titleECEREIDE = $"ECERE IDE";