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(true);
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; };
249 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
250 ToolButton buttonInstall { this, toolTip = $"Install", menuItemPtr = IDEItem(projectInstallItem), disabled = true; };
253 ToolSeparator separator4 { this };
257 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
259 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
261 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
263 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
265 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
267 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
269 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
271 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
273 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
275 ToolSeparator separator5 { this };
277 Window spacer5 { this, size = { 4 } };
281 this, toolTip = $"Active Configuration(s)", size = { 160 }, disabled = true;
282 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
285 ide.workspace.SelectActiveConfig(row.string);
290 Window spacer6 { this, size = { 4 } };
292 DropBox activeCompiler
294 this, toolTip = $"Active Compiler", size = { 160 }, disabled = true;
295 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
297 if(ide.workspace && ide.projectView && row && strcmp(row.string, ide.workspace.compiler))
299 bool silent = ide.projectView.buildInProgress == none ? false : true;
300 CompilerConfig compiler = ideSettings.GetCompilerConfig(row.string);
301 ide.workspace.compiler = row.string;
302 ide.projectView.ShowOutputBuildLog(!silent);
304 ide.projectView.DisplayCompiler(compiler, false);
305 for(prj : ide.workspace.projects)
306 ide.projectView.ProjectPrepareCompiler(prj, compiler, silent);
308 ide.workspace.Save();
314 DropBox activeBitDepth
316 this, toolTip = $"Active Bit Length", size = { 60 }, disabled = true;
317 bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods)
319 if(ide.workspace && ide.projectView && row)
321 bool silent = ide.projectView.buildInProgress == none ? false : true;
322 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
323 ide.workspace.bitDepth = (int)row.tag;
324 ide.projectView.ShowOutputBuildLog(!silent);
326 ide.projectView.DisplayCompiler(compiler, false);
327 for(prj : ide.workspace.projects)
328 ide.projectView.ProjectPrepareCompiler(prj, compiler, silent);
330 ide.workspace.Save();
336 Window spacer7 { this, size = { 4 } };
341 row = activeBitDepth.AddString("Auto");
343 activeBitDepth.AddString("32 bit").tag = 32;
344 activeBitDepth.AddString("64 bit").tag = 64;
345 activeBitDepth.currentRow = row;
350 class IDEMainFrame : Window
352 background = formColor;
353 borderStyle = sizable;
357 minClientSize = { 600, 300 };
359 icon = { ":icon.png" };
360 text = titleECEREIDE;
364 anchor = { top = 0, right = 0, bottom = 0 };
367 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
374 isActiveClient = true;
376 direction = vertical;
377 background = formColor;
378 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
386 ((IDEWorkSpace)master).toolBar = null;
389 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
392 define ide = ideMainFrame.ideWorkSpace;
394 class IDEWorkSpace : Window
396 background = Color { 85, 85, 85 };
399 hasVertScroll = true;
400 hasHorzScroll = true;
402 isActiveClient = true;
403 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
407 MenuItem * driverItems, * skinItems, * languageItems;
408 StatusField pos { width = 150 };
409 StatusField ovr, caps, num;
412 BitmapResource back { ":ecereBack.jpg", window = this };
413 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
414 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
415 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
416 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
417 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
418 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
419 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
420 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
421 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
422 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
424 Debugger debugger { };
426 ProjectView projectView;
428 OutputView outputView
432 void OnGotoError(char * line, bool noParsing)
434 ide.GoToError(line, noParsing);
437 void OnCodeLocationParseAndGoTo(char * line)
439 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
442 bool OnKeyDown(Key key, unichar ch)
447 if(activeBox != findBox || !ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
448 ide.ShowCodeEditor();
452 OutputView::OnKeyDown(key, ch);
459 bool OnClose(bool parentClosing)
463 ide.RepositionWindows(false);
464 return parentClosing;
468 CallStackView callStackView
470 parent = this, font = { panelFont.faceName, panelFont.size };
472 void OnSelectFrame(int frameIndex)
474 ide.debugger.GoToStackFrameLine(frameIndex, true, true);
476 ide.debugger.SelectFrame(frameIndex);
479 void OnToggleBreakpoint()
481 Debugger debugger = ide.debugger;
482 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
484 int line = debugger.activeFrame.line;
485 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line);
488 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
489 if(codeEditor) { codeEditor.Update(null); Activate(); }
494 bool OnKeyDown(Key key, unichar ch)
498 case escape: ide.ShowCodeEditor(); break;
503 bool OnClose(bool parentClosing)
507 ide.RepositionWindows(false);
508 return parentClosing;
511 void OnRedraw(Surface surface)
513 Debugger debugger = ide.debugger;
514 Frame activeFrame = debugger.activeFrame;
518 int lineCursor, lineTopFrame, activeThread, hitThread;
519 int lineH, scrollY, boxH;
521 Breakpoint bp = null;
524 scrollY = editBox.scroll.y;
525 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
526 activeThread = debugger.activeThread;
527 hitThread = debugger.hitThread;
528 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
530 // TODO: improve bp drawing... it should be visible even if it's not on the activeFrame
531 if(activeFrame.absoluteFile)
533 for(i : ide.workspace.breakpoints; i.type == user)
535 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
536 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
537 activeFrame.line == i.line)
545 DrawLineMarginIcon(surface,
546 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
547 lineCursor /*1*/, lineH, scrollY, boxH);
549 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
550 DrawLineMarginIcon(surface,
551 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
552 1, lineH, scrollY, boxH);
554 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
555 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
556 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
558 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
559 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
561 if(editBox.horzScroll && editBox.horzScroll.visible)
563 surface.SetBackground(control);
564 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
569 WatchesView watchesView { parent = this };
570 ThreadsView threadsView
572 parent = this, font = { panelFont.faceName, panelFont.size };
574 bool OnKeyDown(Key key, unichar ch)
578 case escape: ide.ShowCodeEditor(); break;
583 bool OnClose(bool parentClosing)
587 ide.RepositionWindows(false);
588 return parentClosing;
591 void OnSelectThread(int threadId)
594 ide.debugger.SelectThread(threadId);
597 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
600 Debugger debugger = ide.debugger;
601 *activeThread = debugger.activeThread;
602 *hitThread = debugger.hitThread;
603 *signalThread = debugger.signalThread;
608 BreakpointsView breakpointsView { parent = this };
610 ToolBox toolBox { parent = this, visible = false };
611 Sheet sheet { parent = this, visible = false };
614 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
616 Menu fileMenu { menu, $"File", f, hasMargin = true };
619 fileMenu, $"New", n, ctrlN;
620 bitmap = { ":actions/docNew.png" };
621 bool NotifySelect(MenuItem selection, Modifiers mods)
623 Window currentDoc = activeClient;
624 bool maximizeDoc = ((currentDoc && currentDoc.state == maximized) || (!currentDoc && !projectView));
625 Window document = (Window)NewCodeEditor(this, maximizeDoc ? maximized : normal, false);
626 RepositionWindows(false);
627 document.NotifySaved = DocumentSaved;
631 MenuItem fileOpenItem
633 fileMenu, $"Open...", o, ctrlO;
634 bitmap = { ":actions/docOpen.png" };
635 bool NotifySelect(MenuItem selection, Modifiers mods)
637 if(!projectView && ideSettings.ideFileDialogLocation)
638 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
641 if(ideFileDialog.Modal() == ok)
643 bool gotWhatWeWant = false;
645 int numSelections = ideFileDialog.numSelections;
646 char ** multiFilePaths = ideFileDialog.multiFilePaths;
648 for(c = 0; c < numSelections; c++)
650 if(OpenFile(multiFilePaths[c], false, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift))
651 gotWhatWeWant = true;
654 MessageBox { type = yesNo, master = this, text = $"Error opening file",
655 contents = $"Open a different file?" }.Modal() == no)
657 if(!projectView && gotWhatWeWant)
658 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
659 ide.RepositionWindows(false);
669 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
670 MenuDivider { fileMenu };
671 MenuItem fileSaveItem
673 fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" };
675 // For the toolbar button; clients can still override that for the menu item
676 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
678 Window w = activeClient;
680 w.MenuFileSave(null, 0);
684 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
685 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
686 MenuDivider { fileMenu };
689 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
690 bool NotifySelect(MenuItem selection, Modifiers mods)
692 findInFilesDialog.replaceMode = false;
693 findInFilesDialog.Show();
697 MenuItem replaceInFiles
699 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
700 bool NotifySelect(MenuItem selection, Modifiers mods)
702 findInFilesDialog.replaceMode = true;
703 findInFilesDialog.Show();
707 MenuDivider { fileMenu };
708 MenuItem globalSettingsItem
710 fileMenu, $"Global Settings...", g;
711 bool NotifySelect(MenuItem selection, Modifiers mods)
713 globalSettingsDialog.master = this;
714 if(ide.workspace && ide.workspace.compiler)
715 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
716 else if(ideSettings.defaultCompiler)
717 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
718 globalSettingsDialog.Modal();
722 MenuDivider { fileMenu };
723 Menu recentFiles { fileMenu, $"Recent Files", r };
724 Menu recentProjects { fileMenu, $"Recent Projects", p };
725 MenuDivider { fileMenu };
728 fileMenu, $"Exit", x, altF4;
730 bool NotifySelect(MenuItem selection, Modifiers mods)
732 ideMainFrame.Destroy(0);
737 bool FileRecentFile(MenuItem selection, Modifiers mods)
740 for(file : ideSettings.recentFiles)
742 if(id == selection.id)
745 char extension[MAX_EXTENSION] = "";
746 GetExtension(file, extension);
747 isProjectFile = (!strcmpi(extension, "epj") || !strcmpi(extension, "ews"));
750 char * command = PrintString("ide ", isProjectFile ? "-t " : "", file);
756 OpenFile(file, false, true, isProjectFile ? "txt" : null, no, normal, mods.ctrl && mods.shift);
757 ide.RepositionWindows(false);
766 bool FileRecentProject(MenuItem selection, Modifiers mods)
769 for(file : ideSettings.recentProjects)
771 if(id == selection.id)
775 char * command = PrintString("ide ", file);
780 OpenFile(file, false, true, null, no, normal, mods.ctrl && mods.shift);
788 MenuPlacement editMenu { menu, $"Edit", e };
790 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
791 MenuItem projectNewItem
793 projectMenu, $"New...", n, Key { n, true, true };
794 bitmap = { ":actions/projNew.png" };
795 bool NotifySelect(MenuItem selection, Modifiers mods)
797 if(!DontTerminateDebugSession($"New Project"))
800 NewProjectDialog newProjectDialog { master = this };
801 incref newProjectDialog;
802 result = newProjectDialog.Modal();
807 newProjectDialog.CreateNewProject();
810 ideSettings.AddRecentProject(projectView.fileName);
811 ide.UpdateRecentMenus();
812 settingsContainer.Save();
816 delete newProjectDialog;
821 MenuItem projectOpenItem
823 projectMenu, $"Open...", o, Key { o, true, true };
824 bitmap = { ":actions/projOpen.png" };
825 bool NotifySelect(MenuItem selection, Modifiers mods)
827 if(ideSettings.ideProjectFileDialogLocation)
828 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
830 ideProjectFileDialog.text = openProjectFileDialogTitle;
831 if(ideProjectFileDialog.Modal() == ok)
833 OpenFile(ideProjectFileDialog.filePath, false, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal, mods.ctrl && mods.shift);
834 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
839 MenuItem projectQuickItem
841 projectMenu, $"Quick...", q, f7, disabled = true;
842 bool NotifySelect(MenuItem selection, Modifiers mods)
845 QuickProjectDialog { this }.Modal();
849 MenuItem projectAddItem
851 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
852 bitmap = { ":actions/projAdd.png" };
854 bool NotifySelect(MenuItem selection, Modifiers mods)
856 if(ideSettings.ideProjectFileDialogLocation)
857 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
859 ideProjectFileDialog.text = addProjectFileDialogTitle;
862 if(ideProjectFileDialog.Modal() == ok)
864 if(OpenFile(ideProjectFileDialog.filePath, false, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add, mods.ctrl && mods.shift))
866 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
867 contents = $"Add a different project?" }.Modal() == no)
878 MenuItem projectCloseItem
880 projectMenu, $"Close", c, disabled = true;
881 bool NotifySelect(MenuItem selection, Modifiers mods)
885 if(!ide.DontTerminateDebugSession($"Project Close"))
891 MenuDivider { projectMenu };
892 MenuItem projectSettingsItem
894 projectMenu, $"Settings...", s, altF7, disabled = true;
895 bool NotifySelect(MenuItem selection, Modifiers mods)
897 projectView.MenuSettings(projectView.active ? selection : null, mods);
901 MenuDivider { projectMenu };
902 MenuItem projectBrowseFolderItem
904 projectMenu, $"Browse Project Folder", p, disabled = true;
905 bool NotifySelect(MenuItem selection, Modifiers mods)
908 projectView.MenuBrowseFolder(null, mods);
912 MenuDivider { projectMenu };
913 MenuItem projectRunItem
915 projectMenu, $"Run", r, ctrlF5, disabled = true;
916 bitmap = { ":actions/run.png" };
917 bool NotifySelect(MenuItem selection, Modifiers mods)
920 projectView.Run(null, mods);
924 MenuItem projectBuildItem
926 projectMenu, $"Build", b, f7, disabled = true;
927 bitmap = { ":actions/build.png" };
928 bool NotifySelect(MenuItem selection, Modifiers mods)
932 if(projectView.buildInProgress == none)
933 projectView.ProjectBuild(projectView.active ? selection : null, mods);
935 projectView.stopBuild = true;
940 MenuItem projectLinkItem
942 projectMenu, $"Relink", l, disabled = true;
943 bitmap = { ":actions/relink.png" };
944 bool NotifySelect(MenuItem selection, Modifiers mods)
947 projectView.ProjectLink(projectView.active ? selection : null, mods);
951 MenuItem projectRebuildItem
953 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
954 bitmap = { ":actions/rebuild.png" };
955 bool NotifySelect(MenuItem selection, Modifiers mods)
958 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
962 MenuItem projectCleanTargetItem
964 projectMenu, $"Clean Target", g, disabled = true;
965 bitmap = { ":actions/clean.png" };
966 bool NotifySelect(MenuItem selection, Modifiers mods)
971 projectView.ProjectCleanTarget(projectView.active ? selection : null, mods);
976 MenuItem projectCleanItem
978 projectMenu, $"Clean", e, disabled = true;
979 bitmap = { ":actions/clean.png" };
980 bool NotifySelect(MenuItem selection, Modifiers mods)
985 projectView.ProjectClean(projectView.active ? selection : null, mods);
990 MenuItem projectRealCleanItem
992 projectMenu, $"Real Clean", disabled = true;
993 bitmap = { ":actions/clean.png" };
994 bool NotifySelect(MenuItem selection, Modifiers mods)
999 projectView.ProjectRealClean(projectView.active ? selection : null, mods);
1004 MenuItem projectRegenerateItem
1006 projectMenu, $"Regenerate Makefile", m, disabled = true;
1007 bitmap = { ":actions/regMakefile.png" };
1008 bool NotifySelect(MenuItem selection, Modifiers mods)
1011 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
1015 MenuItem projectInstallItem
1017 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
1018 projectMenu, $"Install", t, disabled = true;
1020 bitmap = { ":status/software-update-available.png" };
1021 bool NotifySelect(MenuItem selection, Modifiers mods)
1024 projectView.ProjectInstall(projectView.active ? selection : null, mods);
1028 MenuItem projectCompileItem;
1029 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
1030 MenuItem debugStartResumeItem
1032 debugMenu, $"Start", s, f5, disabled = true;
1033 bitmap = { ":actions/debug.png" };
1034 NotifySelect = MenuDebugStart;
1036 bool MenuDebugStart(MenuItem selection, Modifiers mods)
1040 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
1041 if(!projectView.DebugStart())
1042 debugStartResumeItem.disabled = false; // same exception
1046 bool MenuDebugResume(MenuItem selection, Modifiers mods)
1049 projectView.DebugResume();
1052 MenuItem debugRestartItem
1054 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
1055 bitmap = { ":actions/restart.png" };
1056 bool NotifySelect(MenuItem selection, Modifiers mods)
1059 projectView.DebugRestart();
1063 MenuItem debugBreakItem
1065 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
1066 bitmap = { ":actions/pause.png" };
1067 bool NotifySelect(MenuItem selection, Modifiers mods)
1069 if(projectView && projectView.buildInProgress != none)
1072 projectView.DebugBreak();
1076 MenuItem debugStopItem
1078 debugMenu, $"Stop", p, shiftF5, disabled = true;
1079 bitmap = { ":actions/stopDebug.png" };
1080 bool NotifySelect(MenuItem selection, Modifiers mods)
1083 projectView.DebugStop();
1088 MenuDivider { debugMenu };
1089 MenuItem debugUseValgrindItem
1091 debugMenu, $"Use Valgrind", d, disabled = true, checkable = true;
1092 bool NotifySelect(MenuItem selection, Modifiers mods)
1096 ide.workspace.useValgrind = selection.checked;
1097 ide.workspace.Save();
1099 ide.AdjustValgrindMenus();
1103 Menu debugValgrindLeakCheckItem { debugMenu, $"Valgrind Leak Check", h };
1104 MenuItem debugValgrindNoLeakCheckItem { debugValgrindLeakCheckItem, $"No" , f, id = ValgrindLeakCheck::no , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
1105 MenuItem debugValgrindSummaryLeakCheckItem { debugValgrindLeakCheckItem, $"Summary", f, id = ValgrindLeakCheck::summary, checkable = true, disabled = true; NotifySelect = ValgrindLCSelect, checked = true; }
1106 MenuItem debugValgrindYesLeakCheckItem { debugValgrindLeakCheckItem, $"Yes" , f, id = ValgrindLeakCheck::yes , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
1107 MenuItem debugValgrindFullLeakCheckItem { debugValgrindLeakCheckItem, $"Full" , f, id = ValgrindLeakCheck::full , checkable = true, disabled = true; NotifySelect = ValgrindLCSelect; }
1108 bool ValgrindLCSelect(MenuItem selection, Modifiers mods)
1112 if(selection.checked)
1114 ValgrindLeakCheck vgLeakCheck = (ValgrindLeakCheck)selection.id;
1116 debugValgrindNoLeakCheckItem.checked = debugValgrindNoLeakCheckItem.id == vgLeakCheck;
1117 debugValgrindSummaryLeakCheckItem.checked = debugValgrindSummaryLeakCheckItem.id == vgLeakCheck;
1118 debugValgrindYesLeakCheckItem.checked = debugValgrindYesLeakCheckItem.id == vgLeakCheck;
1119 debugValgrindFullLeakCheckItem.checked = debugValgrindFullLeakCheckItem.id == vgLeakCheck;
1121 ide.workspace.vgLeakCheck = vgLeakCheck;
1122 ide.workspace.Save();
1125 selection.checked = true;
1129 Menu debugValgrindRedzoneSizeItem { debugMenu, $"Valgrind Redzone Size", z };
1130 MenuItem debugValgrindRSDefaultItem { debugValgrindRedzoneSizeItem, $"Default", f, id = -1, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect, checked = true; }
1131 MenuItem debugValgrindRS0Item { debugValgrindRedzoneSizeItem, "0" , f, id = 0, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1132 MenuItem debugValgrindRS16Item { debugValgrindRedzoneSizeItem, "16" , f, id = 16, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1133 MenuItem debugValgrindRS32Item { debugValgrindRedzoneSizeItem, "32" , f, id = 32, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1134 MenuItem debugValgrindRS64Item { debugValgrindRedzoneSizeItem, "64" , f, id = 64, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1135 MenuItem debugValgrindRS128Item { debugValgrindRedzoneSizeItem, "128" , f, id = 128, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1136 MenuItem debugValgrindRS256Item { debugValgrindRedzoneSizeItem, "256" , f, id = 256, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1137 MenuItem debugValgrindRS512Item { debugValgrindRedzoneSizeItem, "512" , f, id = 512, checkable = true, disabled = true; NotifySelect = ValgrindRSSelect; }
1138 bool ValgrindRSSelect(MenuItem selection, Modifiers mods)
1142 if(selection.checked)
1144 int vgRedzoneSize = (int)selection.id;
1146 debugValgrindRSDefaultItem.checked = debugValgrindRSDefaultItem.id == vgRedzoneSize;
1147 debugValgrindRS0Item.checked = debugValgrindRS0Item.id == vgRedzoneSize;
1148 debugValgrindRS16Item.checked = debugValgrindRS16Item.id == vgRedzoneSize;
1149 debugValgrindRS32Item.checked = debugValgrindRS32Item.id == vgRedzoneSize;
1150 debugValgrindRS64Item.checked = debugValgrindRS64Item.id == vgRedzoneSize;
1151 debugValgrindRS128Item.checked = debugValgrindRS128Item.id == vgRedzoneSize;
1152 debugValgrindRS256Item.checked = debugValgrindRS256Item.id == vgRedzoneSize;
1153 debugValgrindRS512Item.checked = debugValgrindRS512Item.id == vgRedzoneSize;
1155 ide.workspace.vgRedzoneSize = vgRedzoneSize;
1156 ide.workspace.Save();
1159 selection.checked = true;
1163 MenuItem debugValgrindTrackOriginsItem
1165 debugMenu, $"Valgrind Track Origins", k, checkable = true, disabled = true;
1166 bool NotifySelect(MenuItem selection, Modifiers mods)
1170 ide.workspace.vgTrackOrigins = selection.checked;
1171 ide.workspace.Save();
1177 MenuDivider { debugMenu };
1178 MenuItem debugStepIntoItem
1180 debugMenu, $"Step Into", i, f11, disabled = true;
1181 bitmap = { ":actions/stepInto.png" };
1182 bool NotifySelect(MenuItem selection, Modifiers mods)
1184 if(projectView) projectView.DebugStepInto();
1188 MenuItem debugStepOverItem
1190 debugMenu, $"Step Over", v, f10, disabled = true;
1191 bitmap = { ":actions/stepOver.png" };
1192 bool NotifySelect(MenuItem selection, Modifiers mods)
1194 if(projectView) projectView.DebugStepOver(false);
1198 MenuItem debugSkipStepOverItem
1200 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1201 bitmap = { ":actions/stepOverSkipBreak.png" };
1202 bool NotifySelect(MenuItem selection, Modifiers mods)
1204 if(projectView) projectView.DebugStepOver(true);
1208 MenuItem debugStepOutItem
1210 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1211 bitmap = { ":actions/stepOut.png" };
1212 bool NotifySelect(MenuItem selection, Modifiers mods)
1214 if(projectView) projectView.DebugStepOut(false);
1218 MenuItem debugSkipStepOutItem
1220 debugMenu, $"Step Out Skipping Breakpoints", n, Key { f11, ctrl = true, shift = true }, disabled = true;
1221 bitmap = { ":actions/skipBreaks.png" };
1222 bool NotifySelect(MenuItem selection, Modifiers mods)
1224 if(projectView) projectView.DebugStepOut(true);
1229 MenuItem debugStepUntilItem
1231 debugMenu, $"Step Over Until Next Line", x, disabled = true;
1232 bool NotifySelect(MenuItem selection, Modifiers mods)
1234 if(projectView) projectView.DebugStepUntil(false);
1238 MenuItem debugSkipStepUntilItem
1240 debugMenu, $"Step Over Until Next Line Skipping Breakpoints", e, Key { f10, shift = true, alt = true }, disabled = true;
1241 bool NotifySelect(MenuItem selection, Modifiers mods)
1243 if(projectView) projectView.DebugStepUntil(true);
1248 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1249 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1250 MenuPlacement debugRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level", l };
1251 MenuPlacement debugSkipRunToCursorAtSameLevelItem { debugMenu, $"Run To Cursor At Same Level Skipping Breakpoints", g };
1253 MenuPlacement debugBpRunToCursorItem { debugMenu, $"BP Run To Cursor" };
1254 MenuPlacement debugBpSkipRunToCursorItem { debugMenu, $"BP Run To Cursor Skipping Breakpoints" };
1255 MenuPlacement debugBpRunToCursorAtSameLevelItem { debugMenu, $"BP Run To Cursor At Same Level" };
1256 MenuPlacement debugBpSkipRunToCursorAtSameLevelItem { debugMenu, $"BP Run To Cursor At Same Level Skipping Breakpoints" };
1258 //MenuDivider { debugMenu };
1259 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1260 MenuPlacement imageMenu { menu, $"Image", i };
1261 Menu viewMenu { menu, $"View", v };
1262 MenuItem viewProjectItem
1264 viewMenu, $"Project View", j, alt0, disabled = true;
1265 bool NotifySelect(MenuItem selection, Modifiers mods)
1269 projectView.visible = true;
1270 projectView.Activate();
1275 MenuPlacement { viewMenu, $"View Designer" };
1276 MenuPlacement { viewMenu, $"View Code" };
1277 MenuPlacement { viewMenu, $"View Properties" };
1278 MenuPlacement { viewMenu, $"View Methods" };
1279 MenuItem viewDesignerItem
1281 viewMenu, $"View Designer", d, f8;
1282 bool NotifySelect(MenuItem selection, Modifiers mods)
1284 Window client = activeClient;
1285 Class dataType = client._class;
1286 if(!strcmp(dataType.name, "Designer"))
1288 client.visible = true;
1292 ((CodeEditor)client).ViewDesigner();
1296 MenuItem viewCodeItem
1298 viewMenu, $"View Code", c, f8;
1299 bool NotifySelect(MenuItem selection, Modifiers mods)
1301 Window client = activeClient;
1302 Class dataType = client._class;
1303 if(!strcmp(dataType.name, "Designer"))
1304 client = ((Designer)client).codeEditor;
1307 // Do this after so the caret isn't moved yet...
1308 client.visible = true;
1312 MenuItem viewPropertiesItem
1314 viewMenu, $"View Properties", p, f4;
1315 bool NotifySelect(MenuItem selection, Modifiers mods)
1317 sheet.visible = true;
1318 sheet.sheetSelected = properties;
1323 MenuItem viewMethodsItem
1325 viewMenu, $"View Methods", m, f4;
1326 bool NotifySelect(MenuItem selection, Modifiers mods)
1328 sheet.visible = true;
1329 sheet.sheetSelected = methods;
1334 MenuItem viewToolBoxItem
1336 viewMenu, $"View Toolbox", x, f12;
1337 bool NotifySelect(MenuItem selection, Modifiers mods)
1339 toolBox.visible = true;
1344 MenuItem viewOutputItem
1346 viewMenu, $"Output", o, alt2;
1347 bool NotifySelect(MenuItem selection, Modifiers mods)
1353 MenuItem viewWatchesItem
1355 viewMenu, $"Watches", w, alt3;
1356 bool NotifySelect(MenuItem selection, Modifiers mods)
1362 MenuItem viewThreadsItem
1364 viewMenu, $"Threads", t, alt4;
1365 bool NotifySelect(MenuItem selection, Modifiers mods)
1371 MenuItem viewBreakpointsItem
1373 viewMenu, $"Breakpoints", b, alt5;
1374 bool NotifySelect(MenuItem selection, Modifiers mods)
1376 breakpointsView.Show();
1380 MenuItem viewCallStackItem
1382 viewMenu, $"Call Stack", s, alt7;
1383 bool NotifySelect(MenuItem selection, Modifiers mods)
1385 callStackView.Show();
1389 MenuItem viewAllDebugViews
1391 viewMenu, $"All Debug Views", a, alt9;
1392 bool NotifySelect(MenuItem selection, Modifiers mods)
1397 callStackView.Show();
1398 breakpointsView.Show();
1402 #ifdef GDB_DEBUG_GUI
1403 MenuDivider { viewMenu };
1404 MenuItem viewGDBItem
1406 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1407 bool NotifySelect(MenuItem selection, Modifiers mods)
1414 MenuDivider { viewMenu };
1415 MenuItem viewColorPicker
1417 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1418 bool NotifySelect(MenuItem selection, Modifiers mods)
1420 ColorPicker colorPicker { master = this };
1421 colorPicker.Modal();
1425 MenuDivider { viewMenu };
1429 viewMenu, "Full Screen", f, checkable = true;
1431 bool NotifySelect(MenuItem selection, Modifiers mods)
1433 app.fullScreen ^= true;
1435 anchor = { 0, 0, 0, 0 };
1440 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1442 MenuDivider { viewMenu };
1444 Menu languageMenu { viewMenu, $"Language", l };
1446 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1447 Menu windowMenu { menu, $"Window", w };
1448 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1449 MenuDivider { windowMenu };
1450 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1451 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1452 MenuDivider { windowMenu };
1453 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1454 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1455 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1456 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1457 MenuDivider { windowMenu };
1458 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1459 Menu helpMenu { menu, $"Help", h };
1462 helpMenu, $"API Reference", r, f1;
1463 bool NotifySelect(MenuItem selection, Modifiers mods)
1467 char * p = new char[MAX_LOCATION];
1469 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
1470 PathCat(p, "documentor");
1471 #if defined(__WIN32__)
1472 ChangeExtension(p, "exe", p);
1474 if(!FileExists(p).isFile)
1475 strcpy(p, "documentor");
1477 documentor = DualPipeOpen({ input = true, output = true, showWindow = true }, p);
1482 Process_ShowWindows(documentor.GetProcessID());
1483 // documentor.Puts("Activate\n");
1488 MenuDivider { helpMenu };
1491 helpMenu, $"Ecere Tao of Programming [work in progress]", t;
1492 bool NotifySelect(MenuItem selection, Modifiers mods)
1494 FindAndShellOpenInstalledFile("doc", "Ecere Tao of Programming [work in progress].pdf");
1498 MenuDivider { helpMenu };
1501 helpMenu, $"Documentation Folder", d;
1502 bool NotifySelect(MenuItem selection, Modifiers mods)
1504 FindAndShellOpenInstalledFolder("doc");
1510 helpMenu, $"Samples Folder", s;
1511 bool NotifySelect(MenuItem selection, Modifiers mods)
1513 FindAndShellOpenInstalledFolder("samples");
1519 helpMenu, $"Extras Folder", x;
1520 bool NotifySelect(MenuItem selection, Modifiers mods)
1522 FindAndShellOpenInstalledFolder("extras");
1526 MenuDivider { helpMenu };
1529 helpMenu, $"Community Forums", f;
1530 bool NotifySelect(MenuItem selection, Modifiers mods)
1532 ShellOpen("http://ecere.com/forums");
1536 MenuDivider { helpMenu };
1539 helpMenu, $"About...", a;
1540 bool NotifySelect(MenuItem selection, Modifiers mods)
1542 AboutIDE { master = this }.Modal();
1547 property ToolBox toolBox
1549 get { return toolBox; }
1552 property Sheet sheet
1554 get { return sheet; }
1557 property Project project
1559 get { return projectView ? projectView.project : null; }
1562 property Workspace workspace
1564 get { return projectView ? projectView.workspace : null; }
1567 FindInFilesDialog findInFilesDialog
1570 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1576 #ifdef GDB_DEBUG_GUI
1579 master = this, parent = this;
1580 //anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1582 void OnCommand(char * string)
1585 ide.debugger.SendGDBCommand(string);
1590 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1592 //app.driver = app.drivers[selection.id];
1593 #if defined(__unix__) || defined(__APPLE__)
1594 app.driver = selection.id ? "OpenGL" : "X";
1596 app.driver = selection.id ? "OpenGL" : "GDI";
1598 delete ideSettings.displayDriver;
1599 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1601 settingsContainer.Save();
1602 //SetDriverAndSkin();
1606 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1608 app.skin = app.skins[selection.id];
1613 void SetDriverAndSkin()
1616 for(c = 0; c < app.numSkins; c++)
1617 if(!strcmp(app.skins[c], app.skin))
1619 skinItems[c].checked = true;
1622 for(c = 0; c < app.numDrivers; c++)
1623 if(!strcmp(app.drivers[c], app.driver))
1625 driverItems[c].checked = true;
1630 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1632 Project project = workspace.projects.firstIterator.data;
1633 projectView = ProjectView
1636 fileName = fileName;
1638 void NotifyDestroyed(Window window, DialogResult result)
1641 text = titleECEREIDE;
1646 projectView.Create();
1647 RepositionWindows(false);
1649 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1650 projectView.workspace = workspace;
1651 projectView.project = project;
1652 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1656 ide.breakpointsView.LoadFromWorkspace();
1657 ide.watchesView.LoadFromWorkspace();
1659 findInFilesDialog.projectNodeField.userData = projectView;
1662 char fileName[MAX_LOCATION];
1663 strcpy(fileName, project.topNode.path);
1664 PathCat(fileName, project.topNode.name);
1671 projectView.visible = false;
1672 if((!projectView || projectView.created == false || projectView.Destroy(0)) && MenuWindowCloseAll(null, 0))
1674 if(findInFilesDialog)
1676 char workingDir[MAX_LOCATION];
1677 GetWorkingDir(workingDir, MAX_LOCATION);
1678 findInFilesDialog.SearchStop();
1679 findInFilesDialog.currentDirectory = workingDir;
1681 sheet.visible = false;
1682 toolBox.visible = false;
1683 outputView.visible = false;
1684 ideMainFrame.text = titleECEREIDE;
1691 void RepositionWindows(bool expand)
1696 bool inDebugMode = debugger.isActive;
1697 bool callStackVisible = expand ? false : callStackView.visible;
1698 bool threadsVisible = expand ? false : threadsView.visible;
1699 bool watchesVisible = expand ? false : watchesView.visible;
1700 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1701 bool toolBoxVisible = toolBox.visible;
1702 bool outputVisible = expand ? false : outputView.visible;
1703 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1704 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1706 for(child = firstChild; child; child = child.next)
1708 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1709 child._class == class(Sheet) || child._class == class(ProjectView))
1711 Anchor anchor = child.anchor;
1712 anchor.top = topDistance;
1713 anchor.bottom = bottomDistance;
1714 if(child._class == class(CodeEditor) || child._class == class(Designer))
1716 anchor.left = (sheet.visible || (projectView && projectView.visible)) ? 300 : 0;
1717 anchor.right = toolBoxVisible ? 150 : 0;
1719 child.anchor = anchor;
1723 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1724 child._class == class(BreakpointsView))
1725 child.visible = false;
1728 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1733 bool ShowCodeEditor()
1736 activeClient.Activate();
1737 else if(projectView)
1739 projectView.visible = true;
1740 projectView.Activate();
1744 sheet.visible = true;
1750 void DocumentSaved(Window document, char * fileName)
1752 ideSettings.AddRecentFile(fileName);
1753 ide.UpdateRecentMenus();
1754 ide.AdjustFileMenus();
1755 settingsContainer.Save();
1758 bool Window::OnFileModified(FileChange fileChange, char * param)
1761 sprintf(temp, $"The document %s was modified by another application.\n"
1762 "Would you like to reload it and lose your changes?", this.fileName);
1763 if(MessageBox { type = yesNo, master = this/*.parent*/,
1764 text = $"Document has been modified", contents = temp }.Modal() == yes)
1766 bool noParsing = (this._class == class(CodeEditor) && ((CodeEditor)this).noParsing) ? true : false;
1767 char * fileName = CopyString(this.fileName);
1768 WindowState state = this.state;
1769 Anchor anchor = this.anchor;
1770 Size size = this.size;
1772 this.modifiedDocument = false;
1774 this = ide.OpenFile(fileName, false, true, null, no, normal, noParsing);
1777 this.anchor = anchor;
1779 this.SetState(state, true, 0);
1787 void UpdateMakefiles()
1791 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1792 for(prj : workspace.projects)
1793 projectView.ProjectUpdateMakefileForAllConfigs(prj);
1798 void UpdateCompilerConfigs(bool mute)
1800 UpdateToolBarActiveCompilers();
1803 bool silent = mute || (ide.projectView.buildInProgress == none ? false : true);
1804 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
1807 projectView.ShowOutputBuildLog(true);
1808 projectView.DisplayCompiler(compiler, false);
1810 for(prj : workspace.projects)
1811 projectView.ProjectPrepareCompiler(prj, compiler, silent);
1816 void UpdateToolBarActiveCompilers()
1818 toolBar.activeCompiler.Clear();
1819 for(compiler : ideSettings.compilerConfigs)
1821 DataRow row = toolBar.activeCompiler.AddString(compiler.name);
1822 if(workspace && workspace.compiler && !strcmp(compiler.name, workspace.compiler))
1823 toolBar.activeCompiler.currentRow = row;
1825 if(!toolBar.activeCompiler.currentRow && toolBar.activeCompiler.firstRow)
1826 toolBar.activeCompiler.SelectRow(toolBar.activeCompiler.firstRow);
1829 void UpdateToolBarActiveConfigs(bool selectionOnly)
1831 bool commonSelected = false;
1832 DataRow row = toolBar.activeConfig.currentRow;
1834 row = toolBar.activeConfig.FindRow(1);
1837 toolBar.activeConfig.Clear();
1838 row = toolBar.activeConfig.AddString($"(Mixed)");
1843 char * configName = null;
1846 Map<String, int> configs { }; // TOIMP: just need sort but using map until containers have sort
1847 for(prj : workspace.projects)
1849 for(cfg : prj.configurations)
1852 configs[cfg.name] = 1;
1857 toolBar.activeConfig.AddString(&name);
1861 if(projectView && projectView.project)
1863 for(prj : workspace.projects)
1865 if(prj.config && prj.config.name)
1867 configName = prj.config.name;
1873 commonSelected = true;
1874 for(prj : workspace.projects)
1876 if(prj.config && (!prj.config.name || strcmp(prj.config.name, configName)))
1878 commonSelected = false;
1886 commonSelected = false;
1887 for(row = toolBar.activeConfig.firstRow; row; row = row.next)
1889 if(!strcmp(row.string, configName))
1891 toolBar.activeConfig.currentRow = row;
1892 commonSelected = true;
1899 toolBar.activeConfig.Sort(null, 0);
1901 toolBar.activeConfig.currentRow = row;
1906 bool unavailable = !project;
1908 projectAddItem.disabled = unavailable;
1909 toolBar.buttonAddProject.disabled = unavailable;
1911 projectSettingsItem.disabled = unavailable;
1913 projectBrowseFolderItem.disabled = unavailable;
1915 viewProjectItem.disabled = unavailable;
1917 toolBar.activeConfig.disabled = unavailable;
1918 toolBar.activeCompiler.disabled = unavailable;
1919 toolBar.activeBitDepth.disabled = unavailable;
1922 debugUseValgrindItem.disabled = unavailable;
1923 AdjustValgrindMenus();
1932 void AdjustValgrindMenus()
1934 bool unavailable = !project || !debugUseValgrindItem.checked;
1935 debugValgrindNoLeakCheckItem.disabled = unavailable;
1936 debugValgrindSummaryLeakCheckItem.disabled = unavailable;
1937 debugValgrindYesLeakCheckItem.disabled = unavailable;
1938 debugValgrindFullLeakCheckItem.disabled = unavailable;
1940 debugValgrindTrackOriginsItem.disabled = unavailable;
1942 debugValgrindRSDefaultItem.disabled = unavailable;
1943 debugValgrindRS0Item.disabled = unavailable;
1944 debugValgrindRS16Item.disabled = unavailable;
1945 debugValgrindRS32Item.disabled = unavailable;
1946 debugValgrindRS64Item.disabled = unavailable;
1947 debugValgrindRS128Item.disabled = unavailable;
1948 debugValgrindRS256Item.disabled = unavailable;
1949 debugValgrindRS512Item.disabled = unavailable;
1953 property bool hasOpenedCodeEditors
1958 for(w = firstChild; w; w = w.next)
1959 if(w._class == class(CodeEditor) &&
1960 w.isDocument && !w.closing && w.visible && w.created &&
1961 w.fileName && w.fileName[0])
1967 void AdjustFileMenus()
1969 bool unavailable = project != null || !hasOpenedCodeEditors; // are they supported source code (ec, c, cpp, etc) ?
1971 projectQuickItem.disabled = unavailable;
1974 void AdjustBuildMenus()
1976 bool unavailable = project && projectView.buildInProgress;
1977 bool naForRun = unavailable || !project || project.GetTargetType(project.config) != executable;
1979 projectNewItem.disabled = unavailable;
1980 toolBar.buttonNewProject.disabled = unavailable;
1981 projectOpenItem.disabled = unavailable;
1982 toolBar.buttonOpenProject.disabled = unavailable;
1984 unavailable = !project || projectView.buildInProgress;
1986 projectCloseItem.disabled = unavailable;
1987 // toolBar.buttonCloseProject.disabled = unavailable;
1989 projectRunItem.disabled = naForRun;
1990 toolBar.buttonRun.disabled = naForRun;
1992 projectBuildItem.disabled = false;
1993 projectBuildItem.text = unavailable ? $"Stop Build" : $"Build";
1994 projectBuildItem.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7;
1996 projectLinkItem.disabled = unavailable;
1997 toolBar.buttonReLink.disabled = unavailable;
1998 projectRebuildItem.disabled = unavailable;
1999 toolBar.buttonRebuild.disabled = unavailable;
2000 projectCleanItem.disabled = unavailable;
2001 toolBar.buttonClean.disabled = unavailable;
2002 projectCleanTargetItem.disabled = unavailable;
2003 projectRealCleanItem.disabled = unavailable;
2004 // toolBar.buttonRealClean.disabled = unavailable;
2005 projectRegenerateItem.disabled = unavailable;
2006 toolBar.buttonRegenerateMakefile.disabled = unavailable;
2007 #ifdef IDE_SHOW_INSTALL_MENU_BUTTON
2008 projectInstallItem.disabled = unavailable;
2009 toolBar.buttonInstall.disabled = unavailable;
2011 projectCompileItem.disabled = unavailable;
2013 AdjustPopupBuildMenus();
2016 void AdjustPopupBuildMenus()
2018 bool unavailable = !project || projectView.buildInProgress;
2020 if(projectView && projectView.popupMenu && projectView.popupMenu.menu && projectView.popupMenu.created)
2023 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectBuild, 0);
2026 menu.disabled = false;
2027 menu.text = unavailable ? $"Stop Build" : $"Build";
2028 menu.accelerator = unavailable ? Key { pauseBreak, ctrl = true } : f7;
2031 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectLink, 0); if(menu) menu.disabled = unavailable;
2032 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRebuild, 0); if(menu) menu.disabled = unavailable;
2033 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectCleanTarget, 0); if(menu) menu.disabled = unavailable;
2034 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectClean, 0); if(menu) menu.disabled = unavailable;
2035 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRealClean, 0); if(menu) menu.disabled = unavailable;
2036 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRegenerate, 0); if(menu) menu.disabled = unavailable;
2037 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectInstall, 0); if(menu) menu.disabled = unavailable;
2038 menu = projectView.popupMenu.menu.FindItem(ProjectView::ProjectRemove, 0); if(menu) menu.disabled = unavailable;
2039 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileClean, 0); if(menu) menu.disabled = unavailable;
2040 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileCompile, 0); if(menu) menu.disabled = unavailable;
2041 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugPrecompile, 0); if(menu) menu.disabled = unavailable;
2042 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugCompile, 0); if(menu) menu.disabled = unavailable;
2043 menu = projectView.popupMenu.menu.FindItem(ProjectView::FileDebugGenerateSymbols, 0); if(menu) menu.disabled = unavailable;
2044 projectView.popupMenu.Update(null);
2048 property bool areDebugMenusUnavailable { get {
2050 project.GetTargetType(project.config) != executable ||
2051 projectView.buildInProgress == buildingMainProject;
2054 property bool isBreakpointTogglingUnavailable { get { return !project; } }
2055 property bool isDebuggerRunning { get { if(ide.debugger) return ide.debugger.state == running; return false; } }
2056 property bool isDebuggerStopped { get { if(ide.debugger) return ide.debugger.state == stopped; return false; } }
2058 void AdjustDebugMenus()
2060 bool unavailable = areDebugMenusUnavailable;
2061 bool running = isDebuggerRunning;
2062 bool stopped = isDebuggerStopped;
2063 bool active = debugger.isActive;
2064 bool noBreakpointToggle = !project;
2066 bool isNotRunning = unavailable || !running;
2067 bool isNotNotRunning = unavailable || running;
2068 bool isNotStopped = unavailable || !stopped;
2069 bool isNotActive = unavailable || !active;
2071 debugStartResumeItem.disabled = isNotNotRunning;
2072 debugStartResumeItem.text = active ? $"Resume" : $"Start";
2073 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
2076 toolBar.buttonDebugStartResume.disabled = isNotNotRunning;
2077 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
2080 debugBreakItem.disabled = isNotRunning;
2081 debugStopItem.disabled = isNotActive;
2082 debugRestartItem.disabled = isNotActive;
2085 toolBar.buttonDebugPause.disabled = isNotRunning;
2086 toolBar.buttonDebugStop.disabled = isNotActive;
2087 toolBar.buttonDebugRestart.disabled = isNotActive;
2090 debugStepIntoItem.disabled = isNotNotRunning;
2091 debugStepOverItem.disabled = isNotNotRunning;
2092 debugSkipStepOverItem.disabled = isNotNotRunning;
2093 debugStepOutItem.disabled = isNotStopped;
2094 debugSkipStepOutItem.disabled = isNotStopped;
2096 debugStepUntilItem.disabled = isNotStopped;
2097 debugSkipStepUntilItem.disabled = isNotStopped;
2101 toolBar.buttonDebugStepInto.disabled = isNotNotRunning;
2102 toolBar.buttonDebugStepOver.disabled = isNotNotRunning;
2103 toolBar.buttonDebugSkipStepOver.disabled = isNotNotRunning;
2104 toolBar.buttonDebugStepOut.disabled = isNotStopped;
2105 //toolBar.buttonDebugSkipStepOutItem.disabled = isNotNotRunning;
2107 if((Designer)GetActiveDesigner())
2109 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
2111 codeEditor.AdjustDebugMenus();
2115 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
2117 char tempString[MAX_LOCATION];
2118 strcpy(tempString, directory);
2119 if(saveSettings && !projectView)
2121 ideSettings.ideFileDialogLocation = directory;
2122 settingsContainer.Save();
2125 ideFileDialog.currentDirectory = tempString;
2126 codeEditorFileDialog.currentDirectory = tempString;
2127 codeEditorFormFileDialog.currentDirectory = tempString;
2130 void ChangeProjectFileDialogDirectory(char * directory)
2132 ideSettings.ideProjectFileDialogLocation = directory;
2133 settingsContainer.Save();
2136 Window FindWindow(char * filePath)
2138 Window document = null;
2140 // TOCHECK: Do we need to change slashes here?
2141 for(document = firstChild; document; document = document.next)
2143 char * fileName = document.fileName;
2144 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
2146 document.visible = true;
2147 document.Activate();
2154 bool DontTerminateDebugSession(char * title)
2156 if(debugger.isActive)
2158 if(MessageBox { type = yesNo, master = ide,
2159 contents = $"Do you want to terminate the debugging session in progress?",
2160 text = title }.Modal() == no)
2163 MessageBox msg { type = yesNo, master = ide,
2164 contents = "Do you want to terminate the debugging session in progress?",
2166 if(msg.Modal() == no)
2178 Window OpenFile(char * origFilePath, bool dontMaximize, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod, bool noParsing)
2180 char extension[MAX_EXTENSION] = "";
2181 Window document = null;
2182 bool isProject = false;
2183 bool needFileModified = true;
2184 char winFilePath[MAX_LOCATION];
2185 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
2186 Window currentDoc = activeClient;
2187 bool maximizeDoc = !dontMaximize && ((currentDoc && currentDoc.state == maximized) || (!currentDoc && !projectView));
2190 GetExtension(filePath, extension);
2194 strcpy(extension, type);
2196 if(strcmp(extension, ProjectExtension))
2198 for(document = firstChild; document; document = document.next)
2200 char * fileName = document.fileName;
2201 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
2203 document.visible = true;
2205 document.Activate();
2211 if(createIfFails == whatever)
2213 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
2215 needFileModified = false;
2216 if(openMethod == normal)
2218 if(DontTerminateDebugSession($"Open Project"))
2228 Workspace workspace = null;
2230 if(FileExists(filePath))
2232 if(!strcmp(extension, ProjectExtension))
2234 char workspaceFile[MAX_LOCATION];
2235 strcpy(workspaceFile, filePath);
2236 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
2237 workspace = LoadWorkspace(workspaceFile, filePath);
2239 else if(!strcmp(extension, WorkspaceExtension))
2240 workspace = LoadWorkspace(filePath, null);
2243 //project = LoadProject(filePath, null);
2248 char absolutePath[MAX_LOCATION];
2249 CreateProjectView(workspace, filePath);
2250 document = projectView;
2252 toolBox.visible = true;
2253 sheet.visible = true;
2254 projectView.MakeActive();
2256 workspace.ParseLoadedBreakpoints();
2257 workspace.DropInvalidBreakpoints(null);
2260 ide.projectView.ShowOutputBuildLog(true);
2262 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
2263 ide.projectView.DisplayCompiler(compiler, false);
2266 UpdateCompilerConfigs(false);
2269 char newWorkingDir[MAX_LOCATION];
2270 StripLastDirectory(filePath, newWorkingDir);
2271 ChangeFileDialogsDirectory(newWorkingDir, false);
2274 document.fileName = filePath;
2276 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
2278 // this crashes on starting ide with epj file, solution please?
2279 // app.UpdateDisplay();
2281 workspace.holdTracking = true;
2282 for(ofi : workspace.openedFiles)
2284 if(ofi.state != closed)
2286 Window file = OpenFile(ofi.path, false, true, null, no, normal, noParsing);
2289 char fileName[MAX_LOCATION];
2291 GetLastDirectory(ofi.path, fileName);
2292 node = projectView.project.topNode.Find(fileName, true);
2294 node.EnsureVisible();
2298 ide.RepositionWindows(false);
2299 workspace.holdTracking = false;
2301 workspace.timer.Start();
2303 #if !defined(__WIN32__)
2304 // Valgrind Debug menu updates
2305 debugUseValgrindItem.checked = workspace.useValgrind;
2307 debugValgrindNoLeakCheckItem.checked = workspace.vgLeakCheck == no;
2308 debugValgrindSummaryLeakCheckItem.checked = workspace.vgLeakCheck == summary;
2309 debugValgrindYesLeakCheckItem.checked = workspace.vgLeakCheck == yes;
2310 debugValgrindFullLeakCheckItem.checked = workspace.vgLeakCheck == full;
2312 debugValgrindRSDefaultItem.checked = workspace.vgRedzoneSize == -1;
2313 debugValgrindRS0Item.checked = workspace.vgRedzoneSize == 0;
2314 debugValgrindRS16Item.checked = workspace.vgRedzoneSize == 16;
2315 debugValgrindRS32Item.checked = workspace.vgRedzoneSize == 32;
2316 debugValgrindRS64Item.checked = workspace.vgRedzoneSize == 64;
2317 debugValgrindRS128Item.checked = workspace.vgRedzoneSize == 128;
2318 debugValgrindRS256Item.checked = workspace.vgRedzoneSize == 256;
2319 debugValgrindRS512Item.checked = workspace.vgRedzoneSize == 512;
2321 debugValgrindTrackOriginsItem.checked = workspace.vgTrackOrigins;
2324 findInFilesDialog.mode = FindInFilesMode::project;
2325 findInFilesDialog.currentDirectory = ide.project.topNode.path;
2328 char location[MAX_LOCATION];
2329 StripLastDirectory(ide.project.topNode.path, location);
2330 ChangeProjectFileDialogDirectory(location);
2337 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
2339 ideProjectFileDialog.text = openProjectFileDialogTitle;
2340 if(ideProjectFileDialog.Modal() == cancel)
2342 filePath = ideProjectFileDialog.filePath;
2343 GetExtension(filePath, extension);
2354 else if(openMethod == add)
2359 char slashFilePath[MAX_LOCATION];
2360 GetSlashPathBuffer(slashFilePath, filePath);
2361 for(p : workspace.projects)
2363 if(!fstrcmp(p.filePath, slashFilePath))
2371 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
2372 contents = $"This project is already present in workspace." }.Modal();
2376 prj = LoadProject(filePath, null);
2379 char * activeConfigName = null;
2380 CompilerConfig compiler = ideSettings.GetCompilerConfig(workspace.compiler);
2381 prj.StartMonitoring();
2382 workspace.projects.Add(prj);
2383 if(toolBar.activeConfig.currentRow && toolBar.activeConfig.currentRow != toolBar.activeConfig.firstRow &&
2384 toolBar.activeConfig.currentRow.string && toolBar.activeConfig.currentRow.string[0])
2385 activeConfigName = toolBar.activeConfig.currentRow.string;
2386 if(activeConfigName)
2388 for(cfg : prj.configurations)
2390 if(cfg.name && !strcmp(cfg.name, activeConfigName))
2398 projectView.AddNode(prj.topNode, null);
2399 workspace.modified = true;
2401 findInFilesDialog.AddProjectItem(prj);
2402 projectView.ShowOutputBuildLog(true);
2403 projectView.DisplayCompiler(compiler, false);
2404 projectView.ProjectUpdateMakefileForAllConfigs(prj);
2408 char location[MAX_LOCATION];
2409 StripLastDirectory(prj.topNode.path, location);
2410 ChangeProjectFileDialogDirectory(location);
2413 // projectView is associated with the main project and not with the one just added but
2414 return projectView; // just to let the caller know something was opened
2422 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
2423 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
2424 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
2426 if(FileExists(filePath))
2427 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2428 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2429 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
2432 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2435 else if(!strcmp(extension, "3ds"))
2437 if(FileExists(filePath))
2438 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
2439 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
2440 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
2444 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
2447 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
2448 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
2449 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
2450 !strcmp(extension, "css") || !strcmp(extension, "php") ||
2451 !strcmp(extension, "js"))
2453 CodeEditor editor { parent = this, state = state, visible = false, noParsing = noParsing };
2454 editor.updatingCode = true;
2455 if(editor.LoadFile(filePath))
2458 editor.visible = true;
2462 needFileModified = false;
2466 CodeEditor editor { parent = this, state = state, visible = false, noParsing = noParsing };
2467 if(editor.LoadFile(filePath))
2470 editor.visible = true;
2474 needFileModified = false;
2477 if(document && (document._class == class(PictureEdit) ||
2478 document._class == class(ModelView)))
2483 document.fileName = filePath;
2484 if(workspace && !workspace.holdTracking)
2485 workspace.UpdateOpenedFileInfo(filePath, opened);
2489 if(!document && createIfFails != no)
2491 if(createIfFails != yes && !needFileModified &&
2492 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
2493 createIfFails = yes;
2494 if(createIfFails == yes || createIfFails == whatever)
2496 document = (Window)NewCodeEditor(this, maximizeDoc ? maximized : normal, true);
2498 document.fileName = filePath;
2504 if(projectView && document._class == class(CodeEditor) && workspace)
2506 int lineNumber, position;
2508 CodeEditor editor = (CodeEditor)document;
2509 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
2510 editor.openedFileInfo.holdTracking = true;
2511 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
2512 position = Max(editor.openedFileInfo.position - 1, 0);
2513 editor.editBox.GoToLineNum(lineNumber);
2514 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
2515 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
2516 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
2517 editor.editBox.scroll = scroll;
2518 editor.openedFileInfo.holdTracking = false;
2521 if(needFileModified)
2522 document.OnFileModified = OnFileModified;
2523 document.NotifySaved = DocumentSaved;
2524 if(maximizeDoc && document.hasMaximize)
2525 document.state = maximized;
2528 ideSettings.AddRecentProject(document.fileName);
2530 ideSettings.AddRecentFile(document.fileName);
2531 ide.UpdateRecentMenus();
2532 ide.AdjustFileMenus();
2533 settingsContainer.Save();
2541 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2542 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2544 if(!parentClosing && ide.workspace)
2545 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2548 bool ModelView::ModelViewOnClose(bool parentClosing)
2550 if(!parentClosing && ide.workspace)
2551 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2554 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2556 if(!parentClosing && ide.workspace)
2557 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2562 void OnUnloadGraphics(Window window)
2564 display.ClearMaterials();
2565 display.ClearTextures();
2566 display.ClearMeshes();
2570 void UpdateStateLight(StatusField fld, bool on)
2572 fld.color = on ? lime : Color { 128,128,128 };
2573 fld.backColor = on ? dimGray : 0;
2577 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2579 UpdateStateLight(caps, app.GetKeyState(capsState));
2580 UpdateStateLight(num, app.GetKeyState(numState));
2584 bool OnKeyDown(Key key, unichar ch)
2588 case b: projectView.Update(null); break;
2589 case capsLock: UpdateStateLight(caps, app.GetKeyState(capsState)); break;
2590 case numLock: UpdateStateLight(num, app.GetKeyState(numState)); break;
2595 bool OnKeyUp(Key key, unichar ch)
2599 case capsLock: UpdateStateLight(caps, app.GetKeyState(capsState)); break;
2600 case numLock: UpdateStateLight(num, app.GetKeyState(numState)); break;
2605 void GoToError(const char * line, bool noParsing)
2608 projectView.GoToError(line, noParsing);
2611 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2615 char *colon = strchr(text, ':');
2616 char filePath[MAX_LOCATION] = "";
2617 char completePath[MAX_LOCATION];
2618 int line = 0, col = 0;
2619 int len = strlen(text);
2621 FileAttribs fileAttribs;
2623 // support for valgrind output
2624 if((s = strstr(text, "==")) && (s = strstr(s+2, "==")) && (s = strstr(s+2, ":")) && (s = strstr(s+1, ":")))
2635 /*for(s=colon; *s; s++)
2644 //line = atoi(colon+1);
2646 // support for "Found n match(es) in "file/path";
2647 else if(path[len-1] == '\"' && strstr(path, $"Found %d match%s in \"%s\"%s\n\n"."Found") && strstr(path, $"match") && strstr(path, $"in") && (s = strstr(path, "\"")) && s != path+len-1)
2653 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2655 path = (colon - 1 > path) ? colon - 1 : path;
2656 colon = strstr(colon + 1, ":");
2658 if(*path == '*' && (s = strchr(path+1, '*')))
2660 while(isspace(*path)) path++;
2664 char * close = strchr(path, ')');
2668 strncpy(name, path+1, close - path - 1);
2669 name[close - path - 1] = '\0';
2670 for(p : ide.workspace.projects)
2672 if(!strcmp(p.name, name))
2682 prj = project ? project : (dir ? null : ide.project);
2685 strncpy(filePath, path, colon - path);
2686 filePath[colon - path] = '\0';
2687 line = atoi(colon + 1);
2688 colon = strstr(colon + 1, ":");
2690 col = atoi(colon + 1);
2692 else if(path - 1 >= text && *(path - 1) == '\"')
2694 colon = strchr(path, '\"');
2697 strncpy(filePath, path, colon - path);
2698 filePath[colon - path] = '\0';
2701 else if(path && !colon)
2703 strcpy(filePath, path);
2709 strcpy(completePath, prj.topNode.path);
2710 else if(dir && dir[0])
2711 strcpy(completePath, dir);
2713 completePath[0] = '\0';
2714 PathCat(completePath, filePath);
2716 if((fileAttribs = FileExists(completePath)))
2717 CodeLocationGoTo(completePath, fileAttribs, line, col);
2718 else if(ide.workspace)
2721 for(p : ide.workspace.projects)
2723 strcpy(completePath, p.topNode.path);
2724 PathCat(completePath, filePath);
2725 if((fileAttribs = FileExists(completePath)).isFile)
2727 CodeLocationGoTo(completePath, fileAttribs, line, col);
2734 for(p : ide.workspace.projects)
2736 ProjectNode node = p.topNode.Find(filePath, false);
2739 node.GetFullFilePath(completePath);
2740 if((fileAttribs = FileExists(completePath)).isFile)
2742 CodeLocationGoTo(completePath, fileAttribs, line, col);
2752 void CodeLocationGoTo(const char * path, const FileAttribs fileAttribs, int line, int col)
2754 if(fileAttribs.isFile)
2756 char ext[MAX_EXTENSION];
2757 GetExtension(path, ext);
2759 if(!strcmp(ext, "mp3") || !strcmp(ext, "flac") || !strcmp(ext, "ogg") || !strcmp(ext, "avi") || !strcmp(ext, "mkv"))
2761 else if(!strcmp(ext, "a") || !strcmp(ext, "o") || !strcmp(ext, "lib") || !strcmp(ext, "dll") || !strcmp(ext, "exe"))
2763 char dirPath[MAX_LOCATION];
2764 StripLastDirectory(path, dirPath);
2769 CodeEditor codeEditor = (CodeEditor)OpenFile(path, false, true, ext, no, normal, false);
2770 if(codeEditor && line)
2772 EditBox editBox = codeEditor.editBox;
2773 editBox.GoToLineNum(line - 1);
2774 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2778 else if(fileAttribs.isDirectory)
2782 void OnRedraw(Surface surface)
2784 Bitmap bitmap = back.bitmap;
2786 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2789 void SheetSelected(SheetType sheetSelected)
2791 if(activeChild == sheet)
2793 if(sheetSelected == methods)
2795 viewPropertiesItem.accelerator = f4;
2796 viewPropertiesItem.parent = viewMenu;
2797 viewMethodsItem.parent = null;
2801 viewMethodsItem.accelerator = f4;
2802 viewMethodsItem.parent = viewMenu;
2803 viewPropertiesItem.parent = null;
2808 viewMethodsItem.parent = viewMenu;
2809 viewPropertiesItem.parent = viewMenu;
2810 if(sheetSelected == methods)
2812 viewMethodsItem.accelerator = f4;
2813 viewPropertiesItem.accelerator = 0;
2817 viewMethodsItem.accelerator = 0;
2818 viewPropertiesItem.accelerator = f4;
2823 void OnActivateClient(Window client, Window previous)
2825 //if(!client || client != previous)
2828 if(!client || client != previous)
2831 dataType = previous._class;
2832 if(previous && !strcmp(dataType.name, "CodeEditor"))
2834 ((CodeEditor)previous).UpdateFormCode();
2836 else if(previous && !strcmp(dataType.name, "Designer"))
2838 ((Designer)previous).codeEditor.UpdateFormCode();
2843 dataType = client._class;
2844 if(client && !strcmp(dataType.name, "CodeEditor"))
2846 CodeEditor codeEditor = (CodeEditor)client;
2847 SetPrivateModule(codeEditor.privateModule);
2848 SetCurrentContext(codeEditor.globalContext);
2849 SetTopContext(codeEditor.globalContext);
2850 SetGlobalContext(codeEditor.globalContext);
2852 SetDefines(&codeEditor.defines);
2853 SetImports(&codeEditor.imports);
2855 SetActiveDesigner(codeEditor.designer);
2857 sheet.codeEditor = codeEditor;
2858 toolBox.codeEditor = codeEditor;
2860 viewDesignerItem.parent = viewMenu;
2861 if(activeChild != codeEditor)
2863 viewCodeItem.parent = viewMenu;
2864 viewDesignerItem.accelerator = 0;
2865 viewCodeItem.accelerator = f8;
2869 viewCodeItem.parent = null;
2870 viewDesignerItem.accelerator = f8;
2873 else if(client && !strcmp(dataType.name, "Designer"))
2875 CodeEditor codeEditor = ((Designer)client).codeEditor;
2878 SetPrivateModule(codeEditor.privateModule);
2879 SetCurrentContext(codeEditor.globalContext);
2880 SetTopContext(codeEditor.globalContext);
2881 SetGlobalContext(codeEditor.globalContext);
2882 SetDefines(&codeEditor.defines);
2883 SetImports(&codeEditor.imports);
2887 SetPrivateModule(null);
2888 SetCurrentContext(null);
2889 SetTopContext(null);
2890 SetGlobalContext(null);
2895 SetActiveDesigner((Designer)client);
2897 sheet.codeEditor = codeEditor;
2898 toolBox.codeEditor = codeEditor;
2900 viewCodeItem.parent = viewMenu;
2901 if(activeChild != client)
2903 viewDesignerItem.parent = viewMenu;
2904 viewDesignerItem.accelerator = f8;
2905 viewCodeItem.accelerator = 0;
2909 viewDesignerItem.parent = null;
2910 viewCodeItem.accelerator = f8;
2915 if(!client && !projectView && sheet.visible)
2918 sheet.visible = false;
2919 toolBox.visible = false;
2922 sheet.codeEditor = null;
2923 toolBox.codeEditor = null;
2924 SetActiveDesigner(null);
2926 viewDesignerItem.parent = null;
2927 viewCodeItem.parent = null;
2930 SheetSelected(sheet.sheetSelected);
2933 projectCompileItem = null;
2938 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2940 CodeEditor codeEditor = (CodeEditor)client;
2941 EditBox editBox = codeEditor.editBox;
2943 statusBar.AddField(pos);
2945 caps = { width = 40, text = $"CAPS" };
2946 statusBar.AddField(caps);
2947 UpdateStateLight(caps, app.GetKeyState(capsState));
2949 ovr = { width = 36, text = $"OVR" };
2950 statusBar.AddField(ovr);
2951 UpdateStateLight(ovr, (editBox && editBox.overwrite));
2953 num = { width = 36, text = $"NUM" };
2954 statusBar.AddField(num);
2955 UpdateStateLight(num, app.GetKeyState(numState));
2957 //statusBar.text = "Ready";
2959 if(projectView && projectView.project)
2961 bool isCObject = false;
2962 ProjectNode node = projectView.GetNodeFromWindow(client, null, true, false, null);
2963 if(!node && (node = projectView.GetNodeFromWindow(client, null, true, true, null)))
2967 char nodeName[MAX_FILENAME];
2968 char name[MAX_FILENAME+96];
2970 ChangeExtension(node.name, "c", nodeName);
2971 sprintf(name, $"Compile %s", isCObject ? nodeName : node.name);
2972 projectCompileItem =
2974 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2976 bool NotifySelect(MenuItem selection, Modifiers mods)
2980 bool isCObject = false;
2981 bool isExcluded = false;
2982 ProjectNode node = projectView.GetNodeForCompilationFromWindow(activeClient, true, &isExcluded, &isCObject);
2986 ide.outputView.buildBox.Logf($"%s %s is excluded from current build configuration.\n", isCObject ? "Object file" : "File", node.name);
2989 List<ProjectNode> nodes { };
2991 projectView.Compile(node.project, nodes, mods.ctrl && mods.shift, isCObject ? cObject : normal);
2999 projectMenu.AddDynamic(projectCompileItem, ide, false);
3005 caps = ovr = num = null;
3010 bool OnClose(bool parentClosing)
3012 //return !projectView.buildInProgress;
3013 if(projectView && projectView.buildInProgress)
3015 if(DontTerminateDebugSession($"Close IDE"))
3017 if(findInFilesDialog)
3018 findInFilesDialog.SearchStop();
3021 workspace.timer.Stop();
3024 ideMainFrame.Destroy(0);
3031 bool passThrough = false;
3032 bool debugStart = false;
3033 bool debugWorkDir = false;
3034 char * passDebugWorkDir = null;
3035 bool openAsText = false;
3036 DynamicString passArgs { };
3039 for(c = 1; c<app.argc; c++)
3043 char * arg = app.argv[c];
3044 char * buf = new char[strlen(arg)*2+1];
3046 passArgs.concat(" ");
3048 passArgs.concat(buf);
3051 else if(debugWorkDir)
3053 passDebugWorkDir = CopyString(app.argv[c]);
3054 StripQuotes(passDebugWorkDir, passDebugWorkDir);
3055 debugWorkDir = false;
3057 else if(!strcmp(app.argv[c], "-t"))
3059 else if(!strcmp(app.argv[c], "-no-parsing"))
3060 ide.noParsing = true;
3061 else if(!strcmp(app.argv[c], "-debug-start"))
3063 else if(!strcmp(app.argv[c], "-debug-work-dir"))
3064 debugWorkDir = true;
3065 else if(!strcmp(app.argv[c], "-@"))
3069 char fullPath[MAX_LOCATION];
3070 char parentPath[MAX_LOCATION];
3071 char ext[MAX_EXTENSION];
3073 FileAttribs dirAttribs;
3074 GetWorkingDir(fullPath, MAX_LOCATION);
3075 PathCat(fullPath, app.argv[c]);
3076 StripLastDirectory(fullPath, parentPath);
3077 GetExtension(app.argv[c], ext);
3078 isProject = !openAsText && !strcmpi(ext, "epj");
3080 if(isProject && c > (debugStart ? 2 : 1)) continue;
3082 // Create directory for projects (only)
3083 if(((dirAttribs = FileExists(parentPath)) && dirAttribs.isDirectory) || isProject)
3085 if(isProject && !FileExists(fullPath))
3087 char name[MAX_LOCATION];
3088 NewProjectDialog newProjectDialog;
3092 projectView.visible = false;
3093 if(!projectView.Destroy(0))
3097 newProjectDialog = { master = this };
3099 strcpy(name, app.argv[c]);
3100 StripExtension(name);
3101 GetLastDirectory(name, name);
3102 newProjectDialog.projectName.contents = name;
3103 newProjectDialog.projectName.NotifyModified(newProjectDialog, newProjectDialog.projectName);
3104 newProjectDialog.locationEditBox.path = parentPath;
3105 newProjectDialog.NotifyModifiedLocation(newProjectDialog.locationEditBox);
3107 incref newProjectDialog;
3108 newProjectDialog.Modal();
3111 ideSettings.AddRecentProject(projectView.fileName);
3112 ide.UpdateRecentMenus();
3113 settingsContainer.Save();
3115 delete newProjectDialog;
3116 // Open only one project
3120 ide.OpenFile(fullPath, app.argFilesCount > 1, true, openAsText ? "txt" : null, yes, normal, false);
3122 else if(strstr(fullPath, "http://") == fullPath)
3123 ide.OpenFile(fullPath, app.argFilesCount > 1, true, openAsText ? "txt" : null, yes, normal, false);
3126 if(passThrough && projectView && projectView.project && workspace)
3127 workspace.commandLineArgs = passArgs;
3128 if(passDebugWorkDir && projectView && projectView.project && workspace)
3130 workspace.debugDir = passDebugWorkDir;
3131 delete passDebugWorkDir;
3134 ;//MenuDebugStart(debugStartResumeItem, 0); // <-- how TODO this without getting into the app.Wait lock
3136 UpdateToolBarActiveConfigs(false);
3137 UpdateToolBarActiveCompilers();
3144 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
3147 projectView.visible = false;
3148 projectView.Destroy(0);
3151 #ifdef GDB_DEBUG_GUI
3152 gdbDialog.Destroy(0);
3157 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config, int bitDepth)
3161 char * oldPaths[128];
3162 String oldList = new char[maxPathLen];
3163 Array<String> newExePaths { };
3164 //Map<String, bool> exePathExists { };
3166 #if defined(__unix__) || defined(__APPLE__)
3167 Array<String> newLibPaths { };
3168 Map<String, bool> libPathExists { };
3173 for(prj : workspace.projects)
3175 DirExpression targetDirExp;
3177 // SKIP FIRST PROJECT...
3178 if(prj == workspace.projects.firstIterator.data) continue;
3180 // NOTE: Right now the additional project config dir will be
3181 // obtained when the debugger is started, so toggling it
3182 // while building will change which library gets used.
3183 // To go with the initial state, e.g. when F5 was pressed,
3184 // we nould need to keep a list of all project's active
3185 // config upon startup.
3186 targetDirExp = prj.GetTargetDir(compiler, prj.config, bitDepth);
3188 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
3192 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
3193 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
3197 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
3198 if(cfg.targetType == sharedLibrary && cfg.debug)
3202 if(targetDirExp.dir)
3204 char buffer[MAX_LOCATION];
3205 #if defined(__WIN32__)
3206 Array<String> paths = newExePaths;
3208 Array<String> paths = newLibPaths;
3210 GetSystemPathBuffer(buffer, prj.topNode.path);
3211 PathCat(buffer, targetDirExp.dir);
3214 if(!fstrcmp(p, buffer))
3221 paths.Add(CopyString(buffer));
3223 delete targetDirExp;
3227 for(item : compiler.executableDirs)
3230 for(p : newExePaths)
3232 if(!fstrcmp(p, item))
3239 newExePaths.Add(CopySystemPath(item));
3242 GetEnvironment("PATH", oldList, maxPathLen);
3244 printf("Old value of PATH: %s\n", oldList);
3246 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
3247 for(c = 0; c < count; c++)
3250 for(p : newExePaths)
3252 if(!fstrcmp(p, oldPaths[c]))
3259 newExePaths.Add(CopySystemPath(oldPaths[c]));
3263 for(path : newExePaths)
3264 len += strlen(path) + 1;
3265 newList = new char[len + 1];
3267 for(path : newExePaths)
3269 strcat(newList, path);
3270 strcat(newList, pathListSep);
3272 newList[len - 1] = '\0';
3273 SetEnvironment("PATH", newList);
3275 printf("New value of PATH: %s\n", newList);
3282 #if defined(__unix__) || defined(__APPLE__)
3284 for(item : compiler.libraryDirs)
3286 if(!libPathExists[item]) // fstrcmp should be used
3288 String s = CopyString(item);
3290 libPathExists[s] = true;
3294 #if defined(__APPLE__)
3295 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
3297 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
3300 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
3302 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
3303 for(c = 0; c < count; c++)
3305 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
3307 String s = CopyString(oldPaths[c]);
3309 libPathExists[s] = true;
3314 for(path : newLibPaths)
3315 len += strlen(path) + 1;
3316 newList = new char[len + 1];
3318 for(path : newLibPaths)
3320 strcat(newList, path);
3321 strcat(newList, pathListSep);
3323 newList[len - 1] = '\0';
3324 #if defined(__APPLE__)
3325 SetEnvironment("DYLD_LIBRARY_PATH", newList);
3327 SetEnvironment("LD_LIBRARY_PATH", newList);
3330 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
3336 delete libPathExists;
3339 if(compiler.distccEnabled && compiler.distccHosts)
3340 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
3345 void DestroyTemporaryProjectDir()
3347 if(tmpPrjDir && tmpPrjDir[0])
3349 if(FileExists(tmpPrjDir).isDirectory)
3350 DestroyDir(tmpPrjDir);
3351 property::tmpPrjDir = null;
3357 // Graphics Driver Menu
3361 app.currentSkin.selectionColor = selectionColor;
3362 app.currentSkin.selectionText = selectionText;
3366 driverItems = new MenuItem[app.numDrivers];
3367 for(c = 0; c < app.numDrivers; c++)
3369 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
3370 driverItems[c].id = c;
3371 driverItems[c].isRadio = true;
3374 driverItems = new MenuItem[2];
3375 #if defined(__unix__)
3376 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
3377 driverItems[0].id = 0;
3378 driverItems[0].isRadio = true;
3380 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
3381 driverItems[0].id = 0;
3382 driverItems[0].isRadio = true;
3384 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
3385 driverItems[1].id = 1;
3386 driverItems[1].isRadio = true;
3388 /* skinItems = new MenuItem[app.numSkins];
3389 for(c = 0; c < app.numSkins; c++)
3391 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
3392 skinItems[c].id = c;
3393 skinItems[c].isRadio = true;
3396 ideFileDialog.master = this;
3397 ideProjectFileDialog.master = this;
3399 //SetDriverAndSkin();
3403 void UpdateRecentMenus()
3406 Menu fileMenu = menu.FindMenu($"File");
3407 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
3408 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
3409 char * itemPath = new char[MAX_LOCATION];
3410 char * itemName = new char[MAX_LOCATION+4];
3413 recentFiles.Clear();
3416 for(recent : ideSettings.recentFiles)
3418 strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0';
3419 MakeSystemPath(itemPath);
3420 snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0';
3421 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
3425 recentProjects.Clear();
3427 for(recent : ideSettings.recentProjects)
3429 strncpy(itemPath, recent, MAX_LOCATION); itemPath[MAX_LOCATION-1] = '\0';
3430 MakeSystemPath(itemPath);
3431 snprintf(itemName, MAX_LOCATION+4, "%d %s", 1 + c, itemPath); itemName[MAX_LOCATION+4-1] = '\0';
3432 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
3447 documentor.Puts("Quit\n");
3454 void DestroyDir(char * path)
3456 RecursiveDeleteFolderFSI fsi { };
3461 #if defined(__WIN32__)
3462 define sdkDirName = "Ecere SDK";
3464 define sdkDirName = "ecere";
3467 void FindAndShellOpenInstalledFolder(char * name)
3469 char * p = new char[MAX_LOCATION];
3470 char * v = new char[maxPathLen];
3473 Array<String> paths { };
3475 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3476 StripLastDirectory(p, p);
3478 paths.Add(CopyString(p));
3479 #if defined(__WIN32__)
3480 GetEnvironment("ECERE_SDK_SRC", v, maxPathLen);
3483 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3484 PathCat(p, name); paths.Add(CopyString(p));
3486 GetEnvironment("AppData", v, maxPathLen);
3489 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3490 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3492 GetEnvironment("ProgramFiles", v, maxPathLen);
3495 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3496 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3498 GetEnvironment("ProgramFiles(x86)", v, maxPathLen);
3501 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3502 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3504 GetEnvironment("SystemDrive", v, maxPathLen);
3507 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3508 PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3511 GetEnvironment("XDG_DATA_DIRS", v, maxPathLen);
3512 numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false);
3513 for(c=0; c<numTokens; c++)
3515 strncpy(p, tokens[c], MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3516 PathCat(p, sdkDirName); PathCat(p, name); paths.Add(CopyString(p));
3521 strncpy(p, path, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3522 if(FileExists(p).isDirectory)
3534 void FindAndShellOpenInstalledFile(char * subdir, char * name)
3536 char * p = new char[MAX_LOCATION];
3537 char * v = new char[maxPathLen];
3540 Array<String> paths { };
3542 strncpy(p, settingsContainer.moduleLocation, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3543 paths.Add(CopyString(p));
3544 StripLastDirectory(p, p);
3546 paths.Add(CopyString(p));
3547 #if defined(__WIN32__)
3548 GetEnvironment("ECERE_SDK_SRC", v, maxPathLen);
3551 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3552 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3554 GetEnvironment("AppData", v, maxPathLen);
3557 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3558 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3560 GetEnvironment("ProgramFiles", v, maxPathLen);
3563 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3564 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3566 GetEnvironment("ProgramFiles(x86)", v, maxPathLen);
3569 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3570 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3572 GetEnvironment("SystemDrive", v, maxPathLen);
3575 strncpy(p, v, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3576 PathCat(p, "Program Files"); PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3579 GetEnvironment("XDG_DATA_DIRS", v, maxPathLen);
3580 numTokens = TokenizeWith(v, sizeof(tokens) / sizeof(byte *), tokens, ":", false);
3581 for(c=0; c<numTokens; c++)
3583 strncpy(p, tokens[c], MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3584 PathCat(p, sdkDirName); PathCat(p, subdir); paths.Add(CopyString(p));
3589 strncpy(p, path, MAX_LOCATION); p[MAX_LOCATION-1] = '\0';
3591 if(FileExists(p).isFile)
3603 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
3605 bool preserveRootFolder;
3607 void OutFolder(char * folderPath, bool isRoot)
3609 if(!(preserveRootFolder && isRoot))
3610 RemoveDir(folderPath);
3613 bool OnFile(char * filePath)
3615 DeleteFile(filePath);
3620 class IDEApp : GuiApplication
3622 //driver = "Win32Console";
3623 // driver = "OpenGL";
3627 TempFile includeFile { };
3632 char ext[MAX_EXTENSION];
3633 SetLoggingMode(stdOut, null);
3634 //SetLoggingMode(debug, null);
3636 settingsContainer.Load();
3638 String language = GetLanguageString();
3639 if(ideSettings.language.OnCompare(language))
3641 LanguageRestart(ideSettings.language, app, null, null, null, null, true);
3646 // First count files arg to decide whether to maximize
3648 bool passThrough = false, debugWorkDir = false;
3651 for(c = 1; c<app.argc; c++)
3654 else if(debugWorkDir)
3655 debugWorkDir = false;
3656 else if(!strcmp(app.argv[c], "-t"));
3657 else if(!strcmp(app.argv[c], "-no-parsing"));
3658 else if(!strcmp(app.argv[c], "-debug-start"));
3659 else if(!strcmp(app.argv[c], "-debug-work-dir"))
3660 debugWorkDir = true;
3661 else if(!strcmp(app.argv[c], "-@"))
3668 if(app.argFilesCount > 1 && !strcmpi(GetExtension(argv[1], ext), "3ds"))
3670 app.driver = "OpenGL";
3671 ide.driverItems[1].checked = true;
3675 #if defined(__unix__) || defined(__APPLE__)
3676 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
3678 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
3680 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
3685 desktop.text = titleECEREIDE;
3688 for(c = 1; c<app.argc; c++)
3690 char fullPath[MAX_LOCATION];
3691 GetWorkingDir(fullPath, MAX_LOCATION);
3692 PathCat(fullPath, app.argv[c]);
3693 ide.OpenFile(fullPath, app.argFilesCount > 1, true, null, yes, normal, false);
3697 // Default to language specified by environment if no language selected
3698 if(!ideSettings.language)
3700 String language = GetLanguageString();
3702 ideSettings.language = language;
3704 ideSettings.language = "";
3707 // Default to home directory if no directory yet set up
3708 if(!ideSettings.ideProjectFileDialogLocation[0])
3711 char location[MAX_LOCATION];
3712 char * home = getenv("HOME");
3713 char * homeDrive = getenv("HOMEDRIVE");
3714 char * homePath = getenv("HOMEPATH");
3715 char * userProfile = getenv("USERPROFILE");
3716 char * systemDrive = getenv("SystemDrive");
3717 if(home && FileExists(home).isDirectory)
3719 strcpy(location, home);
3722 if(!found && homeDrive && homePath)
3724 strcpy(location, homeDrive);
3725 PathCat(location, homePath);
3726 if(FileExists(location).isDirectory)
3729 if(!found && FileExists(userProfile).isDirectory)
3731 strcpy(location, userProfile);
3734 if(!found && FileExists(systemDrive).isDirectory)
3736 strcpy(location, systemDrive);
3741 ideSettings.ideProjectFileDialogLocation = location;
3742 if(!ideSettings.ideFileDialogLocation[0])
3743 ideSettings.ideFileDialogLocation = location;
3747 if(!LoadIncludeFile())
3748 PrintLn("error: unable to load :crossplatform.mk file inside ide binary.");
3750 // Create language menu
3752 String language = ideSettings.language;
3755 ide.languageItems = new MenuItem[languages.count];
3758 ide.languageItems[i] =
3760 ide.languageMenu, l.name;
3761 bitmap = { l.bitmap };
3765 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
3767 if(!LanguageRestart(languages[(int)selection.id].code, app, ideSettings, settingsContainer, ide, ide.projectView, false))
3769 // Re-select previous selected language if aborted
3770 String language = ideSettings.language;
3774 if(((!language || !language[0]) && i == 0) ||
3775 (language && !strcmpi(l.code, language)))
3777 ide.languageItems[i].checked = true;
3786 if(((!language || !language[0]) && i == 0) ||
3787 (language && !strcmpi(l.code, language)))
3788 ide.languageItems[i].checked = true;
3791 MenuDivider { ide.languageMenu };
3794 ide.languageMenu, $"Help Translate";
3796 bool Window::NotifySelect(MenuItem selection, Modifiers mods)
3798 ShellOpen("http://translations.launchpad.net/ecere");
3804 ideMainFrame.Create();
3805 if(app.argFilesCount > 1)
3806 ide.MenuWindowTileVert(null, 0);
3810 bool Cycle(bool idle)
3814 if(ide.documentor.Peek())
3817 ide.documentor.GetLine(line, sizeof(line));
3818 if(!strcmpi(line, "Exited"))
3820 ide.documentor.CloseInput();
3821 ide.documentor.CloseOutput();
3822 ide.documentor.Wait();
3823 delete ide.documentor;
3826 if(ide.documentor && ide.documentor.eof)
3828 ide.documentor.CloseInput();
3829 ide.documentor.CloseOutput();
3830 ide.documentor.Wait();
3831 delete ide.documentor;
3837 bool LoadIncludeFile()
3839 bool result = false;
3840 File include = FileOpen(":crossplatform.mk", read);
3843 File f = includeFile;
3846 for(; !include.Eof(); )
3849 int count = include.Read(buffer, 1, 4096);
3850 f.Write(buffer, 1, count);
3860 IDEMainFrame ideMainFrame { };
3862 define app = ((IDEApp)__thisModule);
3864 define titleECEREIDE = $"Ecere IDE (Debug)";
3866 define titleECEREIDE = $"Ecere IDE";