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 // NOTE: We will move ToolBar and ToolButton classes to libecere...
197 public class ToolBar : public Stacker
199 direction = horizontal;
200 background = activeBorder;
204 anchor = Anchor { left = 0, right = 0 };
205 clientSize = { h = 32 };
212 for(w = firstChild; w; w = w.next)
215 if(eClass_IsDerived(w._class, class(ToolButton)))
217 ToolButton b = (ToolButton)w;
218 MenuItem menuItem = b.menuItem;
220 if(menuItem && (bmp = menuItem.bitmap))
227 public class ToolButton : public Button
230 size = Size { 24, 24 };
232 bitmapAlignment = center;
233 MenuItem * menuItemPtr;
235 watch(master) { Window w; for(w = firstChild; w; w = w.next) w.master = master; };
237 NotifyClicked = SelectMenuItem;
239 bool Window::SelectMenuItem(Button button, int x, int y, Modifiers mods)
241 ToolButton toolButton = (ToolButton)button;
242 MenuItem menuItem = toolButton.menuItem;
243 return menuItem.NotifySelect(this, menuItem, 0);
247 property MenuItem * menuItemPtr { set { menuItemPtr = value; } }
248 property MenuItem menuItem
252 MenuItem menuItem = *(MenuItem *)((byte *)master + (uint)menuItemPtr);
258 #define IDEItem(x) (&((IDEWorkSpace)0).x)
260 class IDEToolbar : ToolBar
262 ToolButton buttonNewProject { this, toolTip = $"New Project", menuItemPtr = IDEItem(projectNewItem) };
265 class IDEMainFrame : Window
267 background = activeBorder;
268 borderStyle = sizable;
273 minClientSize = { 600, 300 };
274 nativeDecorations = true;
275 borderStyle = sizable;
280 icon = { ":icon.png" };
281 text = titleECEREIDE;
285 anchor = { top = 0, right = 0, bottom = 0 };
288 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
295 isActiveClient = true;
297 direction = vertical;
298 background = activeBorder;
299 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
301 IDEToolbar toolBar { master = ideWorkSpace, parent = stack };
302 IDEWorkSpace ideWorkSpace { master = this, parent = stack };
305 define ide = ideMainFrame.ideWorkSpace;
307 class IDEWorkSpace : Window
309 background = Color { 85, 85, 85 };
312 hasVertScroll = true;
313 hasHorzScroll = true;
315 isActiveClient = true;
316 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
319 MenuItem * driverItems, * skinItems;
320 StatusField pos { width = 150 };
321 StatusField ovr, caps, num;
323 BitmapResource back { ":ecereBack.jpg", window = this };
324 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
325 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
326 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
327 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
328 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
329 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
330 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
331 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
332 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
333 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
335 Debugger debugger { };
337 ProjectView projectView;
339 OutputView outputView
343 void OnGotoError(char * line)
348 void OnCodeLocationParseAndGoTo(char * line)
350 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
353 bool OnKeyDown(Key key, unichar ch)
358 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
359 ide.ShowCodeEditor();
362 ide.projectView.stopBuild = true;
366 OutputView::OnKeyDown(key, ch);
373 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
376 ide.RepositionWindows(false);
380 bool OnClose(bool parentClosing)
384 ide.RepositionWindows(false);
385 return parentClosing;
389 CallStackView callStackView
391 parent = this, font = { panelFont.faceName, panelFont.size };
393 void OnGotoLine(char * line)
396 stackLvl = atoi(line);
397 ide.debugger.GoToStackFrameLine(stackLvl, true);
400 void OnSelectFrame(int lineNumber)
402 ide.debugger.SelectFrame(lineNumber);
405 void OnToggleBreakpoint()
407 Debugger debugger = ide.debugger;
408 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
410 int line = debugger.activeFrame.line;
411 char name[MAX_LOCATION];
413 // TOFIX: Improve on this, don't use only filename, make a function
414 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
415 if(ide && ide.workspace)
417 for(p : ide.workspace.projects)
419 if(p.topNode.Find(name, false))
427 for(p : ide.workspace.projects)
429 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
437 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
440 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
441 if(codeEditor) { codeEditor.Update(null); Activate(); }
446 bool OnKeyDown(Key key, unichar ch)
450 case escape: ide.ShowCodeEditor(); break;
455 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
458 ide.RepositionWindows(false);
462 bool OnClose(bool parentClosing)
466 ide.RepositionWindows(false);
467 return parentClosing;
470 void OnRedraw(Surface surface)
473 int lineCursor, lineTopFrame, activeThread, hitThread;
474 int lineH, scrollY, boxH;
476 Breakpoint bp = null;
477 Debugger debugger = ide.debugger;
478 Frame activeFrame = debugger.activeFrame;
481 scrollY = editBox.scroll.y;
482 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
484 activeThread = debugger.activeThread;
485 hitThread = debugger.hitThread;
486 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
488 if(activeFrame && activeFrame.absoluteFile)
490 for(i : ide.workspace.breakpoints; i.type == user)
492 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
493 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
494 activeFrame.line == i.line)
503 DrawLineMarginIcon(surface,
504 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
505 lineCursor /*1*/, lineH, scrollY, boxH);
508 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
509 DrawLineMarginIcon(surface,
510 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
511 1, lineH, scrollY, boxH);
513 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
514 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
515 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
517 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
518 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
519 if(editBox.horzScroll && editBox.horzScroll.visible)
521 surface.SetBackground(control);
522 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
527 WatchesView watchesView { parent = this };
528 ThreadsView threadsView
530 parent = this, font = { panelFont.faceName, panelFont.size };
532 bool OnKeyDown(Key key, unichar ch)
536 case escape: ide.ShowCodeEditor(); break;
541 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
544 ide.RepositionWindows(false);
548 bool OnClose(bool parentClosing)
552 ide.RepositionWindows(false);
553 return parentClosing;
556 void OnSelectThread(int threadId)
559 ide.debugger.SelectThread(threadId);
562 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
565 Debugger debugger = ide.debugger;
566 *activeThread = debugger.activeThread;
567 *hitThread = debugger.hitThread;
568 *signalThread = debugger.signalThread;
573 BreakpointsView breakpointsView { parent = this };
575 ToolBox toolBox { parent = this };
576 Sheet sheet { parent = this };
579 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
581 Menu fileMenu { menu, $"File", f };
584 fileMenu, $"New", n, ctrlN;
585 bool NotifySelect(MenuItem selection, Modifiers mods)
587 Window document = (Window)NewCodeEditor(this, normal, false);
588 document.NotifySaved = DocumentSaved;
592 MenuItem fileOpenItem
594 fileMenu, $"Open...", o, ctrlO;
595 bool NotifySelect(MenuItem selection, Modifiers mods)
597 if(!projectView && ideSettings.ideFileDialogLocation)
598 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
601 if(ideFileDialog.Modal() == ok)
603 bool gotWhatWeWant = false;
605 int numSelections = ideFileDialog.numSelections;
606 char ** multiFilePaths = ideFileDialog.multiFilePaths;
608 for(c = 0; c < numSelections; c++)
610 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
611 gotWhatWeWant = true;
614 MessageBox { type = yesNo, master = this, text = $"Error opening file",
615 contents = $"Open a different file?" }.Modal() == no)
617 if(!projectView && gotWhatWeWant)
618 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
628 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
629 MenuDivider { fileMenu };
630 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS };
631 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
632 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll };
633 MenuDivider { fileMenu };
636 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
637 bool NotifySelect(MenuItem selection, Modifiers mods)
639 findInFilesDialog.replaceMode = false;
640 findInFilesDialog.Show();
644 MenuItem replaceInFiles
646 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
647 bool NotifySelect(MenuItem selection, Modifiers mods)
649 findInFilesDialog.replaceMode = true;
650 findInFilesDialog.Show();
654 MenuDivider { fileMenu };
655 MenuItem globalSettingsItem
657 fileMenu, $"Global Settings...", g;
658 bool NotifySelect(MenuItem selection, Modifiers mods)
660 globalSettingsDialog.master = this;
661 if(ide.workspace && ide.workspace.compiler)
662 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
663 else if(ideSettings.defaultCompiler)
664 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
665 globalSettingsDialog.Modal();
669 MenuDivider { fileMenu };
670 Menu recentFiles { fileMenu, $"Recent Files", r };
671 Menu recentProjects { fileMenu, $"Recent Projects", p };
672 MenuDivider { fileMenu };
675 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
677 bool NotifySelect(MenuItem selection, Modifiers mods)
679 ideMainFrame.Destroy(0);
684 bool FileRecentFile(MenuItem selection, Modifiers mods)
687 for(file : ideSettings.recentFiles)
689 if(id == selection.id)
691 OpenFile(file, normal, true, null, no, normal);
699 bool FileRecentProject(MenuItem selection, Modifiers mods)
702 for(file : ideSettings.recentProjects)
704 if(id == selection.id)
706 OpenFile(file, normal, true, null, no, normal);
714 MenuPlacement editMenu { menu, $"Edit", e };
716 Menu projectMenu { menu, $"Menu"."Project", p, hasMargin = true };
717 MenuItem projectNewItem
719 projectMenu, $"New...", n, Key { n, true, true };
720 bitmap = { "<:ecere>actions/listAdd.png" };
721 bool NotifySelect(MenuItem selection, Modifiers mods)
723 if(!DontTerminateDebugSession($"New Project"))
724 if(MenuWindowCloseAll(null, 0))
726 NewProjectDialog newProjectDialog;
730 projectView.visible = false;
731 if(!projectView.Destroy(0))
735 newProjectDialog = { master = this };
736 newProjectDialog.Modal();
739 ideSettings.AddRecentProject(projectView.fileName);
740 ide.UpdateRecentMenus();
741 settingsContainer.Save();
747 MenuItem projectOpenItem
749 projectMenu, $"Open...", o, Key { o, true, true };
750 bool NotifySelect(MenuItem selection, Modifiers mods)
752 if(ideSettings.ideProjectFileDialogLocation)
753 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
755 ideProjectFileDialog.text = openProjectFileDialogTitle;
756 if(ideProjectFileDialog.Modal() == ok)
758 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
759 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
764 MenuItem projectQuickItem
766 projectMenu, $"Quick...", q, f7;
767 bool NotifySelect(MenuItem selection, Modifiers mods)
770 QuickProjectDialog{ this }.Modal();
774 MenuItem projectAddItem
776 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
778 bool NotifySelect(MenuItem selection, Modifiers mods)
780 if(ideSettings.ideProjectFileDialogLocation)
781 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
783 ideProjectFileDialog.text = addProjectFileDialogTitle;
786 if(ideProjectFileDialog.Modal() == ok)
788 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
790 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
791 contents = $"Add a different project?" }.Modal() == no)
802 MenuItem projectCloseItem
804 projectMenu, $"Close", c, disabled = true;
805 bool NotifySelect(MenuItem selection, Modifiers mods)
809 if(!ide.DontTerminateDebugSession($"Project Close"))
811 if(findInFilesDialog)
812 findInFilesDialog.SearchStop();
813 projectView.visible = false;
814 if(projectView.Destroy(0))
815 MenuWindowCloseAll(null, 0);
817 char workingDir[MAX_LOCATION];
818 GetWorkingDir(workingDir, MAX_LOCATION);
819 findInFilesDialog.currentDirectory = workingDir;
826 MenuDivider { projectMenu };
827 MenuItem activeCompilerItem
829 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
830 bool NotifySelect(MenuItem selection, Modifiers mods)
832 projectView.MenuCompiler(null, mods);
836 MenuItem projectActiveConfigItem
838 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
839 bool NotifySelect(MenuItem selection, Modifiers mods)
841 projectView.MenuConfig(projectView.active ? selection : null, mods);
845 MenuItem projectSettingsItem
847 projectMenu, $"Settings...", s, altF7, disabled = true;
848 bool NotifySelect(MenuItem selection, Modifiers mods)
850 projectView.MenuSettings(projectView.active ? selection : null, mods);
854 MenuDivider { projectMenu };
855 MenuItem projectBrowseFolderItem
857 projectMenu, $"Browse Project Folder", p, disabled = true;
858 bool NotifySelect(MenuItem selection, Modifiers mods)
861 projectView.MenuBrowseFolder(null, mods);
865 MenuDivider { projectMenu };
866 MenuItem projectRunItem
868 projectMenu, $"Run", r, ctrlF5, disabled = true;
869 bool NotifySelect(MenuItem selection, Modifiers mods)
872 projectView.Run(null, mods);
876 MenuItem projectBuildItem
878 projectMenu, $"Build", b, f7, disabled = true;
879 bool NotifySelect(MenuItem selection, Modifiers mods)
882 projectView.ProjectBuild(projectView.active ? selection : null, mods);
886 MenuItem projectLinkItem
888 projectMenu, $"Relink", l, disabled = true;
889 bool NotifySelect(MenuItem selection, Modifiers mods)
892 projectView.ProjectLink(projectView.active ? selection : null, mods);
896 MenuItem projectRebuildItem
898 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
899 bool NotifySelect(MenuItem selection, Modifiers mods)
902 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
906 MenuItem projectCleanItem
908 projectMenu, $"Clean", e, disabled = true;
909 bool NotifySelect(MenuItem selection, Modifiers mods)
914 projectView.ProjectClean(projectView.active ? selection : null, mods);
919 MenuItem projectRegenerateItem
921 projectMenu, $"Regenerate Makefile", m, disabled = true;
922 bool NotifySelect(MenuItem selection, Modifiers mods)
925 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
929 MenuItem projectCompileItem;
930 Menu debugMenu { menu, $"Debug", d };
931 MenuItem debugStartResumeItem
933 debugMenu, $"Start", s, f5, disabled = true;
934 NotifySelect = MenuDebugStart;
936 bool MenuDebugStart(MenuItem selection, Modifiers mods)
940 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
941 if(!projectView.DebugStart())
942 debugStartResumeItem.disabled = false; // same exception
946 bool MenuDebugResume(MenuItem selection, Modifiers mods)
949 projectView.DebugResume();
952 MenuItem debugRestartItem
954 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
955 bool NotifySelect(MenuItem selection, Modifiers mods)
958 projectView.DebugRestart();
962 MenuItem debugBreakItem
964 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
965 bool NotifySelect(MenuItem selection, Modifiers mods)
968 projectView.DebugBreak();
972 MenuItem debugStopItem
974 debugMenu, $"Stop", p, shiftF5, disabled = true;
975 bool NotifySelect(MenuItem selection, Modifiers mods)
978 projectView.DebugStop();
982 MenuDivider { debugMenu };
983 MenuItem debugStepIntoItem
985 debugMenu, $"Step Into", i, f11, disabled = true;
986 bool NotifySelect(MenuItem selection, Modifiers mods)
989 projectView.DebugStepInto();
993 MenuItem debugStepOverItem
995 debugMenu, $"Step Over", v, f10, disabled = true;
996 bool NotifySelect(MenuItem selection, Modifiers mods)
999 projectView.DebugStepOver(false);
1003 MenuItem debugStepOutItem
1005 debugMenu, $"Step Out", o, shiftF11, disabled = true;
1006 bool NotifySelect(MenuItem selection, Modifiers mods)
1009 projectView.DebugStepOut(false);
1013 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
1014 MenuItem debugSkipStepOverItem
1016 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
1017 bool NotifySelect(MenuItem selection, Modifiers mods)
1020 projectView.DebugStepOver(true);
1024 MenuItem debugSkipStepOutItem
1026 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
1027 bool NotifySelect(MenuItem selection, Modifiers mods)
1030 projectView.DebugStepOut(true);
1034 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
1035 //MenuDivider { debugMenu };
1036 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
1037 MenuPlacement imageMenu { menu, $"Image", i };
1038 Menu viewMenu { menu, $"View", v };
1039 MenuItem viewProjectItem
1041 viewMenu, $"Project View", j, alt0, disabled = true;
1042 bool NotifySelect(MenuItem selection, Modifiers mods)
1046 projectView.visible = true;
1047 projectView.Activate();
1052 MenuPlacement { viewMenu, $"View Designer" };
1053 MenuPlacement { viewMenu, $"View Code" };
1054 MenuPlacement { viewMenu, $"View Properties" };
1055 MenuPlacement { viewMenu, $"View Methods" };
1056 MenuItem viewDesignerItem
1058 viewMenu, $"View Designer", d, f8;
1059 bool NotifySelect(MenuItem selection, Modifiers mods)
1061 Window client = activeClient;
1062 Class dataType = client._class;
1063 if(!strcmp(dataType.name, "Designer"))
1065 client.visible = true;
1069 ((CodeEditor)client).ViewDesigner();
1073 MenuItem viewCodeItem
1075 viewMenu, $"View Code", c, f8;
1076 bool NotifySelect(MenuItem selection, Modifiers mods)
1078 Window client = activeClient;
1079 Class dataType = client._class;
1080 if(!strcmp(dataType.name, "Designer"))
1081 client = ((Designer)client).codeEditor;
1084 // Do this after so the caret isn't moved yet...
1085 client.visible = true;
1089 MenuItem viewPropertiesItem
1091 viewMenu, $"View Properties", p, f4;
1092 bool NotifySelect(MenuItem selection, Modifiers mods)
1094 sheet.visible = true;
1095 sheet.sheetSelected = properties;
1100 MenuItem viewMethodsItem
1102 viewMenu, $"View Methods", m, f4;
1103 bool NotifySelect(MenuItem selection, Modifiers mods)
1105 sheet.visible = true;
1106 sheet.sheetSelected = methods;
1111 MenuItem viewToolBoxItem
1113 viewMenu, $"View Toolbox", x, f12;
1114 bool NotifySelect(MenuItem selection, Modifiers mods)
1116 toolBox.visible = true;
1121 MenuItem viewOutputItem
1123 viewMenu, $"Output", o, alt2;
1124 bool NotifySelect(MenuItem selection, Modifiers mods)
1130 MenuItem viewWatchesItem
1132 viewMenu, $"Watches", w, alt3;
1133 bool NotifySelect(MenuItem selection, Modifiers mods)
1139 MenuItem viewThreadsItem
1141 viewMenu, $"Threads", t, alt4;
1142 bool NotifySelect(MenuItem selection, Modifiers mods)
1148 MenuItem viewBreakpointsItem
1150 viewMenu, $"Breakpoints", b, alt5;
1151 bool NotifySelect(MenuItem selection, Modifiers mods)
1153 breakpointsView.Show();
1157 MenuItem viewCallStackItem
1159 viewMenu, $"Call Stack", s, alt7;
1160 bool NotifySelect(MenuItem selection, Modifiers mods)
1162 callStackView.Show();
1166 MenuItem viewAllDebugViews
1168 viewMenu, $"All Debug Views", a, alt9;
1169 bool NotifySelect(MenuItem selection, Modifiers mods)
1174 callStackView.Show();
1175 breakpointsView.Show();
1179 #ifdef GDB_DEBUG_GUI
1180 MenuDivider { viewMenu };
1181 MenuItem viewGDBItem
1183 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1184 bool NotifySelect(MenuItem selection, Modifiers mods)
1191 MenuDivider { viewMenu };
1192 MenuItem viewColorPicker
1194 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1195 bool NotifySelect(MenuItem selection, Modifiers mods)
1197 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1198 colorPicker.Create();
1202 MenuDivider { viewMenu };
1206 viewMenu, "Full Screen", f, checkable = true;
1208 bool NotifySelect(MenuItem selection, Modifiers mods)
1210 app.fullScreen ^= true;
1212 anchor = { 0, 0, 0, 0 };
1217 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1218 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1219 Menu windowMenu { menu, $"Window", w };
1220 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1221 MenuDivider { windowMenu };
1222 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1223 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1224 MenuDivider { windowMenu };
1225 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1226 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1227 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1228 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1229 MenuDivider { windowMenu };
1230 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1231 Menu helpMenu { menu, $"Help", h };
1234 helpMenu, $"API Reference", r, f1;
1235 bool NotifySelect(MenuItem selection, Modifiers mods)
1237 Execute("documentor");
1241 MenuDivider { helpMenu };
1244 helpMenu, $"About...", a;
1245 bool NotifySelect(MenuItem selection, Modifiers mods)
1247 AboutIDE { master = this }.Modal();
1252 property ToolBox toolBox
1254 get { return toolBox; }
1257 property Sheet sheet
1259 get { return sheet; }
1262 property Project project
1264 get { return projectView ? projectView.project : null; }
1267 property Workspace workspace
1269 get { return projectView ? projectView.workspace : null; }
1272 FindInFilesDialog findInFilesDialog
1274 master = this, parent = this;
1275 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1279 #ifdef GDB_DEBUG_GUI
1282 master = this, parent = this;
1283 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1285 void OnCommand(char * string)
1288 ide.debugger.SendGDBCommand(string);
1293 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1295 //app.driver = app.drivers[selection.id];
1297 app.driver = selection.id ? "OpenGL" : "X";
1299 app.driver = selection.id ? "OpenGL" : "GDI";
1301 delete ideSettings.displayDriver;
1302 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1304 settingsContainer.Save();
1305 //SetDriverAndSkin();
1309 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1311 app.skin = app.skins[selection.id];
1316 void SetDriverAndSkin()
1319 for(c = 0; c < app.numSkins; c++)
1320 if(!strcmp(app.skins[c], app.skin))
1322 skinItems[c].checked = true;
1325 for(c = 0; c < app.numDrivers; c++)
1326 if(!strcmp(app.drivers[c], app.driver))
1328 driverItems[c].checked = true;
1333 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1335 Project project = workspace.projects.firstIterator.data;
1336 projectView = ProjectView
1339 fileName = fileName;
1341 void NotifyDestroyed(Window window, DialogResult result)
1344 text = titleECEREIDE;
1349 projectView.Create();
1350 RepositionWindows(false);
1352 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1353 projectView.workspace = workspace;
1354 projectView.project = project;
1355 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1359 ide.breakpointsView.LoadFromWorkspace();
1360 ide.watchesView.LoadFromWorkspace();
1362 findInFilesDialog.projectNodeField.userData = projectView;
1365 char fileName[MAX_LOCATION];
1366 strcpy(fileName, project.topNode.path);
1367 PathCat(fileName, project.topNode.name);
1372 bool GetDebugMenusDisabled()
1376 Project project = projectView.project;
1378 if(project.GetTargetType(project.config) == executable)
1385 void RepositionWindows(bool expand)
1390 bool inDebugMode = debugger.isActive;
1391 bool callStackVisible = expand ? false : callStackView.visible;
1392 bool threadsVisible = expand ? false : threadsView.visible;
1393 bool watchesVisible = expand ? false : watchesView.visible;
1394 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1395 bool toolBoxVisible = toolBox.visible;
1396 bool outputVisible = expand ? false : outputView.visible;
1397 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1398 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1400 for(child = firstChild; child; child = child.next)
1402 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1403 child._class == class(Sheet) || child._class == class(ProjectView))
1405 Anchor anchor = child.anchor;
1406 anchor.top = topDistance;
1407 anchor.bottom = bottomDistance;
1408 if(child._class == class(CodeEditor) || child._class == class(Designer))
1410 anchor.right = toolBoxVisible ? 150 : 0;
1412 child.anchor = anchor;
1416 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1417 child._class == class(BreakpointsView))
1418 child.visible = false;
1421 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1426 bool ShowCodeEditor()
1429 activeClient.Activate();
1430 else if(projectView)
1432 projectView.visible = true;
1433 projectView.Activate();
1437 sheet.visible = true;
1443 bool ShouldStopBuild()
1445 return projectView.stopBuild;
1448 void DocumentSaved(Window document, char * fileName)
1450 ideSettings.AddRecentFile(fileName);
1451 ide.UpdateRecentMenus();
1452 settingsContainer.Save();
1455 bool Window::OnFileModified(FileChange fileChange, char * param)
1458 sprintf(temp, $"The document %s was modified by another application.\n"
1459 "Would you like to reload it and lose your changes?", this.fileName);
1460 if(MessageBox { type = yesNo, master = this/*.parent*/,
1461 text = $"Document has been modified", contents = temp }.Modal() == yes)
1463 char * fileName = CopyString(this.fileName);
1464 WindowState state = this.state;
1465 Anchor anchor = this.anchor;
1466 Size size = this.size;
1468 this.modifiedDocument = false;
1470 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1473 this.anchor = anchor;
1475 this.SetState(state, true, 0);
1483 void UpdateMakefiles()
1487 for(prj : workspace.projects)
1489 bool first = prj == workspace.projects.firstIterator.data;
1490 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1497 bool unavailable = !project;
1499 projectQuickItem.disabled = !unavailable;
1501 projectAddItem.disabled = unavailable;
1503 activeCompilerItem.disabled = unavailable;
1504 projectActiveConfigItem.disabled = unavailable;
1505 projectSettingsItem.disabled = unavailable;
1507 projectBrowseFolderItem.disabled = unavailable;
1509 viewProjectItem.disabled = unavailable;
1515 void AdjustBuildMenus()
1517 bool unavailable = project && projectView.buildInProgress;
1519 projectNewItem.disabled = unavailable;
1520 projectOpenItem.disabled = unavailable;
1522 unavailable = !project || projectView.buildInProgress;
1524 projectCloseItem.disabled = unavailable;
1526 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1527 projectBuildItem.disabled = unavailable;
1528 projectLinkItem.disabled = unavailable;
1529 projectRebuildItem.disabled = unavailable;
1530 projectCleanItem.disabled = unavailable;
1531 projectRegenerateItem.disabled = unavailable;
1532 projectCompileItem.disabled = unavailable;
1535 void AdjustDebugMenus()
1537 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1538 projectView.buildInProgress == buildingMainProject;
1539 bool active = ide.debugger.isActive;
1540 bool executing = ide.debugger.state == running;
1541 //bool holding = ide.debugger.state == stopped;
1543 debugStartResumeItem.disabled = unavailable || executing;
1545 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1546 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1548 debugBreakItem.disabled = unavailable || !executing;
1549 debugStopItem.disabled = unavailable || !active;
1550 debugRestartItem.disabled = unavailable || !active;
1552 debugStepIntoItem.disabled = unavailable || executing;
1553 debugStepOverItem.disabled = unavailable || executing;
1554 debugStepOutItem.disabled = unavailable || executing || !active;
1555 debugSkipStepOverItem.disabled = unavailable || executing;
1556 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1558 if((Designer)GetActiveDesigner())
1560 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1563 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1564 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1569 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1571 char tempString[MAX_LOCATION];
1572 strcpy(tempString, directory);
1573 if(saveSettings && !projectView)
1575 ideSettings.ideFileDialogLocation = directory;
1576 settingsContainer.Save();
1579 ideFileDialog.currentDirectory = tempString;
1580 codeEditorFileDialog.currentDirectory = tempString;
1581 codeEditorFormFileDialog.currentDirectory = tempString;
1584 void ChangeProjectFileDialogDirectory(char * directory)
1586 ideSettings.ideProjectFileDialogLocation = directory;
1587 settingsContainer.Save();
1590 Window FindWindow(char * filePath)
1592 Window document = null;
1594 // TOCHECK: Do we need to change slashes here?
1595 for(document = firstChild; document; document = document.next)
1597 char * fileName = document.fileName;
1598 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1600 document.visible = true;
1601 document.Activate();
1608 bool DontTerminateDebugSession(char * title)
1610 if(debugger.isActive)
1612 if(MessageBox { type = yesNo, master = ide,
1613 contents = $"Do you want to terminate the debugging session in progress?",
1614 text = title }.Modal() == no)
1617 MessageBox msg { type = yesNo, master = ide,
1618 contents = "Do you want to terminate the debugging session in progress?",
1620 if(msg.Modal() == no)
1632 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1634 char extension[MAX_EXTENSION] = "";
1635 Window document = null;
1636 bool isProject = false;
1637 bool needFileModified = true;
1638 char winFilePath[MAX_LOCATION];
1639 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1643 GetExtension(filePath, extension);
1647 strcpy(extension, type);
1649 if(strcmp(extension, ProjectExtension))
1651 for(document = firstChild; document; document = document.next)
1653 char * fileName = document.fileName;
1654 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1656 document.visible = true;
1657 document.Activate();
1663 if(createIfFails == whatever)
1665 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1667 if(openMethod == normal)
1669 if(DontTerminateDebugSession($"Open Project"))
1672 if(MenuWindowCloseAll(null, 0))
1676 projectView.visible = false;
1677 projectView.Destroy(0);
1678 // Where did this come from? projectView = null;
1685 Workspace workspace = null;
1687 if(FileExists(filePath))
1689 if(!strcmp(extension, ProjectExtension))
1691 char workspaceFile[MAX_LOCATION];
1692 strcpy(workspaceFile, filePath);
1693 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1694 workspace = LoadWorkspace(workspaceFile, filePath);
1696 else if(!strcmp(extension, WorkspaceExtension))
1697 workspace = LoadWorkspace(filePath, null);
1700 //project = LoadProject(filePath);
1705 char absolutePath[MAX_LOCATION];
1706 CreateProjectView(workspace, filePath);
1707 document = projectView;
1709 workspace.DropInvalidBreakpoints();
1712 ide.projectView.ShowOutputBuildLog(true);
1714 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1715 ide.projectView.DisplayCompiler(compiler, false);
1720 char newWorkingDir[MAX_LOCATION];
1721 StripLastDirectory(filePath, newWorkingDir);
1722 ChangeFileDialogsDirectory(newWorkingDir, false);
1725 document.fileName = filePath;
1727 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1729 // this crashes on starting ide with epj file, solution please?
1730 // app.UpdateDisplay();
1732 workspace.holdTracking = true;
1733 for(ofi : workspace.openedFiles)
1735 if(ofi.state != closed)
1737 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1740 char fileName[MAX_LOCATION];
1742 GetLastDirectory(ofi.path, fileName);
1743 node = projectView.project.topNode.Find(fileName, true);
1745 node.EnsureVisible();
1749 workspace.holdTracking = false;
1751 workspace.timer.Start();
1753 findInFilesDialog.mode = FindInFilesMode::project;
1754 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1757 char location[MAX_LOCATION];
1758 StripLastDirectory(ide.project.topNode.path, location);
1759 ChangeProjectFileDialogDirectory(location);
1763 if(projectView.debugger)
1764 projectView.debugger.EvaluateWatches();
1771 if(MessageBox { type = yesNo, parent = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1773 ideProjectFileDialog.text = openProjectFileDialogTitle;
1774 if(ideProjectFileDialog.Modal() == cancel)
1776 filePath = ideProjectFileDialog.filePath;
1777 GetExtension(filePath, extension);
1788 else if(openMethod == add)
1793 char slashFilePath[MAX_LOCATION];
1794 GetSlashPathBuffer(slashFilePath, filePath);
1795 for(p : workspace.projects)
1797 if(!fstrcmp(p.filePath, slashFilePath))
1805 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1806 contents = $"This project is already present in workspace." }.Modal();
1810 prj = LoadProject(filePath);
1813 workspace.projects.Add(prj);
1815 projectView.AddNode(prj.topNode, null);
1816 workspace.modified = true;
1818 findInFilesDialog.AddProjectItem(prj);
1819 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1822 char location[MAX_LOCATION];
1823 StripLastDirectory(prj.topNode.path, location);
1824 ChangeProjectFileDialogDirectory(location);
1827 // projectView is associated with the main project and not with the one just added but
1828 return projectView; // just to let the caller know something was opened
1836 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1837 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1838 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1840 if(FileExists(filePath))
1841 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1842 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1843 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1846 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1849 else if(!strcmp(extension, "3ds"))
1851 if(FileExists(filePath))
1852 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1853 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1854 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1858 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1861 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1862 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1863 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1864 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1865 !strcmp(extension, "js"))
1867 CodeEditor editor { parent = this, state = state, visible = false };
1868 editor.updatingCode = true;
1869 if(editor.LoadFile(filePath))
1872 editor.visible = true;
1876 needFileModified = false;
1880 CodeEditor editor { parent = this, state = state, visible = false };
1881 if(editor.LoadFile(filePath))
1884 editor.visible = true;
1888 needFileModified = false;
1891 if(document && (document._class == class(PictureEdit) ||
1892 document._class == class(ModelView)))
1897 document.fileName = filePath;
1898 if(workspace && !workspace.holdTracking)
1899 workspace.UpdateOpenedFileInfo(filePath, opened);
1903 if(!document && createIfFails != no)
1905 if(createIfFails != yes && !needFileModified &&
1906 MessageBox { type = yesNo, parent = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1907 createIfFails = yes;
1908 if(createIfFails == yes || createIfFails == whatever)
1910 document = (Window)NewCodeEditor(this, state, true);
1912 document.fileName = filePath;
1918 if(projectView && document._class == class(CodeEditor) && workspace)
1920 int lineNumber, position;
1922 CodeEditor editor = (CodeEditor)document;
1923 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1924 editor.openedFileInfo.holdTracking = true;
1925 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1926 position = Max(editor.openedFileInfo.position - 1, 0);
1927 editor.editBox.GoToLineNum(lineNumber);
1928 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1929 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1930 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1931 editor.editBox.scroll = scroll;
1932 editor.openedFileInfo.holdTracking = false;
1935 if(needFileModified)
1936 document.OnFileModified = OnFileModified;
1937 document.NotifySaved = DocumentSaved;
1940 ideSettings.AddRecentProject(document.fileName);
1942 ideSettings.AddRecentFile(document.fileName);
1943 ide.UpdateRecentMenus();
1944 settingsContainer.Save();
1952 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
1953 /*bool Window::GenericDocumentOnClose(bool parentClosing)
1955 if(!parentClosing && ide.workspace)
1956 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1959 bool ModelView::ModelViewOnClose(bool parentClosing)
1961 if(!parentClosing && ide.workspace)
1962 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1965 bool PictureEdit::PictureEditOnClose(bool parentClosing)
1967 if(!parentClosing && ide.workspace)
1968 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1973 void OnUnloadGraphics(Window window)
1975 display.ClearMaterials();
1976 display.ClearTextures();
1977 display.ClearMeshes();
1981 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
1983 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1984 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1988 bool OnKeyDown(Key key, unichar ch)
1993 projectView.Update(null);
1996 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1999 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
2005 void GoToError(const char * line)
2008 projectView.GoToError(line);
2011 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
2014 char *colon = strchr(text, ':');
2015 char filePath[MAX_LOCATION];
2016 char completePath[MAX_LOCATION];
2017 int line = 0, col = 0;
2022 char * close = strchr(text, ')');
2026 strncpy(name, &text[4], close - text - 4);
2027 name[close - text - 4] = '\0';
2028 for(p : ide.workspace.projects)
2030 if(!strcmp(p.name, name))
2040 prj = project ? project : (dir ? null : ide.project);
2041 if(colon && (colon[1] == '/' || colon[1] == '\\'))
2043 path = (colon - 1 > path) ? colon - 1 : path;
2044 colon = strstr(colon + 1, ":");
2046 while(isspace(*path)) path++;
2049 strncpy(filePath, path, colon - path);
2050 filePath[colon - path] = '\0';
2051 line = atoi(colon + 1);
2052 colon = strstr(colon + 1, ":");
2054 col = atoi(colon + 1);
2056 else if(path - 1 >= path && *(path - 1) == '\"')
2058 colon = strchr(path, '\"');
2061 strncpy(filePath, path, colon - path);
2062 filePath[colon - path] = '\0';
2067 strcpy(completePath, prj.topNode.path);
2068 else if(dir && dir[0])
2069 strcpy(completePath, dir);
2071 completePath[0] = '\0';
2072 PathCat(completePath, filePath);
2074 if(FileExists(completePath).isFile)
2076 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2077 if(codeEditor && line)
2079 EditBox editBox = codeEditor.editBox;
2080 editBox.GoToLineNum(line - 1);
2081 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2086 void OnRedraw(Surface surface)
2088 Bitmap bitmap = back.bitmap;
2090 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2093 void SheetSelected(SheetType sheetSelected)
2095 if(activeChild == sheet)
2097 if(sheetSelected == methods)
2099 viewPropertiesItem.accelerator = f4;
2100 viewPropertiesItem.parent = viewMenu;
2101 viewMethodsItem.parent = null;
2105 viewMethodsItem.accelerator = f4;
2106 viewMethodsItem.parent = viewMenu;
2107 viewPropertiesItem.parent = null;
2112 viewMethodsItem.parent = viewMenu;
2113 viewPropertiesItem.parent = viewMenu;
2114 if(sheetSelected == methods)
2116 viewMethodsItem.accelerator = f4;
2117 viewPropertiesItem.accelerator = 0;
2121 viewMethodsItem.accelerator = 0;
2122 viewPropertiesItem.accelerator = f4;
2127 void OnActivateClient(Window client, Window previous)
2129 //if(!client || client != previous)
2132 if(!client || client != previous)
2135 dataType = previous._class;
2136 if(previous && !strcmp(dataType.name, "CodeEditor"))
2138 ((CodeEditor)previous).UpdateFormCode();
2140 else if(previous && !strcmp(dataType.name, "Designer"))
2142 ((Designer)previous).codeEditor.UpdateFormCode();
2147 dataType = client._class;
2148 if(client && !strcmp(dataType.name, "CodeEditor"))
2150 CodeEditor codeEditor = (CodeEditor)client;
2151 SetPrivateModule(codeEditor.privateModule);
2152 SetCurrentContext(codeEditor.globalContext);
2153 SetTopContext(codeEditor.globalContext);
2154 SetGlobalContext(codeEditor.globalContext);
2156 SetDefines(&codeEditor.defines);
2157 SetImports(&codeEditor.imports);
2159 SetActiveDesigner(codeEditor.designer);
2161 sheet.codeEditor = codeEditor;
2162 toolBox.codeEditor = codeEditor;
2164 viewDesignerItem.parent = viewMenu;
2165 if(activeChild != codeEditor)
2167 viewCodeItem.parent = viewMenu;
2168 viewDesignerItem.accelerator = 0;
2169 viewCodeItem.accelerator = f8;
2173 viewCodeItem.parent = null;
2174 viewDesignerItem.accelerator = f8;
2177 else if(client && !strcmp(dataType.name, "Designer"))
2179 CodeEditor codeEditor = ((Designer)client).codeEditor;
2182 SetPrivateModule(codeEditor.privateModule);
2183 SetCurrentContext(codeEditor.globalContext);
2184 SetTopContext(codeEditor.globalContext);
2185 SetGlobalContext(codeEditor.globalContext);
2186 SetDefines(&codeEditor.defines);
2187 SetImports(&codeEditor.imports);
2191 SetPrivateModule(null);
2192 SetCurrentContext(null);
2193 SetTopContext(null);
2194 SetGlobalContext(null);
2199 SetActiveDesigner((Designer)client);
2201 sheet.codeEditor = codeEditor;
2202 toolBox.codeEditor = codeEditor;
2204 viewCodeItem.parent = viewMenu;
2205 if(activeChild != client)
2207 viewDesignerItem.parent = viewMenu;
2208 viewDesignerItem.accelerator = f8;
2209 viewCodeItem.accelerator = 0;
2213 viewDesignerItem.parent = null;
2214 viewCodeItem.accelerator = f8;
2220 sheet.codeEditor = null;
2221 toolBox.codeEditor = null;
2222 SetActiveDesigner(null);
2224 viewDesignerItem.parent = null;
2225 viewCodeItem.parent = null;
2228 SheetSelected(sheet.sheetSelected);
2231 projectCompileItem = null;
2236 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2238 CodeEditor codeEditor = (CodeEditor)client;
2239 EditBox editBox = codeEditor.editBox;
2241 statusBar.AddField(pos);
2243 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2244 statusBar.AddField(caps);
2246 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2247 statusBar.AddField(ovr);
2249 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2250 statusBar.AddField(num);
2252 //statusBar.text = "Ready";
2254 if(projectView && projectView.project)
2256 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2260 sprintf(name, $"Compile %s", node.name);
2261 projectCompileItem =
2263 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2265 bool NotifySelect(MenuItem selection, Modifiers mods)
2269 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2271 projectView.Compile(node);
2276 projectMenu.AddDynamic(projectCompileItem, ide, false);
2282 caps = ovr = num = null;
2287 bool OnClose(bool parentClosing)
2289 //return !projectView.buildInProgress;
2290 if(projectView && projectView.buildInProgress)
2292 if(DontTerminateDebugSession($"Close IDE"))
2294 if(findInFilesDialog)
2295 findInFilesDialog.SearchStop();
2298 workspace.timer.Stop();
2301 ideMainFrame.Destroy(0);
2308 for(c = 1; c<app.argc; c++)
2310 char fullPath[MAX_LOCATION];
2311 GetWorkingDir(fullPath, MAX_LOCATION);
2312 PathCat(fullPath, app.argv[c]);
2313 if(FileExists(fullPath))
2314 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2321 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2324 projectView.visible = false;
2325 projectView.Destroy(0);
2328 #ifdef GDB_DEBUG_GUI
2329 gdbDialog.Destroy(0);
2334 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2338 char * oldPaths[128];
2339 String oldList = new char[maxPathLen];
2340 Array<String> newExePaths { };
2341 //Map<String, bool> exePathExists { };
2343 #if defined(__unix__) || defined(__APPLE__)
2344 Array<String> newLibPaths { };
2345 Map<String, bool> libPathExists { };
2350 for(prj : workspace.projects)
2352 DirExpression targetDirExp;
2354 // SKIP FIRST PROJECT...
2355 if(prj == workspace.projects.firstIterator.data) continue;
2357 // NOTE: Right now the additional project config dir will be
2358 // obtained when the debugger is started, so toggling it
2359 // while building will change which library gets used.
2360 // To go with the initial state, e.g. when F5 was pressed,
2361 // we nould need to keep a list of all project's active
2362 // config upon startup.
2363 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2365 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2369 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2370 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2374 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2375 if(cfg.targetType == sharedLibrary && cfg.debug)
2379 if(targetDirExp.dir)
2381 char buffer[MAX_LOCATION];
2382 #if defined(__WIN32__)
2383 Array<String> paths = newExePaths;
2385 Array<String> paths = newLibPaths;
2387 GetSystemPathBuffer(buffer, prj.topNode.path);
2388 PathCat(buffer, targetDirExp.dir);
2391 if(!fstrcmp(p, buffer))
2398 paths.Add(CopyString(buffer));
2400 delete targetDirExp;
2404 for(item : compiler.executableDirs)
2407 for(p : newExePaths)
2409 if(!fstrcmp(p, item))
2416 newExePaths.Add(CopySystemPath(item));
2419 GetEnvironment("PATH", oldList, maxPathLen);
2421 printf("Old value of PATH: %s\n", oldList);
2423 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2424 for(c = 0; c < count; c++)
2427 for(p : newExePaths)
2429 if(!fstrcmp(p, oldPaths[c]))
2436 newExePaths.Add(CopySystemPath(oldPaths[c]));
2440 for(path : newExePaths)
2441 len += strlen(path) + 1;
2442 newList = new char[len + 1];
2444 for(path : newExePaths)
2446 strcat(newList, path);
2447 strcat(newList, pathListSep);
2449 newList[len - 1] = '\0';
2450 SetEnvironment("PATH", newList);
2452 printf("New value of PATH: %s\n", newList);
2459 #if defined(__unix__) || defined(__APPLE__)
2461 for(item : compiler.libraryDirs)
2463 if(!libPathExists[item]) // fstrcmp should be used
2465 newLibPaths.Add(item);
2466 libPathExists[item] = true;
2470 #if defined(__APPLE__)
2471 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2473 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2476 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2478 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2479 for(c = 0; c < count; c++)
2481 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2483 newLibPaths.Add(oldPaths[c]);
2484 libPathExists[oldPaths[c]] = true;
2489 for(path : newLibPaths)
2490 len += strlen(path) + 1;
2491 newList = new char[len + 1];
2493 for(path : newLibPaths)
2495 strcat(newList, path);
2496 strcat(newList, pathListSep);
2498 newList[len - 1] = '\0';
2499 #if defined(__APPLE__)
2500 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2502 SetEnvironment("LD_LIBRARY_PATH", newList);
2505 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2510 delete libPathExists;
2513 if(compiler.distccEnabled && compiler.distccHosts)
2514 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2519 void DestroyTemporaryProjectDir()
2521 if(tmpPrjDir && tmpPrjDir[0])
2523 if(FileExists(tmpPrjDir).isDirectory)
2524 DestroyDir(tmpPrjDir);
2525 property::tmpPrjDir = null;
2531 // Graphics Driver Menu
2535 app.currentSkin.selectionColor = selectionColor;
2536 app.currentSkin.selectionText = selectionText;
2540 driverItems = new MenuItem[app.numDrivers];
2541 for(c = 0; c < app.numDrivers; c++)
2543 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2544 driverItems[c].id = c;
2545 driverItems[c].isRadio = true;
2548 driverItems = new MenuItem[2];
2549 #if defined(__unix__)
2550 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2551 driverItems[0].id = 0;
2552 driverItems[0].isRadio = true;
2554 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2555 driverItems[0].id = 0;
2556 driverItems[0].isRadio = true;
2558 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2559 driverItems[1].id = 1;
2560 driverItems[1].isRadio = true;
2562 /* skinItems = new MenuItem[app.numSkins];
2563 for(c = 0; c < app.numSkins; c++)
2565 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2566 skinItems[c].id = c;
2567 skinItems[c].isRadio = true;
2570 ideFileDialog.master = this;
2571 ideProjectFileDialog.master = this;
2573 //SetDriverAndSkin();
2577 void UpdateRecentMenus()
2580 Menu fileMenu = menu.FindMenu($"File");
2581 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2582 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2583 char itemName[MAX_LOCATION + 4];
2586 recentFiles.Clear();
2589 for(recent : ideSettings.recentFiles)
2591 sprintf(itemName, "%d %s", 1 + c, recent);
2592 MakeSystemPath(itemName);
2593 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2597 recentProjects.Clear();
2599 for(recent : ideSettings.recentProjects)
2601 sprintf(itemName, "%d %s", 1 + c, recent);
2602 MakeSystemPath(itemName);
2603 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2616 void DestroyDir(char * path)
2618 RecursiveDeleteFolderFSI fsi { };
2623 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2625 bool preserveRootFolder;
2627 void OutFolder(char * folderPath, bool isRoot)
2629 if(!(preserveRootFolder && isRoot))
2630 RemoveDir(folderPath);
2633 bool OnFile(char * filePath)
2635 DeleteFile(filePath);
2640 class IDEApp : GuiApplication
2642 //driver = "Win32Console";
2643 // driver = "OpenGL";
2648 SetLoggingMode(stdOut, null);
2649 //SetLoggingMode(debug, null);
2651 settingsContainer.Load();
2652 #if defined(__unix__) || defined(__APPLE__)
2653 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2655 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2657 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2661 desktop.text = titleECEREIDE;
2664 for(c = 1; c<app.argc; c++)
2666 char fullPath[MAX_LOCATION];
2667 GetWorkingDir(fullPath, MAX_LOCATION);
2668 PathCat(fullPath, app.argv[c]);
2669 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2676 IDEMainFrame ideMainFrame { };
2678 define app = ((IDEApp)__thisModule);
2680 define titleECEREIDE = $"ECERE IDE (Debug)";
2682 define titleECEREIDE = $"ECERE IDE";