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 public class ToolBar : public Stacker
198 direction = horizontal;
199 background = activeBorder;
204 anchor = Anchor { left = 0, right = 0 };
205 clientSize = { h = 32 };
209 class IDEMainFrame : Window
211 background = activeBorder;
212 borderStyle = sizable;
217 minClientSize = { 600, 300 };
218 nativeDecorations = true;
219 borderStyle = sizable;
224 icon = { ":icon.png" };
225 text = titleECEREIDE;
229 anchor = { top = 0, right = 0, bottom = 0 };
232 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
239 isActiveClient = true;
241 direction = vertical;
242 background = activeBorder;
243 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
252 IDEWorkSpace ideWorkSpace { stack, this };
255 define ide = ideMainFrame.ideWorkSpace;
257 class IDEWorkSpace : Window
259 background = Color { 85, 85, 85 };
262 hasVertScroll = true;
263 hasHorzScroll = true;
265 isActiveClient = true;
266 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
269 MenuItem * driverItems, * skinItems;
270 StatusField pos { width = 150 };
271 StatusField ovr, caps, num;
273 BitmapResource back { ":ecereBack.jpg", window = this };
274 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
275 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
276 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
277 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
278 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
279 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
280 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
281 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
282 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
283 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
285 Debugger debugger { };
287 ProjectView projectView;
289 OutputView outputView
293 void OnGotoError(char * line)
298 void OnCodeLocationParseAndGoTo(char * line)
300 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
303 bool OnKeyDown(Key key, unichar ch)
308 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
309 ide.ShowCodeEditor();
312 ide.projectView.stopBuild = true;
316 OutputView::OnKeyDown(key, ch);
323 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
326 ide.RepositionWindows(false);
330 bool OnClose(bool parentClosing)
334 ide.RepositionWindows(false);
335 return parentClosing;
339 CallStackView callStackView
341 parent = this, font = { panelFont.faceName, panelFont.size };
343 void OnGotoLine(char * line)
346 stackLvl = atoi(line);
347 ide.debugger.GoToStackFrameLine(stackLvl, true);
350 void OnSelectFrame(int lineNumber)
352 ide.debugger.SelectFrame(lineNumber);
355 void OnToggleBreakpoint()
357 Debugger debugger = ide.debugger;
358 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
360 int line = debugger.activeFrame.line;
361 char name[MAX_LOCATION];
363 // TOFIX: Improve on this, don't use only filename, make a function
364 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
365 if(ide && ide.workspace)
367 for(p : ide.workspace.projects)
369 if(p.topNode.Find(name, false))
377 for(p : ide.workspace.projects)
379 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
387 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
390 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
391 if(codeEditor) { codeEditor.Update(null); Activate(); }
396 bool OnKeyDown(Key key, unichar ch)
400 case escape: ide.ShowCodeEditor(); break;
405 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
408 ide.RepositionWindows(false);
412 bool OnClose(bool parentClosing)
416 ide.RepositionWindows(false);
417 return parentClosing;
420 void OnRedraw(Surface surface)
423 int lineCursor, lineTopFrame, activeThread, hitThread;
424 int lineH, scrollY, boxH;
426 Breakpoint bp = null;
427 Debugger debugger = ide.debugger;
428 Frame activeFrame = debugger.activeFrame;
431 scrollY = editBox.scroll.y;
432 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
434 activeThread = debugger.activeThread;
435 hitThread = debugger.hitThread;
436 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
438 if(activeFrame && activeFrame.absoluteFile)
440 for(i : ide.workspace.breakpoints; i.type == user)
442 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
443 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
444 activeFrame.line == i.line)
453 DrawLineMarginIcon(surface,
454 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
455 lineCursor /*1*/, lineH, scrollY, boxH);
458 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
459 DrawLineMarginIcon(surface,
460 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
461 1, lineH, scrollY, boxH);
463 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
464 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
465 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
467 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
468 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
469 if(editBox.horzScroll && editBox.horzScroll.visible)
471 surface.SetBackground(control);
472 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
477 WatchesView watchesView { parent = this };
478 ThreadsView threadsView
480 parent = this, font = { panelFont.faceName, panelFont.size };
482 bool OnKeyDown(Key key, unichar ch)
486 case escape: ide.ShowCodeEditor(); break;
491 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
494 ide.RepositionWindows(false);
498 bool OnClose(bool parentClosing)
502 ide.RepositionWindows(false);
503 return parentClosing;
506 void OnSelectThread(int threadId)
509 ide.debugger.SelectThread(threadId);
512 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
515 Debugger debugger = ide.debugger;
516 *activeThread = debugger.activeThread;
517 *hitThread = debugger.hitThread;
518 *signalThread = debugger.signalThread;
523 BreakpointsView breakpointsView { parent = this };
525 ToolBox toolBox { parent = this };
526 Sheet sheet { parent = this };
529 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
531 Menu fileMenu { menu, $"File", f };
534 fileMenu, $"New", n, ctrlN;
535 bool NotifySelect(MenuItem selection, Modifiers mods)
537 Window document = (Window)NewCodeEditor(this, normal, false);
538 document.NotifySaved = DocumentSaved;
542 MenuItem fileOpenItem
544 fileMenu, $"Open...", o, ctrlO;
545 bool NotifySelect(MenuItem selection, Modifiers mods)
547 if(!projectView && ideSettings.ideFileDialogLocation)
548 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
551 if(ideFileDialog.Modal() == ok)
553 bool gotWhatWeWant = false;
555 int numSelections = ideFileDialog.numSelections;
556 char ** multiFilePaths = ideFileDialog.multiFilePaths;
558 for(c = 0; c < numSelections; c++)
560 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
561 gotWhatWeWant = true;
564 MessageBox { type = yesNo, master = this, text = $"Error opening file",
565 contents = $"Open a different file?" }.Modal() == no)
567 if(!projectView && gotWhatWeWant)
568 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
578 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
579 MenuDivider { fileMenu };
580 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS };
581 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
582 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll };
583 MenuDivider { fileMenu };
586 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
587 bool NotifySelect(MenuItem selection, Modifiers mods)
589 findInFilesDialog.replaceMode = false;
590 findInFilesDialog.Show();
594 MenuItem replaceInFiles
596 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
597 bool NotifySelect(MenuItem selection, Modifiers mods)
599 findInFilesDialog.replaceMode = true;
600 findInFilesDialog.Show();
604 MenuDivider { fileMenu };
605 MenuItem globalSettingsItem
607 fileMenu, $"Global Settings...", g;
608 bool NotifySelect(MenuItem selection, Modifiers mods)
610 globalSettingsDialog.master = this;
611 if(ide.workspace && ide.workspace.compiler)
612 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
613 else if(ideSettings.defaultCompiler)
614 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
615 globalSettingsDialog.Modal();
619 MenuDivider { fileMenu };
620 Menu recentFiles { fileMenu, $"Recent Files", r };
621 Menu recentProjects { fileMenu, $"Recent Projects", p };
622 MenuDivider { fileMenu };
625 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
627 bool NotifySelect(MenuItem selection, Modifiers mods)
629 ideMainFrame.Destroy(0);
634 bool FileRecentFile(MenuItem selection, Modifiers mods)
637 for(file : ideSettings.recentFiles)
639 if(id == selection.id)
641 OpenFile(file, normal, true, null, no, normal);
649 bool FileRecentProject(MenuItem selection, Modifiers mods)
652 for(file : ideSettings.recentProjects)
654 if(id == selection.id)
656 OpenFile(file, normal, true, null, no, normal);
664 MenuPlacement editMenu { menu, $"Edit", e };
666 Menu projectMenu { menu, $"Menu"."Project", p };
667 MenuItem projectNewItem
669 projectMenu, $"New...", n, Key { n, true, true };
670 bool NotifySelect(MenuItem selection, Modifiers mods)
672 if(!DontTerminateDebugSession($"New Project"))
673 if(MenuWindowCloseAll(null, 0))
675 NewProjectDialog newProjectDialog;
679 projectView.visible = false;
680 if(!projectView.Destroy(0))
684 newProjectDialog = { master = this };
685 newProjectDialog.Modal();
688 ideSettings.AddRecentProject(projectView.fileName);
689 ide.UpdateRecentMenus();
690 settingsContainer.Save();
696 MenuItem projectOpenItem
698 projectMenu, $"Open...", o, Key { o, true, true };
699 bool NotifySelect(MenuItem selection, Modifiers mods)
701 if(ideSettings.ideProjectFileDialogLocation)
702 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
704 ideProjectFileDialog.text = openProjectFileDialogTitle;
705 if(ideProjectFileDialog.Modal() == ok)
707 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
708 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
713 MenuItem projectQuickItem
715 projectMenu, $"Quick...", q, f7;
716 bool NotifySelect(MenuItem selection, Modifiers mods)
719 QuickProjectDialog{ this }.Modal();
723 MenuItem projectAddItem
725 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
727 bool NotifySelect(MenuItem selection, Modifiers mods)
729 if(ideSettings.ideProjectFileDialogLocation)
730 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
732 ideProjectFileDialog.text = addProjectFileDialogTitle;
735 if(ideProjectFileDialog.Modal() == ok)
737 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
739 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
740 contents = $"Add a different project?" }.Modal() == no)
751 MenuItem projectCloseItem
753 projectMenu, $"Close", c, disabled = true;
754 bool NotifySelect(MenuItem selection, Modifiers mods)
758 if(!ide.DontTerminateDebugSession($"Project Close"))
760 if(findInFilesDialog)
761 findInFilesDialog.SearchStop();
762 projectView.visible = false;
763 if(projectView.Destroy(0))
764 MenuWindowCloseAll(null, 0);
766 char workingDir[MAX_LOCATION];
767 GetWorkingDir(workingDir, MAX_LOCATION);
768 findInFilesDialog.currentDirectory = workingDir;
775 MenuDivider { projectMenu };
776 MenuItem activeCompilerItem
778 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
779 bool NotifySelect(MenuItem selection, Modifiers mods)
781 projectView.MenuCompiler(null, mods);
785 MenuItem projectActiveConfigItem
787 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
788 bool NotifySelect(MenuItem selection, Modifiers mods)
790 projectView.MenuConfig(projectView.active ? selection : null, mods);
794 MenuItem projectSettingsItem
796 projectMenu, $"Settings...", s, altF7, disabled = true;
797 bool NotifySelect(MenuItem selection, Modifiers mods)
799 projectView.MenuSettings(projectView.active ? selection : null, mods);
803 MenuDivider { projectMenu };
804 MenuItem projectBrowseFolderItem
806 projectMenu, $"Browse Project Folder", p, disabled = true;
807 bool NotifySelect(MenuItem selection, Modifiers mods)
810 projectView.MenuBrowseFolder(null, mods);
814 MenuDivider { projectMenu };
815 MenuItem projectRunItem
817 projectMenu, $"Run", r, ctrlF5, disabled = true;
818 bool NotifySelect(MenuItem selection, Modifiers mods)
821 projectView.Run(null, mods);
825 MenuItem projectBuildItem
827 projectMenu, $"Build", b, f7, disabled = true;
828 bool NotifySelect(MenuItem selection, Modifiers mods)
831 projectView.ProjectBuild(projectView.active ? selection : null, mods);
835 MenuItem projectLinkItem
837 projectMenu, $"Relink", l, disabled = true;
838 bool NotifySelect(MenuItem selection, Modifiers mods)
841 projectView.ProjectLink(projectView.active ? selection : null, mods);
845 MenuItem projectRebuildItem
847 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
848 bool NotifySelect(MenuItem selection, Modifiers mods)
851 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
855 MenuItem projectCleanItem
857 projectMenu, $"Clean", e, disabled = true;
858 bool NotifySelect(MenuItem selection, Modifiers mods)
863 projectView.ProjectClean(projectView.active ? selection : null, mods);
868 MenuItem projectRegenerateItem
870 projectMenu, $"Regenerate Makefile", m, disabled = true;
871 bool NotifySelect(MenuItem selection, Modifiers mods)
874 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
878 MenuItem projectCompileItem;
879 Menu debugMenu { menu, $"Debug", d };
880 MenuItem debugStartResumeItem
882 debugMenu, $"Start", s, f5, disabled = true;
883 NotifySelect = MenuDebugStart;
885 bool MenuDebugStart(MenuItem selection, Modifiers mods)
889 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
890 if(!projectView.DebugStart())
891 debugStartResumeItem.disabled = false; // same exception
895 bool MenuDebugResume(MenuItem selection, Modifiers mods)
898 projectView.DebugResume();
901 MenuItem debugRestartItem
903 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
904 bool NotifySelect(MenuItem selection, Modifiers mods)
907 projectView.DebugRestart();
911 MenuItem debugBreakItem
913 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
914 bool NotifySelect(MenuItem selection, Modifiers mods)
917 projectView.DebugBreak();
921 MenuItem debugStopItem
923 debugMenu, $"Stop", p, shiftF5, disabled = true;
924 bool NotifySelect(MenuItem selection, Modifiers mods)
927 projectView.DebugStop();
931 MenuDivider { debugMenu };
932 MenuItem debugStepIntoItem
934 debugMenu, $"Step Into", i, f11, disabled = true;
935 bool NotifySelect(MenuItem selection, Modifiers mods)
938 projectView.DebugStepInto();
942 MenuItem debugStepOverItem
944 debugMenu, $"Step Over", v, f10, disabled = true;
945 bool NotifySelect(MenuItem selection, Modifiers mods)
948 projectView.DebugStepOver(false);
952 MenuItem debugStepOutItem
954 debugMenu, $"Step Out", o, shiftF11, disabled = true;
955 bool NotifySelect(MenuItem selection, Modifiers mods)
958 projectView.DebugStepOut(false);
962 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
963 MenuItem debugSkipStepOverItem
965 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
966 bool NotifySelect(MenuItem selection, Modifiers mods)
969 projectView.DebugStepOver(true);
973 MenuItem debugSkipStepOutItem
975 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
976 bool NotifySelect(MenuItem selection, Modifiers mods)
979 projectView.DebugStepOut(true);
983 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
984 //MenuDivider { debugMenu };
985 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
986 MenuPlacement imageMenu { menu, $"Image", i };
987 Menu viewMenu { menu, $"View", v };
988 MenuItem viewProjectItem
990 viewMenu, $"Project View", j, alt0, disabled = true;
991 bool NotifySelect(MenuItem selection, Modifiers mods)
995 projectView.visible = true;
996 projectView.Activate();
1001 MenuPlacement { viewMenu, $"View Designer" };
1002 MenuPlacement { viewMenu, $"View Code" };
1003 MenuPlacement { viewMenu, $"View Properties" };
1004 MenuPlacement { viewMenu, $"View Methods" };
1005 MenuItem viewDesignerItem
1007 viewMenu, $"View Designer", d, f8;
1008 bool NotifySelect(MenuItem selection, Modifiers mods)
1010 Window client = activeClient;
1011 Class dataType = client._class;
1012 if(!strcmp(dataType.name, "Designer"))
1014 client.visible = true;
1018 ((CodeEditor)client).ViewDesigner();
1022 MenuItem viewCodeItem
1024 viewMenu, $"View Code", c, f8;
1025 bool NotifySelect(MenuItem selection, Modifiers mods)
1027 Window client = activeClient;
1028 Class dataType = client._class;
1029 if(!strcmp(dataType.name, "Designer"))
1030 client = ((Designer)client).codeEditor;
1033 // Do this after so the caret isn't moved yet...
1034 client.visible = true;
1038 MenuItem viewPropertiesItem
1040 viewMenu, $"View Properties", p, f4;
1041 bool NotifySelect(MenuItem selection, Modifiers mods)
1043 sheet.visible = true;
1044 sheet.sheetSelected = properties;
1049 MenuItem viewMethodsItem
1051 viewMenu, $"View Methods", m, f4;
1052 bool NotifySelect(MenuItem selection, Modifiers mods)
1054 sheet.visible = true;
1055 sheet.sheetSelected = methods;
1060 MenuItem viewToolBoxItem
1062 viewMenu, $"View Toolbox", x, f12;
1063 bool NotifySelect(MenuItem selection, Modifiers mods)
1065 toolBox.visible = true;
1070 MenuItem viewOutputItem
1072 viewMenu, $"Output", o, alt2;
1073 bool NotifySelect(MenuItem selection, Modifiers mods)
1079 MenuItem viewWatchesItem
1081 viewMenu, $"Watches", w, alt3;
1082 bool NotifySelect(MenuItem selection, Modifiers mods)
1088 MenuItem viewThreadsItem
1090 viewMenu, $"Threads", t, alt4;
1091 bool NotifySelect(MenuItem selection, Modifiers mods)
1097 MenuItem viewBreakpointsItem
1099 viewMenu, $"Breakpoints", b, alt5;
1100 bool NotifySelect(MenuItem selection, Modifiers mods)
1102 breakpointsView.Show();
1106 MenuItem viewCallStackItem
1108 viewMenu, $"Call Stack", s, alt7;
1109 bool NotifySelect(MenuItem selection, Modifiers mods)
1111 callStackView.Show();
1115 MenuItem viewAllDebugViews
1117 viewMenu, $"All Debug Views", a, alt9;
1118 bool NotifySelect(MenuItem selection, Modifiers mods)
1123 callStackView.Show();
1124 breakpointsView.Show();
1128 #ifdef GDB_DEBUG_GUI
1129 MenuDivider { viewMenu };
1130 MenuItem viewGDBItem
1132 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1133 bool NotifySelect(MenuItem selection, Modifiers mods)
1140 MenuDivider { viewMenu };
1141 MenuItem viewColorPicker
1143 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1144 bool NotifySelect(MenuItem selection, Modifiers mods)
1146 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1147 colorPicker.Create();
1151 MenuDivider { viewMenu };
1155 viewMenu, "Full Screen", f, checkable = true;
1157 bool NotifySelect(MenuItem selection, Modifiers mods)
1159 app.fullScreen ^= true;
1161 anchor = { 0, 0, 0, 0 };
1166 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1167 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1168 Menu windowMenu { menu, $"Window", w };
1169 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1170 MenuDivider { windowMenu };
1171 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1172 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1173 MenuDivider { windowMenu };
1174 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1175 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1176 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1177 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1178 MenuDivider { windowMenu };
1179 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1180 Menu helpMenu { menu, $"Help", h };
1183 helpMenu, $"API Reference", r, f1;
1184 bool NotifySelect(MenuItem selection, Modifiers mods)
1186 Execute("documentor");
1190 MenuDivider { helpMenu };
1193 helpMenu, $"About...", a;
1194 bool NotifySelect(MenuItem selection, Modifiers mods)
1196 AboutIDE { master = this }.Modal();
1201 property ToolBox toolBox
1203 get { return toolBox; }
1206 property Sheet sheet
1208 get { return sheet; }
1211 property Project project
1213 get { return projectView ? projectView.project : null; }
1216 property Workspace workspace
1218 get { return projectView ? projectView.workspace : null; }
1221 FindInFilesDialog findInFilesDialog
1223 master = this, parent = this;
1224 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1228 #ifdef GDB_DEBUG_GUI
1231 master = this, parent = this;
1232 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1234 void OnCommand(char * string)
1237 ide.debugger.SendGDBCommand(string);
1242 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1244 //app.driver = app.drivers[selection.id];
1246 app.driver = selection.id ? "OpenGL" : "X";
1248 app.driver = selection.id ? "OpenGL" : "GDI";
1250 delete ideSettings.displayDriver;
1251 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1253 settingsContainer.Save();
1254 //SetDriverAndSkin();
1258 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1260 app.skin = app.skins[selection.id];
1265 void SetDriverAndSkin()
1268 for(c = 0; c < app.numSkins; c++)
1269 if(!strcmp(app.skins[c], app.skin))
1271 skinItems[c].checked = true;
1274 for(c = 0; c < app.numDrivers; c++)
1275 if(!strcmp(app.drivers[c], app.driver))
1277 driverItems[c].checked = true;
1282 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1284 Project project = workspace.projects.firstIterator.data;
1285 projectView = ProjectView
1288 fileName = fileName;
1290 void NotifyDestroyed(Window window, DialogResult result)
1293 text = titleECEREIDE;
1298 projectView.Create();
1299 RepositionWindows(false);
1301 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1302 projectView.workspace = workspace;
1303 projectView.project = project;
1304 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1308 ide.breakpointsView.LoadFromWorkspace();
1309 ide.watchesView.LoadFromWorkspace();
1311 findInFilesDialog.projectNodeField.userData = projectView;
1314 char fileName[MAX_LOCATION];
1315 strcpy(fileName, project.topNode.path);
1316 PathCat(fileName, project.topNode.name);
1321 bool GetDebugMenusDisabled()
1325 Project project = projectView.project;
1327 if(project.GetTargetType(project.config) == executable)
1334 void RepositionWindows(bool expand)
1339 bool inDebugMode = debugger.isActive;
1340 bool callStackVisible = expand ? false : callStackView.visible;
1341 bool threadsVisible = expand ? false : threadsView.visible;
1342 bool watchesVisible = expand ? false : watchesView.visible;
1343 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1344 bool toolBoxVisible = toolBox.visible;
1345 bool outputVisible = expand ? false : outputView.visible;
1346 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1347 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1349 for(child = firstChild; child; child = child.next)
1351 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1352 child._class == class(Sheet) || child._class == class(ProjectView))
1354 Anchor anchor = child.anchor;
1355 anchor.top = topDistance;
1356 anchor.bottom = bottomDistance;
1357 if(child._class == class(CodeEditor) || child._class == class(Designer))
1359 anchor.right = toolBoxVisible ? 150 : 0;
1361 child.anchor = anchor;
1365 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1366 child._class == class(BreakpointsView))
1367 child.visible = false;
1370 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1375 bool ShowCodeEditor()
1378 activeClient.Activate();
1379 else if(projectView)
1381 projectView.visible = true;
1382 projectView.Activate();
1386 sheet.visible = true;
1392 bool ShouldStopBuild()
1394 return projectView.stopBuild;
1397 void DocumentSaved(Window document, char * fileName)
1399 ideSettings.AddRecentFile(fileName);
1400 ide.UpdateRecentMenus();
1401 settingsContainer.Save();
1404 bool Window::OnFileModified(FileChange fileChange, char * param)
1407 sprintf(temp, $"The document %s was modified by another application.\n"
1408 "Would you like to reload it and lose your changes?", this.fileName);
1409 if(MessageBox { type = yesNo, master = this/*.parent*/,
1410 text = $"Document has been modified", contents = temp }.Modal() == yes)
1412 char * fileName = CopyString(this.fileName);
1413 WindowState state = this.state;
1414 Anchor anchor = this.anchor;
1415 Size size = this.size;
1417 this.modifiedDocument = false;
1419 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1422 this.anchor = anchor;
1424 this.SetState(state, true, 0);
1432 void UpdateMakefiles()
1436 for(prj : workspace.projects)
1438 bool first = prj == workspace.projects.firstIterator.data;
1439 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1446 bool unavailable = !project;
1448 projectQuickItem.disabled = !unavailable;
1450 projectAddItem.disabled = unavailable;
1452 activeCompilerItem.disabled = unavailable;
1453 projectActiveConfigItem.disabled = unavailable;
1454 projectSettingsItem.disabled = unavailable;
1456 projectBrowseFolderItem.disabled = unavailable;
1458 viewProjectItem.disabled = unavailable;
1464 void AdjustBuildMenus()
1466 bool unavailable = project && projectView.buildInProgress;
1468 projectNewItem.disabled = unavailable;
1469 projectOpenItem.disabled = unavailable;
1471 unavailable = !project || projectView.buildInProgress;
1473 projectCloseItem.disabled = unavailable;
1475 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1476 projectBuildItem.disabled = unavailable;
1477 projectLinkItem.disabled = unavailable;
1478 projectRebuildItem.disabled = unavailable;
1479 projectCleanItem.disabled = unavailable;
1480 projectRegenerateItem.disabled = unavailable;
1481 projectCompileItem.disabled = unavailable;
1484 void AdjustDebugMenus()
1486 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1487 projectView.buildInProgress == buildingMainProject;
1488 bool active = ide.debugger.isActive;
1489 bool executing = ide.debugger.state == running;
1490 //bool holding = ide.debugger.state == stopped;
1492 debugStartResumeItem.disabled = unavailable || executing;
1494 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1495 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1497 debugBreakItem.disabled = unavailable || !executing;
1498 debugStopItem.disabled = unavailable || !active;
1499 debugRestartItem.disabled = unavailable || !active;
1501 debugStepIntoItem.disabled = unavailable || executing;
1502 debugStepOverItem.disabled = unavailable || executing;
1503 debugStepOutItem.disabled = unavailable || executing || !active;
1504 debugSkipStepOverItem.disabled = unavailable || executing;
1505 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1507 if((Designer)GetActiveDesigner())
1509 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1512 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1513 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1518 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1520 char tempString[MAX_LOCATION];
1521 strcpy(tempString, directory);
1522 if(saveSettings && !projectView)
1524 ideSettings.ideFileDialogLocation = directory;
1525 settingsContainer.Save();
1528 ideFileDialog.currentDirectory = tempString;
1529 codeEditorFileDialog.currentDirectory = tempString;
1530 codeEditorFormFileDialog.currentDirectory = tempString;
1533 void ChangeProjectFileDialogDirectory(char * directory)
1535 ideSettings.ideProjectFileDialogLocation = directory;
1536 settingsContainer.Save();
1539 Window FindWindow(char * filePath)
1541 Window document = null;
1543 // TOCHECK: Do we need to change slashes here?
1544 for(document = firstChild; document; document = document.next)
1546 char * fileName = document.fileName;
1547 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1549 document.visible = true;
1550 document.Activate();
1557 bool DontTerminateDebugSession(char * title)
1559 if(debugger.isActive)
1561 if(MessageBox { type = yesNo, master = ide,
1562 contents = $"Do you want to terminate the debugging session in progress?",
1563 text = title }.Modal() == no)
1566 MessageBox msg { type = yesNo, master = ide,
1567 contents = "Do you want to terminate the debugging session in progress?",
1569 if(msg.Modal() == no)
1581 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1583 char extension[MAX_EXTENSION] = "";
1584 Window document = null;
1585 bool isProject = false;
1586 bool needFileModified = true;
1587 char winFilePath[MAX_LOCATION];
1588 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1592 GetExtension(filePath, extension);
1596 strcpy(extension, type);
1598 if(strcmp(extension, ProjectExtension))
1600 for(document = firstChild; document; document = document.next)
1602 char * fileName = document.fileName;
1603 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1605 document.visible = true;
1606 document.Activate();
1612 if(createIfFails == whatever)
1614 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1616 if(openMethod == normal)
1618 if(DontTerminateDebugSession($"Open Project"))
1621 if(MenuWindowCloseAll(null, 0))
1625 projectView.visible = false;
1626 projectView.Destroy(0);
1627 // Where did this come from? projectView = null;
1634 Workspace workspace = null;
1636 if(FileExists(filePath))
1638 if(!strcmp(extension, ProjectExtension))
1640 char workspaceFile[MAX_LOCATION];
1641 strcpy(workspaceFile, filePath);
1642 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1643 workspace = LoadWorkspace(workspaceFile, filePath);
1645 else if(!strcmp(extension, WorkspaceExtension))
1646 workspace = LoadWorkspace(filePath, null);
1649 //project = LoadProject(filePath);
1654 char absolutePath[MAX_LOCATION];
1655 CreateProjectView(workspace, filePath);
1656 document = projectView;
1658 workspace.DropInvalidBreakpoints();
1661 ide.projectView.ShowOutputBuildLog(true);
1663 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1664 ide.projectView.DisplayCompiler(compiler, false);
1669 char newWorkingDir[MAX_LOCATION];
1670 StripLastDirectory(filePath, newWorkingDir);
1671 ChangeFileDialogsDirectory(newWorkingDir, false);
1674 document.fileName = filePath;
1676 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1678 // this crashes on starting ide with epj file, solution please?
1679 // app.UpdateDisplay();
1681 workspace.holdTracking = true;
1682 for(ofi : workspace.openedFiles)
1684 if(ofi.state != closed)
1686 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1689 char fileName[MAX_LOCATION];
1691 GetLastDirectory(ofi.path, fileName);
1692 node = projectView.project.topNode.Find(fileName, true);
1694 node.EnsureVisible();
1698 workspace.holdTracking = false;
1700 workspace.timer.Start();
1702 findInFilesDialog.mode = FindInFilesMode::project;
1703 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1706 char location[MAX_LOCATION];
1707 StripLastDirectory(ide.project.topNode.path, location);
1708 ChangeProjectFileDialogDirectory(location);
1712 if(projectView.debugger)
1713 projectView.debugger.EvaluateWatches();
1720 if(MessageBox { type = yesNo, parent = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1722 ideProjectFileDialog.text = openProjectFileDialogTitle;
1723 if(ideProjectFileDialog.Modal() == cancel)
1725 filePath = ideProjectFileDialog.filePath;
1726 GetExtension(filePath, extension);
1737 else if(openMethod == add)
1742 char slashFilePath[MAX_LOCATION];
1743 GetSlashPathBuffer(slashFilePath, filePath);
1744 for(p : workspace.projects)
1746 if(!fstrcmp(p.filePath, slashFilePath))
1754 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1755 contents = $"This project is already present in workspace." }.Modal();
1759 prj = LoadProject(filePath);
1762 workspace.projects.Add(prj);
1764 projectView.AddNode(prj.topNode, null);
1765 workspace.modified = true;
1767 findInFilesDialog.AddProjectItem(prj);
1768 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1771 char location[MAX_LOCATION];
1772 StripLastDirectory(prj.topNode.path, location);
1773 ChangeProjectFileDialogDirectory(location);
1776 // projectView is associated with the main project and not with the one just added but
1777 return projectView; // just to let the caller know something was opened
1785 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1786 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1787 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1789 if(FileExists(filePath))
1790 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1791 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1792 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1795 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1798 else if(!strcmp(extension, "3ds"))
1800 if(FileExists(filePath))
1801 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1802 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1803 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1807 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1810 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1811 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1812 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1813 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1814 !strcmp(extension, "js"))
1816 CodeEditor editor { parent = this, state = state, visible = false };
1817 editor.updatingCode = true;
1818 if(editor.LoadFile(filePath))
1821 editor.visible = true;
1825 needFileModified = false;
1829 CodeEditor editor { parent = this, state = state, visible = false };
1830 if(editor.LoadFile(filePath))
1833 editor.visible = true;
1837 needFileModified = false;
1840 if(document && (document._class == class(PictureEdit) ||
1841 document._class == class(ModelView)))
1846 document.fileName = filePath;
1847 if(workspace && !workspace.holdTracking)
1848 workspace.UpdateOpenedFileInfo(filePath, opened);
1852 if(!document && createIfFails != no)
1854 if(createIfFails != yes && !needFileModified &&
1855 MessageBox { type = yesNo, parent = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1856 createIfFails = yes;
1857 if(createIfFails == yes || createIfFails == whatever)
1859 document = (Window)NewCodeEditor(this, state, true);
1861 document.fileName = filePath;
1867 if(projectView && document._class == class(CodeEditor) && workspace)
1869 int lineNumber, position;
1871 CodeEditor editor = (CodeEditor)document;
1872 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1873 editor.openedFileInfo.holdTracking = true;
1874 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1875 position = Max(editor.openedFileInfo.position - 1, 0);
1876 editor.editBox.GoToLineNum(lineNumber);
1877 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1878 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1879 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1880 editor.editBox.scroll = scroll;
1881 editor.openedFileInfo.holdTracking = false;
1884 if(needFileModified)
1885 document.OnFileModified = OnFileModified;
1886 document.NotifySaved = DocumentSaved;
1889 ideSettings.AddRecentProject(document.fileName);
1891 ideSettings.AddRecentFile(document.fileName);
1892 ide.UpdateRecentMenus();
1893 settingsContainer.Save();
1901 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
1902 /*bool Window::GenericDocumentOnClose(bool parentClosing)
1904 if(!parentClosing && ide.workspace)
1905 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1908 bool ModelView::ModelViewOnClose(bool parentClosing)
1910 if(!parentClosing && ide.workspace)
1911 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1914 bool PictureEdit::PictureEditOnClose(bool parentClosing)
1916 if(!parentClosing && ide.workspace)
1917 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1922 void OnUnloadGraphics(Window window)
1924 display.ClearMaterials();
1925 display.ClearTextures();
1926 display.ClearMeshes();
1930 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
1932 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1933 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1937 bool OnKeyDown(Key key, unichar ch)
1942 projectView.Update(null);
1945 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1948 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1954 void GoToError(const char * line)
1957 projectView.GoToError(line);
1960 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
1963 char *colon = strchr(text, ':');
1964 char filePath[MAX_LOCATION];
1965 char completePath[MAX_LOCATION];
1966 int line = 0, col = 0;
1971 char * close = strchr(text, ')');
1975 strncpy(name, &text[4], close - text - 4);
1976 name[close - text - 4] = '\0';
1977 for(p : ide.workspace.projects)
1979 if(!strcmp(p.name, name))
1989 prj = project ? project : (dir ? null : ide.project);
1990 if(colon && (colon[1] == '/' || colon[1] == '\\'))
1992 path = (colon - 1 > path) ? colon - 1 : path;
1993 colon = strstr(colon + 1, ":");
1995 while(isspace(*path)) path++;
1998 strncpy(filePath, path, colon - path);
1999 filePath[colon - path] = '\0';
2000 line = atoi(colon + 1);
2001 colon = strstr(colon + 1, ":");
2003 col = atoi(colon + 1);
2005 else if(path - 1 >= path && *(path - 1) == '\"')
2007 colon = strchr(path, '\"');
2010 strncpy(filePath, path, colon - path);
2011 filePath[colon - path] = '\0';
2016 strcpy(completePath, prj.topNode.path);
2017 else if(dir && dir[0])
2018 strcpy(completePath, dir);
2020 completePath[0] = '\0';
2021 PathCat(completePath, filePath);
2023 if(FileExists(completePath).isFile)
2025 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2026 if(codeEditor && line)
2028 EditBox editBox = codeEditor.editBox;
2029 editBox.GoToLineNum(line - 1);
2030 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2035 void OnRedraw(Surface surface)
2037 Bitmap bitmap = back.bitmap;
2039 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2042 void SheetSelected(SheetType sheetSelected)
2044 if(activeChild == sheet)
2046 if(sheetSelected == methods)
2048 viewPropertiesItem.accelerator = f4;
2049 viewPropertiesItem.parent = viewMenu;
2050 viewMethodsItem.parent = null;
2054 viewMethodsItem.accelerator = f4;
2055 viewMethodsItem.parent = viewMenu;
2056 viewPropertiesItem.parent = null;
2061 viewMethodsItem.parent = viewMenu;
2062 viewPropertiesItem.parent = viewMenu;
2063 if(sheetSelected == methods)
2065 viewMethodsItem.accelerator = f4;
2066 viewPropertiesItem.accelerator = 0;
2070 viewMethodsItem.accelerator = 0;
2071 viewPropertiesItem.accelerator = f4;
2076 void OnActivateClient(Window client, Window previous)
2078 //if(!client || client != previous)
2081 if(!client || client != previous)
2084 dataType = previous._class;
2085 if(previous && !strcmp(dataType.name, "CodeEditor"))
2087 ((CodeEditor)previous).UpdateFormCode();
2089 else if(previous && !strcmp(dataType.name, "Designer"))
2091 ((Designer)previous).codeEditor.UpdateFormCode();
2096 dataType = client._class;
2097 if(client && !strcmp(dataType.name, "CodeEditor"))
2099 CodeEditor codeEditor = (CodeEditor)client;
2100 SetPrivateModule(codeEditor.privateModule);
2101 SetCurrentContext(codeEditor.globalContext);
2102 SetTopContext(codeEditor.globalContext);
2103 SetGlobalContext(codeEditor.globalContext);
2105 SetDefines(&codeEditor.defines);
2106 SetImports(&codeEditor.imports);
2108 SetActiveDesigner(codeEditor.designer);
2110 sheet.codeEditor = codeEditor;
2111 toolBox.codeEditor = codeEditor;
2113 viewDesignerItem.parent = viewMenu;
2114 if(activeChild != codeEditor)
2116 viewCodeItem.parent = viewMenu;
2117 viewDesignerItem.accelerator = 0;
2118 viewCodeItem.accelerator = f8;
2122 viewCodeItem.parent = null;
2123 viewDesignerItem.accelerator = f8;
2126 else if(client && !strcmp(dataType.name, "Designer"))
2128 CodeEditor codeEditor = ((Designer)client).codeEditor;
2131 SetPrivateModule(codeEditor.privateModule);
2132 SetCurrentContext(codeEditor.globalContext);
2133 SetTopContext(codeEditor.globalContext);
2134 SetGlobalContext(codeEditor.globalContext);
2135 SetDefines(&codeEditor.defines);
2136 SetImports(&codeEditor.imports);
2140 SetPrivateModule(null);
2141 SetCurrentContext(null);
2142 SetTopContext(null);
2143 SetGlobalContext(null);
2148 SetActiveDesigner((Designer)client);
2150 sheet.codeEditor = codeEditor;
2151 toolBox.codeEditor = codeEditor;
2153 viewCodeItem.parent = viewMenu;
2154 if(activeChild != client)
2156 viewDesignerItem.parent = viewMenu;
2157 viewDesignerItem.accelerator = f8;
2158 viewCodeItem.accelerator = 0;
2162 viewDesignerItem.parent = null;
2163 viewCodeItem.accelerator = f8;
2169 sheet.codeEditor = null;
2170 toolBox.codeEditor = null;
2171 SetActiveDesigner(null);
2173 viewDesignerItem.parent = null;
2174 viewCodeItem.parent = null;
2177 SheetSelected(sheet.sheetSelected);
2180 projectCompileItem = null;
2185 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2187 CodeEditor codeEditor = (CodeEditor)client;
2188 EditBox editBox = codeEditor.editBox;
2190 statusBar.AddField(pos);
2192 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2193 statusBar.AddField(caps);
2195 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2196 statusBar.AddField(ovr);
2198 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2199 statusBar.AddField(num);
2201 //statusBar.text = "Ready";
2203 if(projectView && projectView.project)
2205 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2209 sprintf(name, $"Compile %s", node.name);
2210 projectCompileItem =
2212 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2214 bool NotifySelect(MenuItem selection, Modifiers mods)
2218 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2220 projectView.Compile(node);
2225 projectMenu.AddDynamic(projectCompileItem, ide, false);
2231 caps = ovr = num = null;
2236 bool OnClose(bool parentClosing)
2238 //return !projectView.buildInProgress;
2239 if(projectView && projectView.buildInProgress)
2241 if(DontTerminateDebugSession($"Close IDE"))
2243 if(findInFilesDialog)
2244 findInFilesDialog.SearchStop();
2247 workspace.timer.Stop();
2250 ideMainFrame.Destroy(0);
2257 for(c = 1; c<app.argc; c++)
2259 char fullPath[MAX_LOCATION];
2260 GetWorkingDir(fullPath, MAX_LOCATION);
2261 PathCat(fullPath, app.argv[c]);
2262 if(FileExists(fullPath))
2263 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2270 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2273 projectView.visible = false;
2274 projectView.Destroy(0);
2277 #ifdef GDB_DEBUG_GUI
2278 gdbDialog.Destroy(0);
2283 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2287 char * oldPaths[128];
2288 String oldList = new char[maxPathLen];
2289 Array<String> newExePaths { };
2290 //Map<String, bool> exePathExists { };
2292 #if defined(__unix__) || defined(__APPLE__)
2293 Array<String> newLibPaths { };
2294 Map<String, bool> libPathExists { };
2299 for(prj : workspace.projects)
2301 DirExpression targetDirExp;
2303 // SKIP FIRST PROJECT...
2304 if(prj == workspace.projects.firstIterator.data) continue;
2306 // NOTE: Right now the additional project config dir will be
2307 // obtained when the debugger is started, so toggling it
2308 // while building will change which library gets used.
2309 // To go with the initial state, e.g. when F5 was pressed,
2310 // we nould need to keep a list of all project's active
2311 // config upon startup.
2312 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2314 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2318 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2319 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2323 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2324 if(cfg.targetType == sharedLibrary && cfg.debug)
2328 if(targetDirExp.dir)
2330 char buffer[MAX_LOCATION];
2331 #if defined(__WIN32__)
2332 Array<String> paths = newExePaths;
2334 Array<String> paths = newLibPaths;
2336 GetSystemPathBuffer(buffer, prj.topNode.path);
2337 PathCat(buffer, targetDirExp.dir);
2340 if(!fstrcmp(p, buffer))
2347 paths.Add(CopyString(buffer));
2349 delete targetDirExp;
2353 for(item : compiler.executableDirs)
2356 for(p : newExePaths)
2358 if(!fstrcmp(p, item))
2365 newExePaths.Add(CopySystemPath(item));
2368 GetEnvironment("PATH", oldList, maxPathLen);
2370 printf("Old value of PATH: %s\n", oldList);
2372 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2373 for(c = 0; c < count; c++)
2376 for(p : newExePaths)
2378 if(!fstrcmp(p, oldPaths[c]))
2385 newExePaths.Add(CopySystemPath(oldPaths[c]));
2389 for(path : newExePaths)
2390 len += strlen(path) + 1;
2391 newList = new char[len + 1];
2393 for(path : newExePaths)
2395 strcat(newList, path);
2396 strcat(newList, pathListSep);
2398 newList[len - 1] = '\0';
2399 SetEnvironment("PATH", newList);
2401 printf("New value of PATH: %s\n", newList);
2408 #if defined(__unix__) || defined(__APPLE__)
2410 for(item : compiler.libraryDirs)
2412 if(!libPathExists[item]) // fstrcmp should be used
2414 newLibPaths.Add(item);
2415 libPathExists[item] = true;
2419 #if defined(__APPLE__)
2420 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2422 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2425 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2427 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2428 for(c = 0; c < count; c++)
2430 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2432 newLibPaths.Add(oldPaths[c]);
2433 libPathExists[oldPaths[c]] = true;
2438 for(path : newLibPaths)
2439 len += strlen(path) + 1;
2440 newList = new char[len + 1];
2442 for(path : newLibPaths)
2444 strcat(newList, path);
2445 strcat(newList, pathListSep);
2447 newList[len - 1] = '\0';
2448 #if defined(__APPLE__)
2449 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2451 SetEnvironment("LD_LIBRARY_PATH", newList);
2454 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2459 delete libPathExists;
2462 if(compiler.distccEnabled && compiler.distccHosts)
2463 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2468 void DestroyTemporaryProjectDir()
2470 if(tmpPrjDir && tmpPrjDir[0])
2472 if(FileExists(tmpPrjDir).isDirectory)
2473 DestroyDir(tmpPrjDir);
2474 property::tmpPrjDir = null;
2480 // Graphics Driver Menu
2484 app.currentSkin.selectionColor = selectionColor;
2485 app.currentSkin.selectionText = selectionText;
2489 driverItems = new MenuItem[app.numDrivers];
2490 for(c = 0; c < app.numDrivers; c++)
2492 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2493 driverItems[c].id = c;
2494 driverItems[c].isRadio = true;
2497 driverItems = new MenuItem[2];
2498 #if defined(__unix__)
2499 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2500 driverItems[0].id = 0;
2501 driverItems[0].isRadio = true;
2503 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2504 driverItems[0].id = 0;
2505 driverItems[0].isRadio = true;
2507 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2508 driverItems[1].id = 1;
2509 driverItems[1].isRadio = true;
2511 /* skinItems = new MenuItem[app.numSkins];
2512 for(c = 0; c < app.numSkins; c++)
2514 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2515 skinItems[c].id = c;
2516 skinItems[c].isRadio = true;
2519 ideFileDialog.master = this;
2520 ideProjectFileDialog.master = this;
2522 //SetDriverAndSkin();
2526 void UpdateRecentMenus()
2529 Menu fileMenu = menu.FindMenu($"File");
2530 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2531 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2532 char itemName[MAX_LOCATION + 4];
2535 recentFiles.Clear();
2538 for(recent : ideSettings.recentFiles)
2540 sprintf(itemName, "%d %s", 1 + c, recent);
2541 MakeSystemPath(itemName);
2542 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2546 recentProjects.Clear();
2548 for(recent : ideSettings.recentProjects)
2550 sprintf(itemName, "%d %s", 1 + c, recent);
2551 MakeSystemPath(itemName);
2552 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2565 void DestroyDir(char * path)
2567 RecursiveDeleteFolderFSI fsi { };
2572 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2574 bool preserveRootFolder;
2576 void OutFolder(char * folderPath, bool isRoot)
2578 if(!(preserveRootFolder && isRoot))
2579 RemoveDir(folderPath);
2582 bool OnFile(char * filePath)
2584 DeleteFile(filePath);
2589 class IDEApp : GuiApplication
2591 //driver = "Win32Console";
2592 // driver = "OpenGL";
2597 SetLoggingMode(stdOut, null);
2598 //SetLoggingMode(debug, null);
2600 settingsContainer.Load();
2601 #if defined(__unix__) || defined(__APPLE__)
2602 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2604 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2606 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2610 desktop.text = titleECEREIDE;
2613 for(c = 1; c<app.argc; c++)
2615 char fullPath[MAX_LOCATION];
2616 GetWorkingDir(fullPath, MAX_LOCATION);
2617 PathCat(fullPath, app.argv[c]);
2618 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2625 IDEMainFrame ideMainFrame { };
2627 define app = ((IDEApp)__thisModule);
2629 define titleECEREIDE = $"ECERE IDE (Debug)";
2631 define titleECEREIDE = $"ECERE IDE";