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;
203 anchor = Anchor { left = 0, right = 0 };
204 clientSize = { h = 32 };
208 class IDEMainFrame : Window
210 background = activeBorder;
211 borderStyle = sizable;
216 minClientSize = { 600, 300 };
217 nativeDecorations = true;
218 borderStyle = sizable;
223 icon = { ":icon.png" };
224 text = titleECEREIDE;
230 isActiveClient = true;
232 direction = vertical;
233 background = activeBorder;
234 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
243 IDEWorkSpace ideWorkSpace { stack, this };
246 define ide = ideMainFrame.ideWorkSpace;
248 class IDEWorkSpace : Window
250 background = Color { 85, 85, 85 };
253 hasVertScroll = true;
254 hasHorzScroll = true;
256 isActiveClient = true;
260 anchor = { top = 0, right = 0, bottom = 0 };
263 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
267 MenuItem * driverItems, * skinItems;
268 StatusField pos { width = 150 };
269 StatusField ovr, caps, num;
271 BitmapResource back { ":ecereBack.jpg", window = this };
272 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
273 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
274 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
275 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
276 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
277 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
278 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
279 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
280 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
281 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
283 Debugger debugger { };
285 ProjectView projectView;
287 OutputView outputView
291 void OnGotoError(char * line)
296 void OnCodeLocationParseAndGoTo(char * line)
298 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
301 bool OnKeyDown(Key key, unichar ch)
306 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
307 ide.ShowCodeEditor();
310 ide.projectView.stopBuild = true;
314 OutputView::OnKeyDown(key, ch);
321 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
324 ide.RepositionWindows(false);
328 bool OnClose(bool parentClosing)
332 ide.RepositionWindows(false);
333 return parentClosing;
337 CallStackView callStackView
339 parent = this, font = { panelFont.faceName, panelFont.size };
341 void OnGotoLine(char * line)
344 stackLvl = atoi(line);
345 ide.debugger.GoToStackFrameLine(stackLvl, true);
348 void OnSelectFrame(int lineNumber)
350 ide.debugger.SelectFrame(lineNumber);
353 void OnToggleBreakpoint()
355 Debugger debugger = ide.debugger;
356 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
358 int line = debugger.activeFrame.line;
359 char name[MAX_LOCATION];
361 // TOFIX: Improve on this, don't use only filename, make a function
362 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
363 if(ide && ide.workspace)
365 for(p : ide.workspace.projects)
367 if(p.topNode.Find(name, false))
375 for(p : ide.workspace.projects)
377 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
385 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
388 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
389 if(codeEditor) { codeEditor.Update(null); Activate(); }
394 bool OnKeyDown(Key key, unichar ch)
398 case escape: ide.ShowCodeEditor(); break;
403 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
406 ide.RepositionWindows(false);
410 bool OnClose(bool parentClosing)
414 ide.RepositionWindows(false);
415 return parentClosing;
418 void OnRedraw(Surface surface)
421 int lineCursor, lineTopFrame, activeThread, hitThread;
422 int lineH, scrollY, boxH;
424 Breakpoint bp = null;
425 Debugger debugger = ide.debugger;
426 Frame activeFrame = debugger.activeFrame;
429 scrollY = editBox.scroll.y;
430 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
432 activeThread = debugger.activeThread;
433 hitThread = debugger.hitThread;
434 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
436 if(activeFrame && activeFrame.absoluteFile)
438 for(i : ide.workspace.breakpoints; i.type == user)
440 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
441 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
442 activeFrame.line == i.line)
451 DrawLineMarginIcon(surface,
452 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
453 lineCursor /*1*/, lineH, scrollY, boxH);
456 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
457 DrawLineMarginIcon(surface,
458 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
459 1, lineH, scrollY, boxH);
461 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
462 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
463 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
465 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
466 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
467 if(editBox.horzScroll && editBox.horzScroll.visible)
469 surface.SetBackground(control);
470 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
475 WatchesView watchesView { parent = this };
476 ThreadsView threadsView
478 parent = this, font = { panelFont.faceName, panelFont.size };
480 bool OnKeyDown(Key key, unichar ch)
484 case escape: ide.ShowCodeEditor(); break;
489 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
492 ide.RepositionWindows(false);
496 bool OnClose(bool parentClosing)
500 ide.RepositionWindows(false);
501 return parentClosing;
504 void OnSelectThread(int threadId)
507 ide.debugger.SelectThread(threadId);
510 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
513 Debugger debugger = ide.debugger;
514 *activeThread = debugger.activeThread;
515 *hitThread = debugger.hitThread;
516 *signalThread = debugger.signalThread;
521 BreakpointsView breakpointsView { parent = this };
523 ToolBox toolBox { parent = this };
524 Sheet sheet { parent = this };
527 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
529 Menu fileMenu { menu, $"File", f };
532 fileMenu, $"New", n, ctrlN;
533 bool NotifySelect(MenuItem selection, Modifiers mods)
535 Window document = (Window)NewCodeEditor(this, normal, false);
536 document.NotifySaved = DocumentSaved;
540 MenuItem fileOpenItem
542 fileMenu, $"Open...", o, ctrlO;
543 bool NotifySelect(MenuItem selection, Modifiers mods)
545 if(!projectView && ideSettings.ideFileDialogLocation)
546 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
549 if(ideFileDialog.Modal() == ok)
551 bool gotWhatWeWant = false;
553 int numSelections = ideFileDialog.numSelections;
554 char ** multiFilePaths = ideFileDialog.multiFilePaths;
556 for(c = 0; c < numSelections; c++)
558 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
559 gotWhatWeWant = true;
562 MessageBox { type = yesNo, master = this, text = $"Error opening file",
563 contents = $"Open a different file?" }.Modal() == no)
565 if(!projectView && gotWhatWeWant)
566 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
576 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
577 MenuDivider { fileMenu };
578 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS };
579 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
580 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll };
581 MenuDivider { fileMenu };
584 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
585 bool NotifySelect(MenuItem selection, Modifiers mods)
587 findInFilesDialog.replaceMode = false;
588 findInFilesDialog.Show();
592 MenuItem replaceInFiles
594 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
595 bool NotifySelect(MenuItem selection, Modifiers mods)
597 findInFilesDialog.replaceMode = true;
598 findInFilesDialog.Show();
602 MenuDivider { fileMenu };
603 MenuItem globalSettingsItem
605 fileMenu, $"Global Settings...", g;
606 bool NotifySelect(MenuItem selection, Modifiers mods)
608 globalSettingsDialog.master = this;
609 if(ide.workspace && ide.workspace.compiler)
610 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
611 else if(ideSettings.defaultCompiler)
612 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
613 globalSettingsDialog.Modal();
617 MenuDivider { fileMenu };
618 Menu recentFiles { fileMenu, $"Recent Files", r };
619 Menu recentProjects { fileMenu, $"Recent Projects", p };
620 MenuDivider { fileMenu };
623 fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit;
625 bool NotifySelect(MenuItem selection, Modifiers mods)
627 ideMainFrame.Destroy(0);
632 bool FileRecentFile(MenuItem selection, Modifiers mods)
635 for(file : ideSettings.recentFiles)
637 if(id == selection.id)
639 OpenFile(file, normal, true, null, no, normal);
647 bool FileRecentProject(MenuItem selection, Modifiers mods)
650 for(file : ideSettings.recentProjects)
652 if(id == selection.id)
654 OpenFile(file, normal, true, null, no, normal);
662 MenuPlacement editMenu { menu, $"Edit", e };
664 Menu projectMenu { menu, $"Menu"."Project", p };
665 MenuItem projectNewItem
667 projectMenu, $"New...", n, Key { n, true, true };
668 bool NotifySelect(MenuItem selection, Modifiers mods)
670 if(!DontTerminateDebugSession($"New Project"))
671 if(MenuWindowCloseAll(null, 0))
673 NewProjectDialog newProjectDialog;
677 projectView.visible = false;
678 if(!projectView.Destroy(0))
682 newProjectDialog = { master = this };
683 newProjectDialog.Modal();
686 ideSettings.AddRecentProject(projectView.fileName);
687 ide.UpdateRecentMenus();
688 settingsContainer.Save();
694 MenuItem projectOpenItem
696 projectMenu, $"Open...", o, Key { o, true, true };
697 bool NotifySelect(MenuItem selection, Modifiers mods)
699 if(ideSettings.ideProjectFileDialogLocation)
700 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
702 ideProjectFileDialog.text = openProjectFileDialogTitle;
703 if(ideProjectFileDialog.Modal() == ok)
705 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
706 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
711 MenuItem projectQuickItem
713 projectMenu, $"Quick...", q, f7;
714 bool NotifySelect(MenuItem selection, Modifiers mods)
717 QuickProjectDialog{ this }.Modal();
721 MenuItem projectAddItem
723 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
725 bool NotifySelect(MenuItem selection, Modifiers mods)
727 if(ideSettings.ideProjectFileDialogLocation)
728 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
730 ideProjectFileDialog.text = addProjectFileDialogTitle;
733 if(ideProjectFileDialog.Modal() == ok)
735 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
737 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
738 contents = $"Add a different project?" }.Modal() == no)
749 MenuItem projectCloseItem
751 projectMenu, $"Close", c, disabled = true;
752 bool NotifySelect(MenuItem selection, Modifiers mods)
756 if(!ide.DontTerminateDebugSession($"Project Close"))
758 if(findInFilesDialog)
759 findInFilesDialog.SearchStop();
760 projectView.visible = false;
761 if(projectView.Destroy(0))
762 MenuWindowCloseAll(null, 0);
764 char workingDir[MAX_LOCATION];
765 GetWorkingDir(workingDir, MAX_LOCATION);
766 findInFilesDialog.currentDirectory = workingDir;
773 MenuDivider { projectMenu };
774 MenuItem activeCompilerItem
776 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
777 bool NotifySelect(MenuItem selection, Modifiers mods)
779 projectView.MenuCompiler(null, mods);
783 MenuItem projectActiveConfigItem
785 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
786 bool NotifySelect(MenuItem selection, Modifiers mods)
788 projectView.MenuConfig(projectView.active ? selection : null, mods);
792 MenuItem projectSettingsItem
794 projectMenu, $"Settings...", s, altF7, disabled = true;
795 bool NotifySelect(MenuItem selection, Modifiers mods)
797 projectView.MenuSettings(projectView.active ? selection : null, mods);
801 MenuDivider { projectMenu };
802 MenuItem projectBrowseFolderItem
804 projectMenu, $"Browse Project Folder", p, disabled = true;
805 bool NotifySelect(MenuItem selection, Modifiers mods)
808 projectView.MenuBrowseFolder(null, mods);
812 MenuDivider { projectMenu };
813 MenuItem projectRunItem
815 projectMenu, $"Run", r, ctrlF5, disabled = true;
816 bool NotifySelect(MenuItem selection, Modifiers mods)
819 projectView.Run(null, mods);
823 MenuItem projectBuildItem
825 projectMenu, $"Build", b, f7, disabled = true;
826 bool NotifySelect(MenuItem selection, Modifiers mods)
829 projectView.ProjectBuild(projectView.active ? selection : null, mods);
833 MenuItem projectLinkItem
835 projectMenu, $"Relink", l, disabled = true;
836 bool NotifySelect(MenuItem selection, Modifiers mods)
839 projectView.ProjectLink(projectView.active ? selection : null, mods);
843 MenuItem projectRebuildItem
845 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
846 bool NotifySelect(MenuItem selection, Modifiers mods)
849 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
853 MenuItem projectCleanItem
855 projectMenu, $"Clean", e, disabled = true;
856 bool NotifySelect(MenuItem selection, Modifiers mods)
861 projectView.ProjectClean(projectView.active ? selection : null, mods);
866 MenuItem projectRegenerateItem
868 projectMenu, $"Regenerate Makefile", m, disabled = true;
869 bool NotifySelect(MenuItem selection, Modifiers mods)
872 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
876 MenuItem projectCompileItem;
877 Menu debugMenu { menu, $"Debug", d };
878 MenuItem debugStartResumeItem
880 debugMenu, $"Start", s, f5, disabled = true;
881 NotifySelect = MenuDebugStart;
883 bool MenuDebugStart(MenuItem selection, Modifiers mods)
887 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
888 if(!projectView.DebugStart())
889 debugStartResumeItem.disabled = false; // same exception
893 bool MenuDebugResume(MenuItem selection, Modifiers mods)
896 projectView.DebugResume();
899 MenuItem debugRestartItem
901 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
902 bool NotifySelect(MenuItem selection, Modifiers mods)
905 projectView.DebugRestart();
909 MenuItem debugBreakItem
911 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
912 bool NotifySelect(MenuItem selection, Modifiers mods)
915 projectView.DebugBreak();
919 MenuItem debugStopItem
921 debugMenu, $"Stop", p, shiftF5, disabled = true;
922 bool NotifySelect(MenuItem selection, Modifiers mods)
925 projectView.DebugStop();
929 MenuDivider { debugMenu };
930 MenuItem debugStepIntoItem
932 debugMenu, $"Step Into", i, f11, disabled = true;
933 bool NotifySelect(MenuItem selection, Modifiers mods)
936 projectView.DebugStepInto();
940 MenuItem debugStepOverItem
942 debugMenu, $"Step Over", v, f10, disabled = true;
943 bool NotifySelect(MenuItem selection, Modifiers mods)
946 projectView.DebugStepOver(false);
950 MenuItem debugStepOutItem
952 debugMenu, $"Step Out", o, shiftF11, disabled = true;
953 bool NotifySelect(MenuItem selection, Modifiers mods)
956 projectView.DebugStepOut(false);
960 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
961 MenuItem debugSkipStepOverItem
963 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
964 bool NotifySelect(MenuItem selection, Modifiers mods)
967 projectView.DebugStepOver(true);
971 MenuItem debugSkipStepOutItem
973 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
974 bool NotifySelect(MenuItem selection, Modifiers mods)
977 projectView.DebugStepOut(true);
981 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
982 //MenuDivider { debugMenu };
983 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
984 MenuPlacement imageMenu { menu, $"Image", i };
985 Menu viewMenu { menu, $"View", v };
986 MenuItem viewProjectItem
988 viewMenu, $"Project View", j, alt0, disabled = true;
989 bool NotifySelect(MenuItem selection, Modifiers mods)
993 projectView.visible = true;
994 projectView.Activate();
999 MenuPlacement { viewMenu, $"View Designer" };
1000 MenuPlacement { viewMenu, $"View Code" };
1001 MenuPlacement { viewMenu, $"View Properties" };
1002 MenuPlacement { viewMenu, $"View Methods" };
1003 MenuItem viewDesignerItem
1005 viewMenu, $"View Designer", d, f8;
1006 bool NotifySelect(MenuItem selection, Modifiers mods)
1008 Window client = activeClient;
1009 Class dataType = client._class;
1010 if(!strcmp(dataType.name, "Designer"))
1012 client.visible = true;
1016 ((CodeEditor)client).ViewDesigner();
1020 MenuItem viewCodeItem
1022 viewMenu, $"View Code", c, f8;
1023 bool NotifySelect(MenuItem selection, Modifiers mods)
1025 Window client = activeClient;
1026 Class dataType = client._class;
1027 if(!strcmp(dataType.name, "Designer"))
1028 client = ((Designer)client).codeEditor;
1031 // Do this after so the caret isn't moved yet...
1032 client.visible = true;
1036 MenuItem viewPropertiesItem
1038 viewMenu, $"View Properties", p, f4;
1039 bool NotifySelect(MenuItem selection, Modifiers mods)
1041 sheet.visible = true;
1042 sheet.sheetSelected = properties;
1047 MenuItem viewMethodsItem
1049 viewMenu, $"View Methods", m, f4;
1050 bool NotifySelect(MenuItem selection, Modifiers mods)
1052 sheet.visible = true;
1053 sheet.sheetSelected = methods;
1058 MenuItem viewToolBoxItem
1060 viewMenu, $"View Toolbox", x, f12;
1061 bool NotifySelect(MenuItem selection, Modifiers mods)
1063 toolBox.visible = true;
1068 MenuItem viewOutputItem
1070 viewMenu, $"Output", o, alt2;
1071 bool NotifySelect(MenuItem selection, Modifiers mods)
1077 MenuItem viewWatchesItem
1079 viewMenu, $"Watches", w, alt3;
1080 bool NotifySelect(MenuItem selection, Modifiers mods)
1086 MenuItem viewThreadsItem
1088 viewMenu, $"Threads", t, alt4;
1089 bool NotifySelect(MenuItem selection, Modifiers mods)
1095 MenuItem viewBreakpointsItem
1097 viewMenu, $"Breakpoints", b, alt5;
1098 bool NotifySelect(MenuItem selection, Modifiers mods)
1100 breakpointsView.Show();
1104 MenuItem viewCallStackItem
1106 viewMenu, $"Call Stack", s, alt7;
1107 bool NotifySelect(MenuItem selection, Modifiers mods)
1109 callStackView.Show();
1113 MenuItem viewAllDebugViews
1115 viewMenu, $"All Debug Views", a, alt9;
1116 bool NotifySelect(MenuItem selection, Modifiers mods)
1121 callStackView.Show();
1122 breakpointsView.Show();
1126 #ifdef GDB_DEBUG_GUI
1127 MenuDivider { viewMenu };
1128 MenuItem viewGDBItem
1130 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1131 bool NotifySelect(MenuItem selection, Modifiers mods)
1138 MenuDivider { viewMenu };
1139 MenuItem viewColorPicker
1141 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1142 bool NotifySelect(MenuItem selection, Modifiers mods)
1144 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1145 colorPicker.Create();
1149 MenuDivider { viewMenu };
1153 viewMenu, "Full Screen", f, checkable = true;
1155 bool NotifySelect(MenuItem selection, Modifiers mods)
1157 app.fullScreen ^= true;
1159 anchor = { 0, 0, 0, 0 };
1164 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1165 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1166 Menu windowMenu { menu, $"Window", w };
1167 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1168 MenuDivider { windowMenu };
1169 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1170 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1171 MenuDivider { windowMenu };
1172 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1173 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1174 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1175 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1176 MenuDivider { windowMenu };
1177 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1178 Menu helpMenu { menu, $"Help", h };
1181 helpMenu, $"API Reference", r, f1;
1182 bool NotifySelect(MenuItem selection, Modifiers mods)
1184 Execute("documentor");
1188 MenuDivider { helpMenu };
1191 helpMenu, $"About...", a;
1192 bool NotifySelect(MenuItem selection, Modifiers mods)
1194 AboutIDE { master = this }.Modal();
1199 property ToolBox toolBox
1201 get { return toolBox; }
1204 property Sheet sheet
1206 get { return sheet; }
1209 property Project project
1211 get { return projectView ? projectView.project : null; }
1214 property Workspace workspace
1216 get { return projectView ? projectView.workspace : null; }
1219 FindInFilesDialog findInFilesDialog
1221 master = this, parent = this;
1222 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1226 #ifdef GDB_DEBUG_GUI
1229 master = this, parent = this;
1230 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1232 void OnCommand(char * string)
1235 ide.debugger.SendGDBCommand(string);
1240 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1242 //app.driver = app.drivers[selection.id];
1244 app.driver = selection.id ? "OpenGL" : "X";
1246 app.driver = selection.id ? "OpenGL" : "GDI";
1248 delete ideSettings.displayDriver;
1249 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1251 settingsContainer.Save();
1252 //SetDriverAndSkin();
1256 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1258 app.skin = app.skins[selection.id];
1263 void SetDriverAndSkin()
1266 for(c = 0; c < app.numSkins; c++)
1267 if(!strcmp(app.skins[c], app.skin))
1269 skinItems[c].checked = true;
1272 for(c = 0; c < app.numDrivers; c++)
1273 if(!strcmp(app.drivers[c], app.driver))
1275 driverItems[c].checked = true;
1280 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1282 Project project = workspace.projects.firstIterator.data;
1283 projectView = ProjectView
1286 fileName = fileName;
1288 void NotifyDestroyed(Window window, DialogResult result)
1291 text = titleECEREIDE;
1296 projectView.Create();
1297 RepositionWindows(false);
1299 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1300 projectView.workspace = workspace;
1301 projectView.project = project;
1302 ideMainFrame.SetText("%s - %s", project.topNode.name, titleECEREIDE);
1306 ide.breakpointsView.LoadFromWorkspace();
1307 ide.watchesView.LoadFromWorkspace();
1309 findInFilesDialog.projectNodeField.userData = projectView;
1312 char fileName[MAX_LOCATION];
1313 strcpy(fileName, project.topNode.path);
1314 PathCat(fileName, project.topNode.name);
1319 bool GetDebugMenusDisabled()
1323 Project project = projectView.project;
1325 if(project.GetTargetType(project.config) == executable)
1332 void RepositionWindows(bool expand)
1337 bool inDebugMode = debugger.isActive;
1338 bool callStackVisible = expand ? false : callStackView.visible;
1339 bool threadsVisible = expand ? false : threadsView.visible;
1340 bool watchesVisible = expand ? false : watchesView.visible;
1341 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1342 bool toolBoxVisible = toolBox.visible;
1343 bool outputVisible = expand ? false : outputView.visible;
1344 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1345 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1347 for(child = firstChild; child; child = child.next)
1349 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1350 child._class == class(Sheet) || child._class == class(ProjectView))
1352 Anchor anchor = child.anchor;
1353 anchor.top = topDistance;
1354 anchor.bottom = bottomDistance;
1355 if(child._class == class(CodeEditor) || child._class == class(Designer))
1357 anchor.right = toolBoxVisible ? 150 : 0;
1359 child.anchor = anchor;
1363 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1364 child._class == class(BreakpointsView))
1365 child.visible = false;
1368 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1373 bool ShowCodeEditor()
1376 activeClient.Activate();
1377 else if(projectView)
1379 projectView.visible = true;
1380 projectView.Activate();
1384 sheet.visible = true;
1390 bool ShouldStopBuild()
1392 return projectView.stopBuild;
1395 void DocumentSaved(Window document, char * fileName)
1397 ideSettings.AddRecentFile(fileName);
1398 ide.UpdateRecentMenus();
1399 settingsContainer.Save();
1402 bool Window::OnFileModified(FileChange fileChange, char * param)
1405 sprintf(temp, $"The document %s was modified by another application.\n"
1406 "Would you like to reload it and lose your changes?", this.fileName);
1407 if(MessageBox { type = yesNo, master = this/*.parent*/,
1408 text = $"Document has been modified", contents = temp }.Modal() == yes)
1410 char * fileName = CopyString(this.fileName);
1411 WindowState state = this.state;
1412 Anchor anchor = this.anchor;
1413 Size size = this.size;
1415 this.modifiedDocument = false;
1417 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1420 this.anchor = anchor;
1422 this.SetState(state, true, 0);
1430 void UpdateMakefiles()
1434 for(prj : workspace.projects)
1436 bool first = prj == workspace.projects.firstIterator.data;
1437 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1444 bool unavailable = !project;
1446 projectQuickItem.disabled = !unavailable;
1448 projectAddItem.disabled = unavailable;
1450 activeCompilerItem.disabled = unavailable;
1451 projectActiveConfigItem.disabled = unavailable;
1452 projectSettingsItem.disabled = unavailable;
1454 projectBrowseFolderItem.disabled = unavailable;
1456 viewProjectItem.disabled = unavailable;
1462 void AdjustBuildMenus()
1464 bool unavailable = project && projectView.buildInProgress;
1466 projectNewItem.disabled = unavailable;
1467 projectOpenItem.disabled = unavailable;
1469 unavailable = !project || projectView.buildInProgress;
1471 projectCloseItem.disabled = unavailable;
1473 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1474 projectBuildItem.disabled = unavailable;
1475 projectLinkItem.disabled = unavailable;
1476 projectRebuildItem.disabled = unavailable;
1477 projectCleanItem.disabled = unavailable;
1478 projectRegenerateItem.disabled = unavailable;
1479 projectCompileItem.disabled = unavailable;
1482 void AdjustDebugMenus()
1484 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1485 projectView.buildInProgress == buildingMainProject;
1486 bool active = ide.debugger.isActive;
1487 bool executing = ide.debugger.state == running;
1488 //bool holding = ide.debugger.state == stopped;
1490 debugStartResumeItem.disabled = unavailable || executing;
1492 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1493 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1495 debugBreakItem.disabled = unavailable || !executing;
1496 debugStopItem.disabled = unavailable || !active;
1497 debugRestartItem.disabled = unavailable || !active;
1499 debugStepIntoItem.disabled = unavailable || executing;
1500 debugStepOverItem.disabled = unavailable || executing;
1501 debugStepOutItem.disabled = unavailable || executing || !active;
1502 debugSkipStepOverItem.disabled = unavailable || executing;
1503 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1505 if((Designer)GetActiveDesigner())
1507 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1510 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1511 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1516 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1518 char tempString[MAX_LOCATION];
1519 strcpy(tempString, directory);
1520 if(saveSettings && !projectView)
1522 ideSettings.ideFileDialogLocation = directory;
1523 settingsContainer.Save();
1526 ideFileDialog.currentDirectory = tempString;
1527 codeEditorFileDialog.currentDirectory = tempString;
1528 codeEditorFormFileDialog.currentDirectory = tempString;
1531 void ChangeProjectFileDialogDirectory(char * directory)
1533 ideSettings.ideProjectFileDialogLocation = directory;
1534 settingsContainer.Save();
1537 Window FindWindow(char * filePath)
1539 Window document = null;
1541 // TOCHECK: Do we need to change slashes here?
1542 for(document = firstChild; document; document = document.next)
1544 char * fileName = document.fileName;
1545 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1547 document.visible = true;
1548 document.Activate();
1555 bool DontTerminateDebugSession(char * title)
1557 if(debugger.isActive)
1559 if(MessageBox { type = yesNo, master = ide,
1560 contents = $"Do you want to terminate the debugging session in progress?",
1561 text = title }.Modal() == no)
1564 MessageBox msg { type = yesNo, master = ide,
1565 contents = "Do you want to terminate the debugging session in progress?",
1567 if(msg.Modal() == no)
1579 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1581 char extension[MAX_EXTENSION] = "";
1582 Window document = null;
1583 bool isProject = false;
1584 bool needFileModified = true;
1585 char winFilePath[MAX_LOCATION];
1586 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1590 GetExtension(filePath, extension);
1594 strcpy(extension, type);
1596 if(strcmp(extension, ProjectExtension))
1598 for(document = firstChild; document; document = document.next)
1600 char * fileName = document.fileName;
1601 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1603 document.visible = true;
1604 document.Activate();
1610 if(createIfFails == whatever)
1612 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1614 if(openMethod == normal)
1616 if(DontTerminateDebugSession($"Open Project"))
1619 if(MenuWindowCloseAll(null, 0))
1623 projectView.visible = false;
1624 projectView.Destroy(0);
1625 // Where did this come from? projectView = null;
1632 Workspace workspace = null;
1634 if(FileExists(filePath))
1636 if(!strcmp(extension, ProjectExtension))
1638 char workspaceFile[MAX_LOCATION];
1639 strcpy(workspaceFile, filePath);
1640 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1641 workspace = LoadWorkspace(workspaceFile, filePath);
1643 else if(!strcmp(extension, WorkspaceExtension))
1644 workspace = LoadWorkspace(filePath, null);
1647 //project = LoadProject(filePath);
1652 char absolutePath[MAX_LOCATION];
1653 CreateProjectView(workspace, filePath);
1654 document = projectView;
1656 workspace.DropInvalidBreakpoints();
1659 ide.projectView.ShowOutputBuildLog(true);
1661 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1662 ide.projectView.DisplayCompiler(compiler, false);
1667 char newWorkingDir[MAX_LOCATION];
1668 StripLastDirectory(filePath, newWorkingDir);
1669 ChangeFileDialogsDirectory(newWorkingDir, false);
1672 document.fileName = filePath;
1674 ideMainFrame.SetText("%s - %s", filePath, titleECEREIDE);
1676 // this crashes on starting ide with epj file, solution please?
1677 // app.UpdateDisplay();
1679 workspace.holdTracking = true;
1680 for(ofi : workspace.openedFiles)
1682 if(ofi.state != closed)
1684 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1687 char fileName[MAX_LOCATION];
1689 GetLastDirectory(ofi.path, fileName);
1690 node = projectView.project.topNode.Find(fileName, true);
1692 node.EnsureVisible();
1696 workspace.holdTracking = false;
1698 workspace.timer.Start();
1700 findInFilesDialog.mode = FindInFilesMode::project;
1701 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1704 char location[MAX_LOCATION];
1705 StripLastDirectory(ide.project.topNode.path, location);
1706 ChangeProjectFileDialogDirectory(location);
1710 if(projectView.debugger)
1711 projectView.debugger.EvaluateWatches();
1718 if(MessageBox { type = yesNo, parent = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1720 ideProjectFileDialog.text = openProjectFileDialogTitle;
1721 if(ideProjectFileDialog.Modal() == cancel)
1723 filePath = ideProjectFileDialog.filePath;
1724 GetExtension(filePath, extension);
1735 else if(openMethod == add)
1740 char slashFilePath[MAX_LOCATION];
1741 GetSlashPathBuffer(slashFilePath, filePath);
1742 for(p : workspace.projects)
1744 if(!fstrcmp(p.filePath, slashFilePath))
1752 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1753 contents = $"This project is already present in workspace." }.Modal();
1757 prj = LoadProject(filePath);
1760 workspace.projects.Add(prj);
1762 projectView.AddNode(prj.topNode, null);
1763 workspace.modified = true;
1765 findInFilesDialog.AddProjectItem(prj);
1766 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1769 char location[MAX_LOCATION];
1770 StripLastDirectory(prj.topNode.path, location);
1771 ChangeProjectFileDialogDirectory(location);
1774 // projectView is associated with the main project and not with the one just added but
1775 return projectView; // just to let the caller know something was opened
1783 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1784 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1785 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1787 if(FileExists(filePath))
1788 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1789 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1790 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1793 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1796 else if(!strcmp(extension, "3ds"))
1798 if(FileExists(filePath))
1799 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1800 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1801 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1805 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1808 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1809 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1810 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1811 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1812 !strcmp(extension, "js"))
1814 CodeEditor editor { parent = this, state = state, visible = false };
1815 editor.updatingCode = true;
1816 if(editor.LoadFile(filePath))
1819 editor.visible = true;
1823 needFileModified = false;
1827 CodeEditor editor { parent = this, state = state, visible = false };
1828 if(editor.LoadFile(filePath))
1831 editor.visible = true;
1835 needFileModified = false;
1838 if(document && (document._class == class(PictureEdit) ||
1839 document._class == class(ModelView)))
1844 document.fileName = filePath;
1845 if(workspace && !workspace.holdTracking)
1846 workspace.UpdateOpenedFileInfo(filePath, opened);
1850 if(!document && createIfFails != no)
1852 if(createIfFails != yes && !needFileModified &&
1853 MessageBox { type = yesNo, parent = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1854 createIfFails = yes;
1855 if(createIfFails == yes || createIfFails == whatever)
1857 document = (Window)NewCodeEditor(this, state, true);
1859 document.fileName = filePath;
1865 if(projectView && document._class == class(CodeEditor) && workspace)
1867 int lineNumber, position;
1869 CodeEditor editor = (CodeEditor)document;
1870 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1871 editor.openedFileInfo.holdTracking = true;
1872 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1873 position = Max(editor.openedFileInfo.position - 1, 0);
1874 editor.editBox.GoToLineNum(lineNumber);
1875 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1876 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1877 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1878 editor.editBox.scroll = scroll;
1879 editor.openedFileInfo.holdTracking = false;
1882 if(needFileModified)
1883 document.OnFileModified = OnFileModified;
1884 document.NotifySaved = DocumentSaved;
1887 ideSettings.AddRecentProject(document.fileName);
1889 ideSettings.AddRecentFile(document.fileName);
1890 ide.UpdateRecentMenus();
1891 settingsContainer.Save();
1899 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
1900 /*bool Window::GenericDocumentOnClose(bool parentClosing)
1902 if(!parentClosing && ide.workspace)
1903 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1906 bool ModelView::ModelViewOnClose(bool parentClosing)
1908 if(!parentClosing && ide.workspace)
1909 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1912 bool PictureEdit::PictureEditOnClose(bool parentClosing)
1914 if(!parentClosing && ide.workspace)
1915 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1920 void OnUnloadGraphics(Window window)
1922 display.ClearMaterials();
1923 display.ClearTextures();
1924 display.ClearMeshes();
1928 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
1930 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1931 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1935 bool OnKeyDown(Key key, unichar ch)
1940 projectView.Update(null);
1943 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1946 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1952 void GoToError(const char * line)
1955 projectView.GoToError(line);
1958 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
1961 char *colon = strchr(text, ':');
1962 char filePath[MAX_LOCATION];
1963 char completePath[MAX_LOCATION];
1964 int line = 0, col = 0;
1969 char * close = strchr(text, ')');
1973 strncpy(name, &text[4], close - text - 4);
1974 name[close - text - 4] = '\0';
1975 for(p : ide.workspace.projects)
1977 if(!strcmp(p.name, name))
1987 prj = project ? project : (dir ? null : ide.project);
1988 if(colon && (colon[1] == '/' || colon[1] == '\\'))
1990 path = (colon - 1 > path) ? colon - 1 : path;
1991 colon = strstr(colon + 1, ":");
1993 while(isspace(*path)) path++;
1996 strncpy(filePath, path, colon - path);
1997 filePath[colon - path] = '\0';
1998 line = atoi(colon + 1);
1999 colon = strstr(colon + 1, ":");
2001 col = atoi(colon + 1);
2003 else if(path - 1 >= path && *(path - 1) == '\"')
2005 colon = strchr(path, '\"');
2008 strncpy(filePath, path, colon - path);
2009 filePath[colon - path] = '\0';
2014 strcpy(completePath, prj.topNode.path);
2015 else if(dir && dir[0])
2016 strcpy(completePath, dir);
2018 completePath[0] = '\0';
2019 PathCat(completePath, filePath);
2021 if(FileExists(completePath).isFile)
2023 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
2024 if(codeEditor && line)
2026 EditBox editBox = codeEditor.editBox;
2027 editBox.GoToLineNum(line - 1);
2028 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
2033 void OnRedraw(Surface surface)
2035 Bitmap bitmap = back.bitmap;
2037 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
2040 void SheetSelected(SheetType sheetSelected)
2042 if(activeChild == sheet)
2044 if(sheetSelected == methods)
2046 viewPropertiesItem.accelerator = f4;
2047 viewPropertiesItem.parent = viewMenu;
2048 viewMethodsItem.parent = null;
2052 viewMethodsItem.accelerator = f4;
2053 viewMethodsItem.parent = viewMenu;
2054 viewPropertiesItem.parent = null;
2059 viewMethodsItem.parent = viewMenu;
2060 viewPropertiesItem.parent = viewMenu;
2061 if(sheetSelected == methods)
2063 viewMethodsItem.accelerator = f4;
2064 viewPropertiesItem.accelerator = 0;
2068 viewMethodsItem.accelerator = 0;
2069 viewPropertiesItem.accelerator = f4;
2074 void OnActivateClient(Window client, Window previous)
2076 //if(!client || client != previous)
2079 if(!client || client != previous)
2082 dataType = previous._class;
2083 if(previous && !strcmp(dataType.name, "CodeEditor"))
2085 ((CodeEditor)previous).UpdateFormCode();
2087 else if(previous && !strcmp(dataType.name, "Designer"))
2089 ((Designer)previous).codeEditor.UpdateFormCode();
2094 dataType = client._class;
2095 if(client && !strcmp(dataType.name, "CodeEditor"))
2097 CodeEditor codeEditor = (CodeEditor)client;
2098 SetPrivateModule(codeEditor.privateModule);
2099 SetCurrentContext(codeEditor.globalContext);
2100 SetTopContext(codeEditor.globalContext);
2101 SetGlobalContext(codeEditor.globalContext);
2103 SetDefines(&codeEditor.defines);
2104 SetImports(&codeEditor.imports);
2106 SetActiveDesigner(codeEditor.designer);
2108 sheet.codeEditor = codeEditor;
2109 toolBox.codeEditor = codeEditor;
2111 viewDesignerItem.parent = viewMenu;
2112 if(activeChild != codeEditor)
2114 viewCodeItem.parent = viewMenu;
2115 viewDesignerItem.accelerator = 0;
2116 viewCodeItem.accelerator = f8;
2120 viewCodeItem.parent = null;
2121 viewDesignerItem.accelerator = f8;
2124 else if(client && !strcmp(dataType.name, "Designer"))
2126 CodeEditor codeEditor = ((Designer)client).codeEditor;
2129 SetPrivateModule(codeEditor.privateModule);
2130 SetCurrentContext(codeEditor.globalContext);
2131 SetTopContext(codeEditor.globalContext);
2132 SetGlobalContext(codeEditor.globalContext);
2133 SetDefines(&codeEditor.defines);
2134 SetImports(&codeEditor.imports);
2138 SetPrivateModule(null);
2139 SetCurrentContext(null);
2140 SetTopContext(null);
2141 SetGlobalContext(null);
2146 SetActiveDesigner((Designer)client);
2148 sheet.codeEditor = codeEditor;
2149 toolBox.codeEditor = codeEditor;
2151 viewCodeItem.parent = viewMenu;
2152 if(activeChild != client)
2154 viewDesignerItem.parent = viewMenu;
2155 viewDesignerItem.accelerator = f8;
2156 viewCodeItem.accelerator = 0;
2160 viewDesignerItem.parent = null;
2161 viewCodeItem.accelerator = f8;
2167 sheet.codeEditor = null;
2168 toolBox.codeEditor = null;
2169 SetActiveDesigner(null);
2171 viewDesignerItem.parent = null;
2172 viewCodeItem.parent = null;
2175 SheetSelected(sheet.sheetSelected);
2178 projectCompileItem = null;
2183 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2185 CodeEditor codeEditor = (CodeEditor)client;
2186 EditBox editBox = codeEditor.editBox;
2188 statusBar.AddField(pos);
2190 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2191 statusBar.AddField(caps);
2193 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2194 statusBar.AddField(ovr);
2196 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2197 statusBar.AddField(num);
2199 //statusBar.text = "Ready";
2201 if(projectView && projectView.project)
2203 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2207 sprintf(name, $"Compile %s", node.name);
2208 projectCompileItem =
2210 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2212 bool NotifySelect(MenuItem selection, Modifiers mods)
2216 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2218 projectView.Compile(node);
2223 projectMenu.AddDynamic(projectCompileItem, ide, false);
2229 caps = ovr = num = null;
2234 bool OnClose(bool parentClosing)
2236 //return !projectView.buildInProgress;
2237 if(projectView && projectView.buildInProgress)
2239 if(DontTerminateDebugSession($"Close IDE"))
2241 if(findInFilesDialog)
2242 findInFilesDialog.SearchStop();
2245 workspace.timer.Stop();
2248 ideMainFrame.Destroy(0);
2255 for(c = 1; c<app.argc; c++)
2257 char fullPath[MAX_LOCATION];
2258 GetWorkingDir(fullPath, MAX_LOCATION);
2259 PathCat(fullPath, app.argv[c]);
2260 if(FileExists(fullPath))
2261 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2268 // IS THIS NEEDED? WASN'T HERE BEFORE... Crashes on getting node's projectView otherwise
2271 projectView.visible = false;
2272 projectView.Destroy(0);
2275 #ifdef GDB_DEBUG_GUI
2276 gdbDialog.Destroy(0);
2281 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2285 char * oldPaths[128];
2286 String oldList = new char[maxPathLen];
2287 Array<String> newExePaths { };
2288 //Map<String, bool> exePathExists { };
2290 #if defined(__unix__) || defined(__APPLE__)
2291 Array<String> newLibPaths { };
2292 Map<String, bool> libPathExists { };
2297 for(prj : workspace.projects)
2299 DirExpression targetDirExp;
2301 // SKIP FIRST PROJECT...
2302 if(prj == workspace.projects.firstIterator.data) continue;
2304 // NOTE: Right now the additional project config dir will be
2305 // obtained when the debugger is started, so toggling it
2306 // while building will change which library gets used.
2307 // To go with the initial state, e.g. when F5 was pressed,
2308 // we nould need to keep a list of all project's active
2309 // config upon startup.
2310 targetDirExp = prj.GetTargetDir(compiler, prj.config);
2312 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2316 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2317 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2321 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2322 if(cfg.targetType == sharedLibrary && cfg.debug)
2326 if(targetDirExp.dir)
2328 char buffer[MAX_LOCATION];
2329 #if defined(__WIN32__)
2330 Array<String> paths = newExePaths;
2332 Array<String> paths = newLibPaths;
2334 GetSystemPathBuffer(buffer, prj.topNode.path);
2335 PathCat(buffer, targetDirExp.dir);
2338 if(!fstrcmp(p, buffer))
2345 paths.Add(CopyString(buffer));
2347 delete targetDirExp;
2351 for(item : compiler.executableDirs)
2354 for(p : newExePaths)
2356 if(!fstrcmp(p, item))
2363 newExePaths.Add(CopySystemPath(item));
2366 GetEnvironment("PATH", oldList, maxPathLen);
2368 printf("Old value of PATH: %s\n", oldList);
2370 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2371 for(c = 0; c < count; c++)
2374 for(p : newExePaths)
2376 if(!fstrcmp(p, oldPaths[c]))
2383 newExePaths.Add(CopySystemPath(oldPaths[c]));
2387 for(path : newExePaths)
2388 len += strlen(path) + 1;
2389 newList = new char[len + 1];
2391 for(path : newExePaths)
2393 strcat(newList, path);
2394 strcat(newList, pathListSep);
2396 newList[len - 1] = '\0';
2397 SetEnvironment("PATH", newList);
2399 printf("New value of PATH: %s\n", newList);
2406 #if defined(__unix__) || defined(__APPLE__)
2408 for(item : compiler.libraryDirs)
2410 if(!libPathExists[item]) // fstrcmp should be used
2412 newLibPaths.Add(item);
2413 libPathExists[item] = true;
2417 #if defined(__APPLE__)
2418 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2420 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2423 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2425 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2426 for(c = 0; c < count; c++)
2428 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2430 newLibPaths.Add(oldPaths[c]);
2431 libPathExists[oldPaths[c]] = true;
2436 for(path : newLibPaths)
2437 len += strlen(path) + 1;
2438 newList = new char[len + 1];
2440 for(path : newLibPaths)
2442 strcat(newList, path);
2443 strcat(newList, pathListSep);
2445 newList[len - 1] = '\0';
2446 #if defined(__APPLE__)
2447 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2449 SetEnvironment("LD_LIBRARY_PATH", newList);
2452 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2457 delete libPathExists;
2460 if(compiler.distccEnabled && compiler.distccHosts)
2461 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2466 void DestroyTemporaryProjectDir()
2468 if(tmpPrjDir && tmpPrjDir[0])
2470 if(FileExists(tmpPrjDir).isDirectory)
2471 DestroyDir(tmpPrjDir);
2472 property::tmpPrjDir = null;
2478 // Graphics Driver Menu
2482 app.currentSkin.selectionColor = selectionColor;
2483 app.currentSkin.selectionText = selectionText;
2487 driverItems = new MenuItem[app.numDrivers];
2488 for(c = 0; c < app.numDrivers; c++)
2490 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2491 driverItems[c].id = c;
2492 driverItems[c].isRadio = true;
2495 driverItems = new MenuItem[2];
2496 #if defined(__unix__)
2497 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2498 driverItems[0].id = 0;
2499 driverItems[0].isRadio = true;
2501 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2502 driverItems[0].id = 0;
2503 driverItems[0].isRadio = true;
2505 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2506 driverItems[1].id = 1;
2507 driverItems[1].isRadio = true;
2509 /* skinItems = new MenuItem[app.numSkins];
2510 for(c = 0; c < app.numSkins; c++)
2512 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2513 skinItems[c].id = c;
2514 skinItems[c].isRadio = true;
2517 ideFileDialog.master = this;
2518 ideProjectFileDialog.master = this;
2520 //SetDriverAndSkin();
2524 void UpdateRecentMenus()
2527 Menu fileMenu = menu.FindMenu($"File");
2528 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2529 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2530 char itemName[MAX_LOCATION + 4];
2533 recentFiles.Clear();
2536 for(recent : ideSettings.recentFiles)
2538 sprintf(itemName, "%d %s", 1 + c, recent);
2539 MakeSystemPath(itemName);
2540 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, ide, true);
2544 recentProjects.Clear();
2546 for(recent : ideSettings.recentProjects)
2548 sprintf(itemName, "%d %s", 1 + c, recent);
2549 MakeSystemPath(itemName);
2550 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, ide, true);
2563 void DestroyDir(char * path)
2565 RecursiveDeleteFolderFSI fsi { };
2570 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2572 bool preserveRootFolder;
2574 void OutFolder(char * folderPath, bool isRoot)
2576 if(!(preserveRootFolder && isRoot))
2577 RemoveDir(folderPath);
2580 bool OnFile(char * filePath)
2582 DeleteFile(filePath);
2587 class IDEApp : GuiApplication
2589 //driver = "Win32Console";
2590 // driver = "OpenGL";
2595 SetLoggingMode(stdOut, null);
2596 //SetLoggingMode(debug, null);
2598 settingsContainer.Load();
2599 #if defined(__unix__) || defined(__APPLE__)
2600 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2602 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2604 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2608 desktop.text = titleECEREIDE;
2611 for(c = 1; c<app.argc; c++)
2613 char fullPath[MAX_LOCATION];
2614 GetWorkingDir(fullPath, MAX_LOCATION);
2615 PathCat(fullPath, app.argv[c]);
2616 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2623 IDEMainFrame ideMainFrame { };
2625 define app = ((IDEApp)__thisModule);
2627 define titleECEREIDE = $"ECERE IDE (Debug)";
2629 define titleECEREIDE = $"ECERE IDE";