2 public import static "ecere"
3 public import static "ec"
9 import "GlobalSettingsDialog"
10 import "NewProjectDialog"
11 import "FindInFilesDialog"
12 import "ActiveCompilerDialog"
19 import "ProjectActiveConfig"
20 import "ProjectConfig"
22 import "NodeProperties"
23 import "ProjectSettings"
35 import "BreakpointsView"
36 import "CallStackView"
47 import "FileSystemIterator"
49 #if defined(__WIN32__)
50 define pathListSep = ";";
52 define pathListSep = ":";
55 define maxPathLen = 65 * MAX_LOCATION;
57 class PathBackup : struct
64 oldPath = new char[maxPathLen];
65 oldLDPath = new char[maxPathLen];
67 GetEnvironment("PATH", oldPath, maxPathLen);
68 #if defined(__APPLE__)
69 GetEnvironment("DYLD_LIBRARY_PATH", oldLDPath, maxPathLen);
71 GetEnvironment("LD_LIBRARY_PATH", oldLDPath, maxPathLen);
77 SetEnvironment("PATH", oldPath);
78 #if defined(__APPLE__)
79 SetEnvironment("DYLD_LIBRARY_PATH", oldLDPath);
81 SetEnvironment("LD_LIBRARY_PATH", oldLDPath);
88 enum OpenCreateIfFails { no, yes, something, whatever };
89 enum OpenMethod { normal, add };
91 static Array<FileFilter> fileFilters
93 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
94 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
95 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
96 { $"Text files (*.txt, *.text, *.nfo, *.info)", "txt, text, nfo, info" },
97 { $"Web files (*.html, *.htm, *.xhtml, *.css, *.php, *.js, *.jsi, *.rb, *.xml)", "html, htm, xhtml, css, php, js, jsi, rb, xml" },
98 { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
99 { $"3D Studio Model Files (*.3ds)", "3ds" },
100 { $"All files", null }
103 static Array<FileType> fileTypes
105 { $"Based on extension", null },
108 { $"3D Studio Model", "3ds" }
111 static Array<FileFilter> projectFilters
113 { $"Project Files (*.epj)", ProjectExtension }
116 static Array<FileType> projectTypes
118 { $"Project File", ProjectExtension }
121 static Array<FileFilter> findInFilesFileFilters
123 { $"eC Files (*.ec, *.eh)", "ec, eh" },
124 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
125 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
126 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
127 { $"Text files (*.txt)", "txt" },
128 { $"All files", null }
131 FileDialog ideFileDialog
133 type = multiOpen, text = $"Open";
134 types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
137 define openProjectFileDialogTitle = $"Open Project";
138 define addProjectFileDialogTitle = $"Open Additional Project";
139 FileDialog ideProjectFileDialog
142 types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
145 GlobalSettingsDialog globalSettingsDialog
147 ideSettings = ideSettings;
148 settingsContainer = settingsContainer;
150 void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
152 switch(globalSettingsChange)
157 for(child = ide.firstChild; child; child = child.next)
159 if(child._class == class(CodeEditor))
161 CodeEditor codeEditor = (CodeEditor) child;
162 codeEditor.editBox.freeCaret = ideSettings.useFreeCaret;
163 // codeEditor.editBox.lineNumbers = ideSettings.showLineNumbers;
164 codeEditor.editBox.caretFollowsScrolling = ideSettings.caretFollowsScrolling;
165 codeEditor.OnPostCreate(); // Update editBox margin size
172 case compilerSettings:
174 ide.UpdateMakefiles();
181 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
186 lineY = (line - 1) * lineH;
187 if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
189 Bitmap bitmap = resource.bitmap;
191 surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
196 #define IDEItem(x) (&((IDEWorkSpace)0).x)
198 class IDEToolbar : ToolBar
202 ToolButton buttonNewFile { this, toolTip = $"New file", menuItemPtr = IDEItem(fileNewItem) };
204 ToolButton buttonOpenFile { this, toolTip = $"Open file", menuItemPtr = IDEItem(fileOpenItem) };
206 // ToolButton buttonCloseFile { this, toolTip = $"Close file", menuItemPtr = IDEItem(fileCloseItem) };
208 ToolButton buttonSaveFile { this, toolTip = $"Save file", menuItemPtr = IDEItem(fileSaveItem) };
210 ToolButton buttonSaveAllFile { this, toolTip = $"Save all", menuItemPtr = IDEItem(fileSaveAllItem) };
212 ToolSeparator separator1 { this };
221 //ToolSeparator separator2 { this };
223 /* Project options */
225 ToolButton buttonNewProject { this, toolTip = $"New project", menuItemPtr = IDEItem(projectNewItem) };
227 ToolButton buttonOpenProject { this, toolTip = $"Open project", menuItemPtr = IDEItem(projectOpenItem) };
228 // Add project to workspace
229 ToolButton buttonAddProject { this, toolTip = $"Add project to workspace", menuItemPtr = IDEItem(projectAddItem), disabled = true; };
231 //ToolButton buttonCloseProject { this, toolTip = $"Close project", menuItemPtr = IDEItem(projectCloseItem), disabled = true; };
233 ToolSeparator separator3 { this };
235 /* Build/Execution options */
237 ToolButton buttonBuild { this, toolTip = $"Build project", menuItemPtr = IDEItem(projectBuildItem), disabled = true; };
239 ToolButton buttonReLink { this, toolTip = $"Relink project", menuItemPtr = IDEItem(projectLinkItem), disabled = true; };
241 ToolButton buttonRebuild { this, toolTip = $"Rebuild project", menuItemPtr = IDEItem(projectRebuildItem), disabled = true; };
243 ToolButton buttonClean { this, toolTip = $"Clean project", menuItemPtr = IDEItem(projectCleanItem), disabled = true; };
244 // Regenerate Makefile
245 ToolButton buttonRegenerateMakefile { this, toolTip = $"Regenerate Makefile", menuItemPtr = IDEItem(projectRegenerateItem), disabled = true; };
246 // Compile actual file
248 ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem), disabled = true; };
250 ToolSeparator separator4 { this };
254 ToolButton buttonDebugStartResume { this, toolTip = $"Start", menuItemPtr = IDEItem(debugStartResumeItem), disabled = true; };
256 ToolButton buttonDebugRestart { this, toolTip = $"Restart", menuItemPtr = IDEItem(debugRestartItem), disabled = true; };
258 ToolButton buttonDebugPause { this, toolTip = $"Break", menuItemPtr = IDEItem(debugBreakItem), disabled = true; };
260 ToolButton buttonDebugStop { this, toolTip = $"Stop", menuItemPtr = IDEItem(debugStopItem), disabled = true; };
262 //ToolButton buttonRun { this, toolTip = $"Run", menuItemPtr = IDEItem(projectRunItem) };
264 ToolButton buttonDebugStepInto { this, toolTip = $"Step Into", menuItemPtr = IDEItem(debugStepIntoItem), disabled = true; };
266 ToolButton buttonDebugStepOver { this, toolTip = $"Step Over", menuItemPtr = IDEItem(debugStepOverItem), disabled = true; };
268 ToolButton buttonDebugStepOut { this, toolTip = $"Step Out", menuItemPtr = IDEItem(debugStepOutItem), disabled = true; };
270 ToolButton buttonDebugSkipStepOver { this, toolTip = $"Step Over Skipping Breakpoints", menuItemPtr = IDEItem(debugSkipStepOverItem), disabled = true; };
273 class IDEMainFrame : Window
275 background = activeBorder;
276 borderStyle = sizable;
280 minClientSize = { 600, 300 };
282 icon = { ":icon.png" };
283 text = titleECEREIDE;
287 anchor = { top = 0, right = 0, bottom = 0 };
290 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
297 isActiveClient = true;
299 direction = vertical;
300 background = activeBorder;
301 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
309 ((IDEWorkSpace)master).toolBar = null;
312 IDEWorkSpace ideWorkSpace { stack, this, toolBar = toolBar };
315 define ide = ideMainFrame.ideWorkSpace;
317 class IDEWorkSpace : Window
319 background = Color { 85, 85, 85 };
322 hasVertScroll = true;
323 hasHorzScroll = true;
325 isActiveClient = true;
326 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
330 MenuItem * driverItems, * skinItems;
331 StatusField pos { width = 150 };
332 StatusField ovr, caps, num;
334 BitmapResource back { ":ecereBack.jpg", window = this };
335 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
336 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
337 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
338 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
339 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
340 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
341 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
342 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
343 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
344 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
346 Debugger debugger { };
348 ProjectView projectView;
350 OutputView outputView
354 void OnGotoError(char * line)
359 void OnCodeLocationParseAndGoTo(char * line)
361 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
364 bool OnKeyDown(Key key, unichar ch)
369 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
370 ide.ShowCodeEditor();
373 ide.projectView.stopBuild = true;
377 OutputView::OnKeyDown(key, ch);
384 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
387 ide.RepositionWindows(false);
391 bool OnClose(bool parentClosing)
395 ide.RepositionWindows(false);
396 return parentClosing;
400 CallStackView callStackView
402 parent = this, font = { panelFont.faceName, panelFont.size };
404 void OnGotoLine(char * line)
407 stackLvl = atoi(line);
408 ide.debugger.GoToStackFrameLine(stackLvl, true);
411 void OnSelectFrame(int lineNumber)
413 ide.debugger.SelectFrame(lineNumber);
416 void OnToggleBreakpoint()
418 Debugger debugger = ide.debugger;
419 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
421 int line = debugger.activeFrame.line;
422 char name[MAX_LOCATION];
424 // TOFIX: Improve on this, don't use only filename, make a function
425 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
426 if(ide && ide.workspace)
428 for(p : ide.workspace.projects)
430 if(p.topNode.Find(name, false))
438 for(p : ide.workspace.projects)
440 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
448 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
451 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
452 if(codeEditor) { codeEditor.Update(null); Activate(); }
457 bool OnKeyDown(Key key, unichar ch)
461 case escape: ide.ShowCodeEditor(); break;
466 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
469 ide.RepositionWindows(false);
473 bool OnClose(bool parentClosing)
477 ide.RepositionWindows(false);
478 return parentClosing;
481 void OnRedraw(Surface surface)
484 int lineCursor, lineTopFrame, activeThread, hitThread;
485 int lineH, scrollY, boxH;
487 Breakpoint bp = null;
488 Debugger debugger = ide.debugger;
489 Frame activeFrame = debugger.activeFrame;
492 scrollY = editBox.scroll.y;
493 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
495 activeThread = debugger.activeThread;
496 hitThread = debugger.hitThread;
497 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
499 if(activeFrame && activeFrame.absoluteFile)
501 for(i : ide.workspace.breakpoints; i.type == user)
503 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
504 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
505 activeFrame.line == i.line)
514 DrawLineMarginIcon(surface,
515 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
516 lineCursor /*1*/, lineH, scrollY, boxH);
519 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
520 DrawLineMarginIcon(surface,
521 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
522 1, lineH, scrollY, boxH);
524 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
525 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
526 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
528 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
529 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
530 if(editBox.horzScroll && editBox.horzScroll.visible)
532 surface.SetBackground(control);
533 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
538 WatchesView watchesView { parent = this };
539 ThreadsView threadsView
541 parent = this, font = { panelFont.faceName, panelFont.size };
543 bool OnKeyDown(Key key, unichar ch)
547 case escape: ide.ShowCodeEditor(); break;
552 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
555 ide.RepositionWindows(false);
559 bool OnClose(bool parentClosing)
563 ide.RepositionWindows(false);
564 return parentClosing;
567 void OnSelectThread(int threadId)
570 ide.debugger.SelectThread(threadId);
573 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
576 Debugger debugger = ide.debugger;
577 *activeThread = debugger.activeThread;
578 *hitThread = debugger.hitThread;
579 *signalThread = debugger.signalThread;
584 BreakpointsView breakpointsView { parent = this };
586 ToolBox toolBox { parent = this };
587 Sheet sheet { parent = this };
590 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
592 Menu fileMenu { menu, $"File", f, hasMargin = true };
595 fileMenu, $"New", n, ctrlN;
596 bitmap = { ":actions/docNew.png" };
597 bool NotifySelect(MenuItem selection, Modifiers mods)
599 Window document = (Window)NewCodeEditor(this, normal, false);
600 document.NotifySaved = DocumentSaved;
604 MenuItem fileOpenItem
606 fileMenu, $"Open...", o, ctrlO;
607 bitmap = { ":actions/docOpen.png" };
608 bool NotifySelect(MenuItem selection, Modifiers mods)
610 if(!projectView && ideSettings.ideFileDialogLocation)
611 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
614 if(ideFileDialog.Modal() == ok)
616 bool gotWhatWeWant = false;
618 int numSelections = ideFileDialog.numSelections;
619 char ** multiFilePaths = ideFileDialog.multiFilePaths;
621 for(c = 0; c < numSelections; c++)
623 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
624 gotWhatWeWant = true;
627 MessageBox { type = yesNo, master = this, text = $"Error opening file",
628 contents = $"Open a different file?" }.Modal() == no)
630 if(!projectView && gotWhatWeWant)
631 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
641 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
642 MenuDivider { fileMenu };
643 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS, bitmap = { ":actions/docSave.png" } };
644 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
645 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll, bitmap = { ":actions/docSaveAll.png" } };
646 MenuDivider { fileMenu };
649 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
650 bool NotifySelect(MenuItem selection, Modifiers mods)
652 findInFilesDialog.replaceMode = false;
653 findInFilesDialog.Show();
657 MenuItem replaceInFiles
659 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
660 bool NotifySelect(MenuItem selection, Modifiers mods)
662 findInFilesDialog.replaceMode = true;
663 findInFilesDialog.Show();
667 MenuDivider { fileMenu };
668 MenuItem globalSettingsItem
670 fileMenu, $"Global Settings...", g;
671 bool NotifySelect(MenuItem selection, Modifiers mods)
673 globalSettingsDialog.master = this;
674 if(ide.workspace && ide.workspace.compiler)
675 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
676 else if(ideSettings.defaultCompiler)
677 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
678 globalSettingsDialog.Modal();
682 MenuDivider { fileMenu };
683 Menu recentFiles { fileMenu, $"Recent Files", r };
684 Menu recentProjects { fileMenu, $"Recent Projects", p };
685 MenuDivider { fileMenu };
688 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
690 bool NotifySelect(MenuItem selection, Modifiers mods)
692 ideMainFrame.Destroy(0);
697 bool FileRecentFile(MenuItem selection, Modifiers mods)
700 for(file : ideSettings.recentFiles)
702 if(id == selection.id)
704 OpenFile(file, normal, true, null, no, normal);
712 bool FileRecentProject(MenuItem selection, Modifiers mods)
715 for(file : ideSettings.recentProjects)
717 if(id == selection.id)
719 OpenFile(file, normal, true, null, no, normal);
727 MenuPlacement editMenu { menu, $"Edit", e };
729 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
730 MenuItem projectNewItem
732 projectMenu, $"New...", n, Key { n, true, true };
733 bitmap = { ":actions/projNew.png" };
734 bool NotifySelect(MenuItem selection, Modifiers mods)
736 if(!DontTerminateDebugSession($"New Project"))
737 if(MenuWindowCloseAll(null, 0))
739 NewProjectDialog newProjectDialog;
743 projectView.visible = false;
744 if(!projectView.Destroy(0))
748 newProjectDialog = { master = this };
749 newProjectDialog.Modal();
752 ideSettings.AddRecentProject(projectView.fileName);
753 ide.UpdateRecentMenus();
754 settingsContainer.Save();
760 MenuItem projectOpenItem
762 projectMenu, $"Open...", o, Key { o, true, true };
763 bitmap = { ":actions/projOpen.png" };
764 bool NotifySelect(MenuItem selection, Modifiers mods)
766 if(ideSettings.ideProjectFileDialogLocation)
767 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
769 ideProjectFileDialog.text = openProjectFileDialogTitle;
770 if(ideProjectFileDialog.Modal() == ok)
772 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
773 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
778 MenuItem projectQuickItem
780 projectMenu, $"Quick...", q, f7;
781 bool NotifySelect(MenuItem selection, Modifiers mods)
784 QuickProjectDialog{ this }.Modal();
788 MenuItem projectAddItem
790 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
791 bitmap = { ":actions/projAdd.png" };
793 bool NotifySelect(MenuItem selection, Modifiers mods)
795 if(ideSettings.ideProjectFileDialogLocation)
796 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
798 ideProjectFileDialog.text = addProjectFileDialogTitle;
801 if(ideProjectFileDialog.Modal() == ok)
803 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
805 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
806 contents = $"Add a different project?" }.Modal() == no)
817 MenuItem projectCloseItem
819 projectMenu, $"Close", c, disabled = true;
820 bool NotifySelect(MenuItem selection, Modifiers mods)
824 if(!ide.DontTerminateDebugSession($"Project Close"))
826 if(findInFilesDialog)
827 findInFilesDialog.SearchStop();
828 projectView.visible = false;
829 if(projectView.Destroy(0))
830 MenuWindowCloseAll(null, 0);
832 char workingDir[MAX_LOCATION];
833 GetWorkingDir(workingDir, MAX_LOCATION);
834 findInFilesDialog.currentDirectory = workingDir;
841 MenuDivider { projectMenu };
842 MenuItem activeCompilerItem
844 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
845 bool NotifySelect(MenuItem selection, Modifiers mods)
847 projectView.MenuCompiler(null, mods);
851 MenuItem projectActiveConfigItem
853 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
854 bool NotifySelect(MenuItem selection, Modifiers mods)
856 projectView.MenuConfig(projectView.active ? selection : null, mods);
860 MenuItem projectSettingsItem
862 projectMenu, $"Settings...", s, altF7, disabled = true;
863 bool NotifySelect(MenuItem selection, Modifiers mods)
865 projectView.MenuSettings(projectView.active ? selection : null, mods);
869 MenuDivider { projectMenu };
870 MenuItem projectBrowseFolderItem
872 projectMenu, $"Browse Project Folder", p, disabled = true;
873 bool NotifySelect(MenuItem selection, Modifiers mods)
876 projectView.MenuBrowseFolder(null, mods);
880 MenuDivider { projectMenu };
881 MenuItem projectRunItem
883 projectMenu, $"Run", r, ctrlF5, disabled = true;
884 bitmap = { ":actions/run.png" };
885 bool NotifySelect(MenuItem selection, Modifiers mods)
888 projectView.Run(null, mods);
892 MenuItem projectBuildItem
894 projectMenu, $"Build", b, f7, disabled = true;
895 bitmap = { ":actions/build.png" };
896 bool NotifySelect(MenuItem selection, Modifiers mods)
899 projectView.ProjectBuild(projectView.active ? selection : null, mods);
903 MenuItem projectLinkItem
905 projectMenu, $"Relink", l, disabled = true;
906 bitmap = { ":actions/relink.png" };
907 bool NotifySelect(MenuItem selection, Modifiers mods)
910 projectView.ProjectLink(projectView.active ? selection : null, mods);
914 MenuItem projectRebuildItem
916 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
917 bitmap = { ":actions/rebuild.png" };
918 bool NotifySelect(MenuItem selection, Modifiers mods)
921 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
925 MenuItem projectCleanItem
927 projectMenu, $"Clean", e, disabled = true;
928 bitmap = { ":actions/clean.png" };
929 bool NotifySelect(MenuItem selection, Modifiers mods)
934 projectView.ProjectClean(projectView.active ? selection : null, mods);
939 MenuItem projectRegenerateItem
941 projectMenu, $"Regenerate Makefile", m, disabled = true;
942 bitmap = { ":actions/regMakefile.png" };
943 bool NotifySelect(MenuItem selection, Modifiers mods)
946 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
950 MenuItem projectCompileItem;
951 Menu debugMenu { menu, $"Debug", d, hasMargin = true };
952 MenuItem debugStartResumeItem
954 debugMenu, $"Start", s, f5, disabled = true;
955 bitmap = { ":actions/debug.png" };
956 NotifySelect = MenuDebugStart;
958 bool MenuDebugStart(MenuItem selection, Modifiers mods)
962 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
963 if(!projectView.DebugStart())
964 debugStartResumeItem.disabled = false; // same exception
968 bool MenuDebugResume(MenuItem selection, Modifiers mods)
971 projectView.DebugResume();
974 MenuItem debugRestartItem
976 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
977 bitmap = { ":actions/restart.png" };
978 bool NotifySelect(MenuItem selection, Modifiers mods)
981 projectView.DebugRestart();
985 MenuItem debugBreakItem
987 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
988 bitmap = { ":actions/pause.png" };
989 bool NotifySelect(MenuItem selection, Modifiers mods)
992 projectView.DebugBreak();
996 MenuItem debugStopItem
998 debugMenu, $"Stop", p, shiftF5, disabled = true;
999 bitmap = { ":actions/stopDebug.png" };
1000 bool NotifySelect(MenuItem selection, Modifiers mods)
1003 projectView.DebugStop();
1007 MenuDivider { debugMenu };
1008 MenuItem debugStepIntoItem
1010 debugMenu, $"Step Into", i, f11, disabled = true;
1011 bitmap = { ":actions/stepInto.png" };
1012 bool NotifySelect(MenuItem selection, Modifiers mods)
1015 projectView.DebugStepInto();
1019 MenuItem debugStepOverItem
1021 debugMenu, $"Step Over", v, f10, disabled = true;
1022 bitmap = { ":actions/stepOver.png" };
1023 bool NotifySelect(MenuItem selection, Modifiers mods)
1026 projectView.DebugStepOver(false);
1030 MenuItem debugStepOutItem
1032 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1033 bitmap = { ":actions/stepOut.png" };
1034 bool NotifySelect(MenuItem selection, Modifiers mods)
1037 projectView.DebugStepOut(false);
1041 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1042 MenuItem debugSkipStepOverItem
1044 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1045 bool NotifySelect(MenuItem selection, Modifiers mods)
1048 projectView.DebugStepOver(true);
1052 MenuItem debugSkipStepOutItem
1054 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1055 bitmap = { ":actions/skipBreaks.png" };
1056 bool NotifySelect(MenuItem selection, Modifiers mods)
1059 projectView.DebugStepOut(true);
1063 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1064 //MenuDivider { debugMenu };
1065 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1066 MenuPlacement imageMenu { menu, $"Image", i };
1067 Menu viewMenu { menu, $"View", v };
1068 MenuItem viewProjectItem
1070 viewMenu, $"Project View", j, alt0, disabled = true;
1071 bool NotifySelect(MenuItem selection, Modifiers mods)
1075 projectView.visible = true;
1076 projectView.Activate();
1081 MenuPlacement { viewMenu, $"View Designer" };
1082 MenuPlacement { viewMenu, $"View Code" };
1083 MenuPlacement { viewMenu, $"View Properties" };
1084 MenuPlacement { viewMenu, $"View Methods" };
1085 MenuItem viewDesignerItem
1087 viewMenu, $"View Designer", d, f8;
1088 bool NotifySelect(MenuItem selection, Modifiers mods)
1090 Window client = activeClient;
1091 Class dataType = client._class;
1092 if(!strcmp(dataType.name, "Designer"))
1094 client.visible = true;
1098 ((CodeEditor)client).ViewDesigner();
1102 MenuItem viewCodeItem
1104 viewMenu, $"View Code", c, f8;
1105 bool NotifySelect(MenuItem selection, Modifiers mods)
1107 Window client = activeClient;
1108 Class dataType = client._class;
1109 if(!strcmp(dataType.name, "Designer"))
1110 client = ((Designer)client).codeEditor;
1113 // Do this after so the caret isn't moved yet...
1114 client.visible = true;
1118 MenuItem viewPropertiesItem
1120 viewMenu, $"View Properties", p, f4;
1121 bool NotifySelect(MenuItem selection, Modifiers mods)
1123 sheet.visible = true;
1124 sheet.sheetSelected = properties;
1129 MenuItem viewMethodsItem
1131 viewMenu, $"View Methods", m, f4;
1132 bool NotifySelect(MenuItem selection, Modifiers mods)
1134 sheet.visible = true;
1135 sheet.sheetSelected = methods;
1140 MenuItem viewToolBoxItem
1142 viewMenu, $"View Toolbox", x, f12;
1143 bool NotifySelect(MenuItem selection, Modifiers mods)
1145 toolBox.visible = true;
1150 MenuItem viewOutputItem
1152 viewMenu, $"Output", o, alt2;
1153 bool NotifySelect(MenuItem selection, Modifiers mods)
1159 MenuItem viewWatchesItem
1161 viewMenu, $"Watches", w, alt3;
1162 bool NotifySelect(MenuItem selection, Modifiers mods)
1168 MenuItem viewThreadsItem
1170 viewMenu, $"Threads", t, alt4;
1171 bool NotifySelect(MenuItem selection, Modifiers mods)
1177 MenuItem viewBreakpointsItem
1179 viewMenu, $"Breakpoints", b, alt5;
1180 bool NotifySelect(MenuItem selection, Modifiers mods)
1182 breakpointsView.Show();
1186 MenuItem viewCallStackItem
1188 viewMenu, $"Call Stack", s, alt7;
1189 bool NotifySelect(MenuItem selection, Modifiers mods)
1191 callStackView.Show();
1195 MenuItem viewAllDebugViews
1197 viewMenu, $"All Debug Views", a, alt9;
1198 bool NotifySelect(MenuItem selection, Modifiers mods)
1203 callStackView.Show();
1204 breakpointsView.Show();
1208 #ifdef GDB_DEBUG_GUI
1209 MenuDivider { viewMenu };
1210 MenuItem viewGDBItem
1212 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1213 bool NotifySelect(MenuItem selection, Modifiers mods)
1220 MenuDivider { viewMenu };
1221 MenuItem viewColorPicker
1223 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1224 bool NotifySelect(MenuItem selection, Modifiers mods)
1226 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1227 colorPicker.Create();
1231 MenuDivider { viewMenu };
1235 viewMenu, "Full Screen", f, checkable = true;
1237 bool NotifySelect(MenuItem selection, Modifiers mods)
1239 app.fullScreen ^= true;
1241 anchor = { 0, 0, 0, 0 };
1246 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1247 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1248 Menu windowMenu { menu, $"Window", w };
1249 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1250 MenuDivider { windowMenu };
1251 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1252 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1253 MenuDivider { windowMenu };
1254 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1255 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1256 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1257 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1258 MenuDivider { windowMenu };
1259 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1260 Menu helpMenu { menu, $"Help", h };
1263 helpMenu, $"API Reference", r, f1;
1264 bool NotifySelect(MenuItem selection, Modifiers mods)
1266 Execute("documentor");
1270 MenuDivider { helpMenu };
1273 helpMenu, $"About...", a;
1274 bool NotifySelect(MenuItem selection, Modifiers mods)
1276 AboutIDE { master = this }.Modal();
1281 property ToolBox toolBox
1283 get { return toolBox; }
1286 property Sheet sheet
1288 get { return sheet; }
1291 property Project project
1293 get { return projectView ? projectView.project : null; }
1296 property Workspace workspace
1298 get { return projectView ? projectView.workspace : null; }
1301 FindInFilesDialog findInFilesDialog
1303 master = this, parent = this;
1304 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1308 #ifdef GDB_DEBUG_GUI
1311 master = this, parent = this;
1312 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1314 void OnCommand(char * string)
1317 ide.debugger.SendGDBCommand(string);
1322 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1324 //app.driver = app.drivers[selection.id];
1326 app.driver = selection.id ? "OpenGL" : "X";
1328 app.driver = selection.id ? "OpenGL" : "GDI";
1330 delete ideSettings.displayDriver;
1331 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1333 settingsContainer.Save();
1334 //SetDriverAndSkin();
1338 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1340 app.skin = app.skins[selection.id];
1345 void SetDriverAndSkin()
1348 for(c = 0; c < app.numSkins; c++)
1349 if(!strcmp(app.skins[c], app.skin))
1351 skinItems[c].checked = true;
1354 for(c = 0; c < app.numDrivers; c++)
1355 if(!strcmp(app.drivers[c], app.driver))
1357 driverItems[c].checked = true;
1362 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1364 Project project = workspace.projects.firstIterator.data;
1365 projectView = ProjectView
1368 fileName = fileName;
1370 void NotifyDestroyed(Window window, DialogResult result)
1373 text = titleECEREIDE;
1378 projectView.Create();
1379 RepositionWindows(false);
1381 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1382 projectView.workspace = workspace;
1383 projectView.project = project;
1384 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1388 ide.breakpointsView.LoadFromWorkspace();
1389 ide.watchesView.LoadFromWorkspace();
1391 findInFilesDialog.projectNodeField.userData = projectView;
1394 char fileName[MAX_LOCATION];
1395 strcpy(fileName, project.topNode.path);
1396 PathCat(fileName, project.topNode.name);
1401 bool GetDebugMenusDisabled()
1405 Project project = projectView.project;
1407 if(project.GetTargetType(project.config) == executable)
1414 void RepositionWindows(bool expand)
1419 bool inDebugMode = debugger.isActive;
1420 bool callStackVisible = expand ? false : callStackView.visible;
1421 bool threadsVisible = expand ? false : threadsView.visible;
1422 bool watchesVisible = expand ? false : watchesView.visible;
1423 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1424 bool toolBoxVisible = toolBox.visible;
1425 bool outputVisible = expand ? false : outputView.visible;
1426 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1427 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1429 for(child = firstChild; child; child = child.next)
1431 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1432 child._class == class(Sheet) || child._class == class(ProjectView))
1434 Anchor anchor = child.anchor;
1435 anchor.top = topDistance;
1436 anchor.bottom = bottomDistance;
1437 if(child._class == class(CodeEditor) || child._class == class(Designer))
1439 anchor.right = toolBoxVisible ? 150 : 0;
1441 child.anchor = anchor;
1445 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1446 child._class == class(BreakpointsView))
1447 child.visible = false;
1450 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1455 bool ShowCodeEditor()
1458 activeClient.Activate();
1459 else if(projectView)
1461 projectView.visible = true;
1462 projectView.Activate();
1466 sheet.visible = true;
1472 bool ShouldStopBuild()
1474 return projectView.stopBuild;
1477 void DocumentSaved(Window document, char * fileName)
1479 ideSettings.AddRecentFile(fileName);
1480 ide.UpdateRecentMenus();
1481 settingsContainer.Save();
1484 bool Window::OnFileModified(FileChange fileChange, char * param)
1487 sprintf(temp, $"The document %s was modified by another application.\n"
1488 "Would you like to reload it and lose your changes?", this.fileName);
1489 if(MessageBox { type = yesNo, master = this/*.parent*/,
1490 text = $"Document has been modified", contents = temp }.Modal() == yes)
1492 char * fileName = CopyString(this.fileName);
1493 WindowState state = this.state;
1494 Anchor anchor = this.anchor;
1495 Size size = this.size;
1497 this.modifiedDocument = false;
1499 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1502 this.anchor = anchor;
1504 this.SetState(state, true, 0);
1512 void UpdateMakefiles()
1516 for(prj : workspace.projects)
1518 bool first = prj == workspace.projects.firstIterator.data;
1519 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1526 bool unavailable = !project;
1528 projectQuickItem.disabled = !unavailable;
1530 projectAddItem.disabled = unavailable;
1531 ((IDEMainFrame)master).toolBar.buttonAddProject.disabled = unavailable;
1533 activeCompilerItem.disabled = unavailable;
1534 projectActiveConfigItem.disabled = unavailable;
1535 projectSettingsItem.disabled = unavailable;
1537 projectBrowseFolderItem.disabled = unavailable;
1539 viewProjectItem.disabled = unavailable;
1545 void AdjustBuildMenus()
1547 bool unavailable = project && projectView.buildInProgress;
1549 projectNewItem.disabled = unavailable;
1550 toolBar.buttonNewProject.disabled = unavailable;
1551 projectOpenItem.disabled = unavailable;
1552 toolBar.buttonOpenProject.disabled = unavailable;
1554 unavailable = !project || projectView.buildInProgress;
1556 projectCloseItem.disabled = unavailable;
1557 // toolBar.buttonCloseProject.disabled = unavailable;
1559 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1560 toolBar.buttonRun.disabled = unavailable || project.GetTargetType(project.config) != executable;
1561 projectBuildItem.disabled = unavailable;
1562 toolBar.buttonBuild.disabled = unavailable;
1563 projectLinkItem.disabled = unavailable;
1564 toolBar.buttonReLink.disabled = unavailable;
1565 projectRebuildItem.disabled = unavailable;
1566 toolBar.buttonRebuild.disabled = unavailable;
1567 projectCleanItem.disabled = unavailable;
1568 toolBar.buttonClean.disabled = unavailable;
1569 projectRegenerateItem.disabled = unavailable;
1570 toolBar.buttonRegenerateMakefile.disabled = unavailable;
1571 projectCompileItem.disabled = unavailable;
1574 void AdjustDebugMenus()
1576 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1577 projectView.buildInProgress == buildingMainProject;
1578 bool active = ide.debugger.isActive;
1579 bool executing = ide.debugger.state == running;
1580 //bool holding = ide.debugger.state == stopped;
1582 debugStartResumeItem.disabled = unavailable || executing;
1584 toolBar.buttonDebugStartResume.disabled = unavailable || executing;
1586 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1588 toolBar.buttonDebugStartResume.toolTip = active ? $"Resume" : $"Start";
1589 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1591 debugBreakItem.disabled = unavailable || !executing;
1593 toolBar.buttonDebugPause.disabled = unavailable || !executing;
1594 debugStopItem.disabled = unavailable || !active;
1596 toolBar.buttonDebugStop.disabled = unavailable || !active;
1597 debugRestartItem.disabled = unavailable || !active;
1599 toolBar.buttonDebugRestart.disabled =unavailable || !active;
1601 debugStepIntoItem.disabled = unavailable || executing;
1603 toolBar.buttonDebugStepInto.disabled = unavailable || executing;
1604 debugStepOverItem.disabled = unavailable || executing;
1606 toolBar.buttonDebugStepOver.disabled = unavailable || executing;
1607 debugStepOutItem.disabled = unavailable || executing || !active;
1609 toolBar.buttonDebugStepOut.disabled = unavailable || executing || !active;
1610 debugSkipStepOverItem.disabled = unavailable || executing;
1612 toolBar.buttonDebugSkipStepOver.disabled = unavailable || executing;
1613 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1615 if((Designer)GetActiveDesigner())
1617 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1620 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1621 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1626 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1628 char tempString[MAX_LOCATION];
1629 strcpy(tempString, directory);
1630 if(saveSettings && !projectView)
1632 ideSettings.ideFileDialogLocation = directory;
1633 settingsContainer.Save();
1636 ideFileDialog.currentDirectory = tempString;
1637 codeEditorFileDialog.currentDirectory = tempString;
1638 codeEditorFormFileDialog.currentDirectory = tempString;
1641 void ChangeProjectFileDialogDirectory(char * directory)
1643 ideSettings.ideProjectFileDialogLocation = directory;
1644 settingsContainer.Save();
1647 Window FindWindow(char * filePath)
1649 Window document = null;
1651 // TOCHECK: Do we need to change slashes here?
1652 for(document = firstChild; document; document = document.next)
1654 char * fileName = document.fileName;
1655 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1657 document.visible = true;
1658 document.Activate();
1665 bool DontTerminateDebugSession(char * title)
1667 if(debugger.isActive)
1669 if(MessageBox { type = yesNo, master = ide,
1670 contents = $"Do you want to terminate the debugging session in progress?",
1671 text = title }.Modal() == no)
1674 MessageBox msg { type = yesNo, master = ide,
1675 contents = "Do you want to terminate the debugging session in progress?",
1677 if(msg.Modal() == no)
1689 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1691 char extension[MAX_EXTENSION] = "";
1692 Window document = null;
1693 bool isProject = false;
1694 bool needFileModified = true;
1695 char winFilePath[MAX_LOCATION];
1696 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1700 GetExtension(filePath, extension);
1704 strcpy(extension, type);
1706 if(strcmp(extension, ProjectExtension))
1708 for(document = firstChild; document; document = document.next)
1710 char * fileName = document.fileName;
1711 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1713 document.visible = true;
1714 document.Activate();
1720 if(createIfFails == whatever)
1722 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1724 if(openMethod == normal)
1726 if(DontTerminateDebugSession($"Open Project"))
1729 if(MenuWindowCloseAll(null, 0))
1733 projectView.visible = false;
1734 projectView.Destroy(0);
1735 // Where did this come from? projectView = null;
1742 Workspace workspace = null;
1744 if(FileExists(filePath))
1746 if(!strcmp(extension, ProjectExtension))
1748 char workspaceFile[MAX_LOCATION];
1749 strcpy(workspaceFile, filePath);
1750 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1751 workspace = LoadWorkspace(workspaceFile, filePath);
1753 else if(!strcmp(extension, WorkspaceExtension))
1754 workspace = LoadWorkspace(filePath, null);
1757 //project = LoadProject(filePath);
1762 char absolutePath[MAX_LOCATION];
1763 CreateProjectView(workspace, filePath);
1764 document = projectView;
1766 workspace.DropInvalidBreakpoints();
1769 ide.projectView.ShowOutputBuildLog(true);
1771 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1772 ide.projectView.DisplayCompiler(compiler, false);
1777 char newWorkingDir[MAX_LOCATION];
1778 StripLastDirectory(filePath, newWorkingDir);
1779 ChangeFileDialogsDirectory(newWorkingDir, false);
1782 document.fileName = filePath;
1784 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1786 // this crashes on starting ide with epj file, solution please?
1787 // app.UpdateDisplay();
1789 workspace.holdTracking = true;
1790 for(ofi : workspace.openedFiles)
1792 if(ofi.state != closed)
1794 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1797 char fileName[MAX_LOCATION];
1799 GetLastDirectory(ofi.path, fileName);
1800 node = projectView.project.topNode.Find(fileName, true);
1802 node.EnsureVisible();
1806 workspace.holdTracking = false;
1808 workspace.timer.Start();
1810 findInFilesDialog.mode = FindInFilesMode::project;
1811 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1814 char location[MAX_LOCATION];
1815 StripLastDirectory(ide.project.topNode.path, location);
1816 ChangeProjectFileDialogDirectory(location);
1820 if(projectView.debugger)
1821 projectView.debugger.EvaluateWatches();
1828 if(MessageBox { type = yesNo, master = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1830 ideProjectFileDialog.text = openProjectFileDialogTitle;
1831 if(ideProjectFileDialog.Modal() == cancel)
1833 filePath = ideProjectFileDialog.filePath;
1834 GetExtension(filePath, extension);
1845 else if(openMethod == add)
1850 char slashFilePath[MAX_LOCATION];
1851 GetSlashPathBuffer(slashFilePath, filePath);
1852 for(p : workspace.projects)
1854 if(!fstrcmp(p.filePath, slashFilePath))
1862 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1863 contents = $"This project is already present in workspace." }.Modal();
1867 prj = LoadProject(filePath);
1870 workspace.projects.Add(prj);
1872 projectView.AddNode(prj.topNode, null);
1873 workspace.modified = true;
1875 findInFilesDialog.AddProjectItem(prj);
1876 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1879 char location[MAX_LOCATION];
1880 StripLastDirectory(prj.topNode.path, location);
1881 ChangeProjectFileDialogDirectory(location);
1884 // projectView is associated with the main project and not with the one just added but
1885 return projectView; // just to let the caller know something was opened
1893 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1894 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1895 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1897 if(FileExists(filePath))
1898 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1899 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1900 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1903 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1906 else if(!strcmp(extension, "3ds"))
1908 if(FileExists(filePath))
1909 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1910 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1911 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1915 MessageBox { type = ok, master = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1918 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1919 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1920 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1921 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1922 !strcmp(extension, "js"))
1924 CodeEditor editor { parent = this, state = state, visible = false };
1925 editor.updatingCode = true;
1926 if(editor.LoadFile(filePath))
1929 editor.visible = true;
1933 needFileModified = false;
1937 CodeEditor editor { parent = this, state = state, visible = false };
1938 if(editor.LoadFile(filePath))
1941 editor.visible = true;
1945 needFileModified = false;
1948 if(document && (document._class == class(PictureEdit) ||
1949 document._class == class(ModelView)))
1954 document.fileName = filePath;
1955 if(workspace && !workspace.holdTracking)
1956 workspace.UpdateOpenedFileInfo(filePath, opened);
1960 if(!document && createIfFails != no)
1962 if(createIfFails != yes && !needFileModified &&
1963 MessageBox { type = yesNo, master = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1964 createIfFails = yes;
1965 if(createIfFails == yes || createIfFails == whatever)
1967 document = (Window)NewCodeEditor(this, state, true);
1969 document.fileName = filePath;
1975 if(projectView && document._class == class(CodeEditor) && workspace)
1977 int lineNumber, position;
1979 CodeEditor editor = (CodeEditor)document;
1980 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1981 editor.openedFileInfo.holdTracking = true;
1982 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1983 position = Max(editor.openedFileInfo.position - 1, 0);
1984 editor.editBox.GoToLineNum(lineNumber);
1985 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1986 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1987 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1988 editor.editBox.scroll = scroll;
1989 editor.openedFileInfo.holdTracking = false;
1992 if(needFileModified)
1993 document.OnFileModified = OnFileModified;
1994 document.NotifySaved = DocumentSaved;
1997 ideSettings.AddRecentProject(document.fileName);
1999 ideSettings.AddRecentFile(document.fileName);
2000 ide.UpdateRecentMenus();
2001 settingsContainer.Save();
2009 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
2010 /*bool Window::GenericDocumentOnClose(bool parentClosing)
2012 if(!parentClosing && ide.workspace)
2013 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2016 bool ModelView::ModelViewOnClose(bool parentClosing)
2018 if(!parentClosing && ide.workspace)
2019 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2022 bool PictureEdit::PictureEditOnClose(bool parentClosing)
2024 if(!parentClosing && ide.workspace)
2025 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
2030 void OnUnloadGraphics(Window window)
2032 display.ClearMaterials();
2033 display.ClearTextures();
2034 display.ClearMeshes();
2038 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
2040 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2041 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2045 bool OnKeyDown(Key key, unichar ch)
2050 projectView.Update(null);
2053 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
2056 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2062 void GoToError(const char * line)
2065 projectView.GoToError(line);
2068 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2071 char *colon = strchr(text, ':');
2072 char filePath[MAX_LOCATION];
2073 char completePath[MAX_LOCATION];
2074 int line = 0, col = 0;
2079 char * close = strchr(text, ')');
2083 strncpy(name, &text[4], close - text - 4);
2084 name[close - text - 4] = '\0';
2085 for(p : ide.workspace.projects)
2087 if(!strcmp(p.name, name))
2097 prj = project ? project : (dir ? null : ide.project);
2098 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2100 path = (colon - 1 > path) ? colon - 1 : path;
2101 colon = strstr(colon + 1, ":");
2103 while(isspace(*path)) path++;
2106 strncpy(filePath, path, colon - path);
2107 filePath[colon - path] = '\0';
2108 line = atoi(colon + 1);
2109 colon = strstr(colon + 1, ":");
2111 col = atoi(colon + 1);
2113 else if(path - 1 >= path && *(path - 1) == '\"')
2115 colon = strchr(path, '\"');
2118 strncpy(filePath, path, colon - path);
2119 filePath[colon - path] = '\0';
2124 strcpy(completePath, prj.topNode.path);
2125 else if(dir && dir[0])
2126 strcpy(completePath, dir);
2128 completePath[0] = '\0';
2129 PathCat(completePath, filePath);
2131 if(FileExists(completePath).isFile)
2133 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2134 if(codeEditor && line)
2136 EditBox editBox = codeEditor.editBox;
2137 editBox.GoToLineNum(line - 1);
2138 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2143 void OnRedraw(Surface surface)
2145 Bitmap bitmap = back.bitmap;
2147 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2150 void SheetSelected(SheetType sheetSelected)
2152 if(activeChild == sheet)
2154 if(sheetSelected == methods)
2156 viewPropertiesItem.accelerator = f4;
2157 viewPropertiesItem.parent = viewMenu;
2158 viewMethodsItem.parent = null;
2162 viewMethodsItem.accelerator = f4;
2163 viewMethodsItem.parent = viewMenu;
2164 viewPropertiesItem.parent = null;
2169 viewMethodsItem.parent = viewMenu;
2170 viewPropertiesItem.parent = viewMenu;
2171 if(sheetSelected == methods)
2173 viewMethodsItem.accelerator = f4;
2174 viewPropertiesItem.accelerator = 0;
2178 viewMethodsItem.accelerator = 0;
2179 viewPropertiesItem.accelerator = f4;
2184 void OnActivateClient(Window client, Window previous)
2186 //if(!client || client != previous)
2189 if(!client || client != previous)
2192 dataType = previous._class;
2193 if(previous && !strcmp(dataType.name, "CodeEditor"))
2195 ((CodeEditor)previous).UpdateFormCode();
2197 else if(previous && !strcmp(dataType.name, "Designer"))
2199 ((Designer)previous).codeEditor.UpdateFormCode();
2204 dataType = client._class;
2205 if(client && !strcmp(dataType.name, "CodeEditor"))
2207 CodeEditor codeEditor = (CodeEditor)client;
2208 SetPrivateModule(codeEditor.privateModule);
2209 SetCurrentContext(codeEditor.globalContext);
2210 SetTopContext(codeEditor.globalContext);
2211 SetGlobalContext(codeEditor.globalContext);
2213 SetDefines(&codeEditor.defines);
2214 SetImports(&codeEditor.imports);
2216 SetActiveDesigner(codeEditor.designer);
2218 sheet.codeEditor = codeEditor;
2219 toolBox.codeEditor = codeEditor;
2221 viewDesignerItem.parent = viewMenu;
2222 if(activeChild != codeEditor)
2224 viewCodeItem.parent = viewMenu;
2225 viewDesignerItem.accelerator = 0;
2226 viewCodeItem.accelerator = f8;
2230 viewCodeItem.parent = null;
2231 viewDesignerItem.accelerator = f8;
2234 else if(client && !strcmp(dataType.name, "Designer"))
2236 CodeEditor codeEditor = ((Designer)client).codeEditor;
2239 SetPrivateModule(codeEditor.privateModule);
2240 SetCurrentContext(codeEditor.globalContext);
2241 SetTopContext(codeEditor.globalContext);
2242 SetGlobalContext(codeEditor.globalContext);
2243 SetDefines(&codeEditor.defines);
2244 SetImports(&codeEditor.imports);
2248 SetPrivateModule(null);
2249 SetCurrentContext(null);
2250 SetTopContext(null);
2251 SetGlobalContext(null);
2256 SetActiveDesigner((Designer)client);
2258 sheet.codeEditor = codeEditor;
2259 toolBox.codeEditor = codeEditor;
2261 viewCodeItem.parent = viewMenu;
2262 if(activeChild != client)
2264 viewDesignerItem.parent = viewMenu;
2265 viewDesignerItem.accelerator = f8;
2266 viewCodeItem.accelerator = 0;
2270 viewDesignerItem.parent = null;
2271 viewCodeItem.accelerator = f8;
2277 sheet.codeEditor = null;
2278 toolBox.codeEditor = null;
2279 SetActiveDesigner(null);
2281 viewDesignerItem.parent = null;
2282 viewCodeItem.parent = null;
2285 SheetSelected(sheet.sheetSelected);
2288 projectCompileItem = null;
2293 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2295 CodeEditor codeEditor = (CodeEditor)client;
2296 EditBox editBox = codeEditor.editBox;
2298 statusBar.AddField(pos);
2300 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2301 statusBar.AddField(caps);
2303 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2304 statusBar.AddField(ovr);
2306 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2307 statusBar.AddField(num);
2309 //statusBar.text = "Ready";
2311 if(projectView && projectView.project)
2313 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2317 sprintf(name, $"Compile %s", node.name);
2318 projectCompileItem =
2320 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2322 bool NotifySelect(MenuItem selection, Modifiers mods)
2326 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2328 projectView.Compile(node);
2333 projectMenu.AddDynamic(projectCompileItem, ide, false);
2339 caps = ovr = num = null;
2344 bool OnClose(bool parentClosing)
2346 //return !projectView.buildInProgress;
2347 if(projectView && projectView.buildInProgress)
2349 if(DontTerminateDebugSession($"Close IDE"))
2351 if(findInFilesDialog)
2352 findInFilesDialog.SearchStop();
2355 workspace.timer.Stop();
2358 ideMainFrame.Destroy(0);
2365 for(c = 1; c<app.argc; c++)
2367 char fullPath[MAX_LOCATION];
2368 GetWorkingDir(fullPath, MAX_LOCATION);
2369 PathCat(fullPath, app.argv[c]);
2370 if(FileExists(fullPath))
2371 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2378 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2381 projectView.visible = false;
2382 projectView.Destroy(0);
2385 #ifdef GDB_DEBUG_GUI
2386 gdbDialog.Destroy(0);
2391 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2395 char * oldPaths[128];
2396 String oldList = new char[maxPathLen];
2397 Array<String> newExePaths { };
2398 //Map<String, bool> exePathExists { };
2400 #if defined(__unix__) || defined(__APPLE__)
2401 Array<String> newLibPaths { };
2402 Map<String, bool> libPathExists { };
2407 for(prj : workspace.projects)
2409 DirExpression targetDirExp;
2411 // SKIP FIRST PROJECT...
2412 if(prj == workspace.projects.firstIterator.data) continue;
2414 // NOTE: Right now the additional project config dir will be
2415 // obtained when the debugger is started, so toggling it
2416 // while building will change which library gets used.
2417 // To go with the initial state, e.g. when F5 was pressed,
2418 // we nould need to keep a list of all project's active
2419 // config upon startup.
2420 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2422 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2426 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2427 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2431 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2432 if(cfg.targetType == sharedLibrary && cfg.debug)
2436 if(targetDirExp.dir)
2438 char buffer[MAX_LOCATION];
2439 #if defined(__WIN32__)
2440 Array<String> paths = newExePaths;
2442 Array<String> paths = newLibPaths;
2444 GetSystemPathBuffer(buffer, prj.topNode.path);
2445 PathCat(buffer, targetDirExp.dir);
2448 if(!fstrcmp(p, buffer))
2455 paths.Add(CopyString(buffer));
2457 delete targetDirExp;
2461 for(item : compiler.executableDirs)
2464 for(p : newExePaths)
2466 if(!fstrcmp(p, item))
2473 newExePaths.Add(CopySystemPath(item));
2476 GetEnvironment("PATH", oldList, maxPathLen);
2478 printf("Old value of PATH: %s\n", oldList);
2480 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2481 for(c = 0; c < count; c++)
2484 for(p : newExePaths)
2486 if(!fstrcmp(p, oldPaths[c]))
2493 newExePaths.Add(CopySystemPath(oldPaths[c]));
2497 for(path : newExePaths)
2498 len += strlen(path) + 1;
2499 newList = new char[len + 1];
2501 for(path : newExePaths)
2503 strcat(newList, path);
2504 strcat(newList, pathListSep);
2506 newList[len - 1] = '\0';
2507 SetEnvironment("PATH", newList);
2509 printf("New value of PATH: %s\n", newList);
2516 #if defined(__unix__) || defined(__APPLE__)
2518 for(item : compiler.libraryDirs)
2520 if(!libPathExists[item]) // fstrcmp should be used
2522 newLibPaths.Add(item);
2523 libPathExists[item] = true;
2527 #if defined(__APPLE__)
2528 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2530 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2533 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2535 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2536 for(c = 0; c < count; c++)
2538 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2540 newLibPaths.Add(oldPaths[c]);
2541 libPathExists[oldPaths[c]] = true;
2546 for(path : newLibPaths)
2547 len += strlen(path) + 1;
2548 newList = new char[len + 1];
2550 for(path : newLibPaths)
2552 strcat(newList, path);
2553 strcat(newList, pathListSep);
2555 newList[len - 1] = '\0';
2556 #if defined(__APPLE__)
2557 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2559 SetEnvironment("LD_LIBRARY_PATH", newList);
2562 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2567 delete libPathExists;
2570 if(compiler.distccEnabled && compiler.distccHosts)
2571 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2576 void DestroyTemporaryProjectDir()
2578 if(tmpPrjDir && tmpPrjDir[0])
2580 if(FileExists(tmpPrjDir).isDirectory)
2581 DestroyDir(tmpPrjDir);
2582 property::tmpPrjDir = null;
2588 // Graphics Driver Menu
2592 app.currentSkin.selectionColor = selectionColor;
2593 app.currentSkin.selectionText = selectionText;
2597 driverItems = new MenuItem[app.numDrivers];
2598 for(c = 0; c < app.numDrivers; c++)
2600 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2601 driverItems[c].id = c;
2602 driverItems[c].isRadio = true;
2605 driverItems = new MenuItem[2];
2606 #if defined(__unix__)
2607 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2608 driverItems[0].id = 0;
2609 driverItems[0].isRadio = true;
2611 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2612 driverItems[0].id = 0;
2613 driverItems[0].isRadio = true;
2615 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2616 driverItems[1].id = 1;
2617 driverItems[1].isRadio = true;
2619 /* skinItems = new MenuItem[app.numSkins];
2620 for(c = 0; c < app.numSkins; c++)
2622 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2623 skinItems[c].id = c;
2624 skinItems[c].isRadio = true;
2627 ideFileDialog.master = this;
2628 ideProjectFileDialog.master = this;
2630 //SetDriverAndSkin();
2634 void UpdateRecentMenus()
2637 Menu fileMenu = menu.FindMenu($"File");
2638 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2639 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2640 char itemName[MAX_LOCATION + 4];
2643 recentFiles.Clear();
2646 for(recent : ideSettings.recentFiles)
2648 sprintf(itemName, "%d %s", 1 + c, recent);
2649 MakeSystemPath(itemName);
2650 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2654 recentProjects.Clear();
2656 for(recent : ideSettings.recentProjects)
2658 sprintf(itemName, "%d %s", 1 + c, recent);
2659 MakeSystemPath(itemName);
2660 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2673 void DestroyDir(char * path)
2675 RecursiveDeleteFolderFSI fsi { };
2680 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2682 bool preserveRootFolder;
2684 void OutFolder(char * folderPath, bool isRoot)
2686 if(!(preserveRootFolder && isRoot))
2687 RemoveDir(folderPath);
2690 bool OnFile(char * filePath)
2692 DeleteFile(filePath);
2697 class IDEApp : GuiApplication
2699 //driver = "Win32Console";
2700 // driver = "OpenGL";
2705 SetLoggingMode(stdOut, null);
2706 //SetLoggingMode(debug, null);
2708 settingsContainer.Load();
2709 #if defined(__unix__) || defined(__APPLE__)
2710 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2712 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2714 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2718 desktop.text = titleECEREIDE;
2721 for(c = 1; c<app.argc; c++)
2723 char fullPath[MAX_LOCATION];
2724 GetWorkingDir(fullPath, MAX_LOCATION);
2725 PathCat(fullPath, app.argv[c]);
2726 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2733 IDEMainFrame ideMainFrame { };
2735 define app = ((IDEApp)__thisModule);
2737 define titleECEREIDE = $"ECERE IDE (Debug)";
2739 define titleECEREIDE = $"ECERE IDE";