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);
198 nativeDecorations = true;
199 icon = { ":icon.png" };
200 text = titleECEREIDE;
201 background = Color { 85, 85, 85 };
202 borderStyle = sizable;
207 hasVertScroll = true;
208 hasHorzScroll = true;
214 anchor = { top = 0, right = 0, bottom = 0 };
217 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
221 MenuItem * driverItems, * skinItems;
222 StatusField pos { width = 150 };
223 StatusField ovr, caps, num;
225 BitmapResource back { ":ecereBack.jpg", window = this };
226 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
227 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
228 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
229 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
230 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
231 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
232 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
233 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
234 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
235 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
237 Debugger debugger { };
239 ProjectView projectView;
241 OutputView outputView
245 void OnGotoError(char * line)
250 void OnCodeLocationParseAndGoTo(char * line)
252 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
255 bool OnKeyDown(Key key, unichar ch)
260 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
261 ide.ShowCodeEditor();
264 ide.projectView.stopBuild = true;
268 OutputView::OnKeyDown(key, ch);
275 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
278 ide.RepositionWindows(false);
282 bool OnClose(bool parentClosing)
286 ide.RepositionWindows(false);
287 return parentClosing;
291 CallStackView callStackView
293 parent = this, font = { panelFont.faceName, panelFont.size };
295 void OnGotoLine(char * line)
298 stackLvl = atoi(line);
299 ide.debugger.GoToStackFrameLine(stackLvl, true);
302 void OnSelectFrame(int lineNumber)
304 ide.debugger.SelectFrame(lineNumber);
307 void OnToggleBreakpoint()
309 Debugger debugger = ide.debugger;
310 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
312 int line = debugger.activeFrame.line;
313 char name[MAX_LOCATION];
315 // TOFIX: Improve on this, don't use only filename, make a function
316 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
317 if(ide && ide.workspace)
319 for(p : ide.workspace.projects)
321 if(p.topNode.Find(name, false))
329 for(p : ide.workspace.projects)
331 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
339 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
342 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
343 if(codeEditor) { codeEditor.Update(null); Activate(); }
348 bool OnKeyDown(Key key, unichar ch)
352 case escape: ide.ShowCodeEditor(); break;
357 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
360 ide.RepositionWindows(false);
364 bool OnClose(bool parentClosing)
368 ide.RepositionWindows(false);
369 return parentClosing;
372 void OnRedraw(Surface surface)
375 int lineCursor, lineTopFrame, activeThread, hitThread;
376 int lineH, scrollY, boxH;
378 Breakpoint bp = null;
379 Debugger debugger = ide.debugger;
380 Frame activeFrame = debugger.activeFrame;
383 scrollY = editBox.scroll.y;
384 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
386 activeThread = debugger.activeThread;
387 hitThread = debugger.hitThread;
388 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
390 if(activeFrame && activeFrame.absoluteFile)
392 for(i : ide.workspace.breakpoints; i.type == user)
394 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
395 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
396 activeFrame.line == i.line)
405 DrawLineMarginIcon(surface,
406 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
407 lineCursor /*1*/, lineH, scrollY, boxH);
410 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
411 DrawLineMarginIcon(surface,
412 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
413 1, lineH, scrollY, boxH);
415 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
416 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
417 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
419 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
420 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
421 if(editBox.horzScroll && editBox.horzScroll.visible)
423 surface.SetBackground(control);
424 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
429 WatchesView watchesView { parent = this };
430 ThreadsView threadsView
432 parent = this, font = { panelFont.faceName, panelFont.size };
434 bool OnKeyDown(Key key, unichar ch)
438 case escape: ide.ShowCodeEditor(); break;
443 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
446 ide.RepositionWindows(false);
450 bool OnClose(bool parentClosing)
454 ide.RepositionWindows(false);
455 return parentClosing;
458 void OnSelectThread(int threadId)
461 ide.debugger.SelectThread(threadId);
464 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
467 Debugger debugger = ide.debugger;
468 *activeThread = debugger.activeThread;
469 *hitThread = debugger.hitThread;
470 *signalThread = debugger.signalThread;
475 BreakpointsView breakpointsView { parent = this };
477 ToolBox toolBox { parent = this };
478 Sheet sheet { parent = this };
481 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
483 Menu fileMenu { menu, $"File", f };
486 fileMenu, $"New", n, ctrlN;
487 bool NotifySelect(MenuItem selection, Modifiers mods)
489 Window document = (Window)NewCodeEditor(this, normal, false);
490 document.NotifySaved = DocumentSaved;
494 MenuItem fileOpenItem
496 fileMenu, $"Open...", o, ctrlO;
497 bool NotifySelect(MenuItem selection, Modifiers mods)
499 if(!projectView && ideSettings.ideFileDialogLocation)
500 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
503 if(ideFileDialog.Modal() == ok)
505 bool gotWhatWeWant = false;
507 int numSelections = ideFileDialog.numSelections;
508 char ** multiFilePaths = ideFileDialog.multiFilePaths;
510 for(c = 0; c < numSelections; c++)
512 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
513 gotWhatWeWant = true;
516 MessageBox { type = yesNo, master = this, text = $"Error opening file",
517 contents = $"Open a different file?" }.Modal() == no)
519 if(!projectView && gotWhatWeWant)
520 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
530 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
531 MenuDivider { fileMenu };
532 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS };
533 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
534 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll };
535 MenuDivider { fileMenu };
538 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
539 bool NotifySelect(MenuItem selection, Modifiers mods)
541 findInFilesDialog.replaceMode = false;
542 findInFilesDialog.Show();
546 MenuItem replaceInFiles
548 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
549 bool NotifySelect(MenuItem selection, Modifiers mods)
551 findInFilesDialog.replaceMode = true;
552 findInFilesDialog.Show();
556 MenuDivider { fileMenu };
557 MenuItem globalSettingsItem
559 fileMenu, $"Global Settings...", g;
560 bool NotifySelect(MenuItem selection, Modifiers mods)
562 globalSettingsDialog.master = this;
563 if(ide.workspace && ide.workspace.compiler)
564 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
565 else if(ideSettings.defaultCompiler)
566 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
567 globalSettingsDialog.Modal();
571 MenuDivider { fileMenu };
572 Menu recentFiles { fileMenu, $"Recent Files", r };
573 Menu recentProjects { fileMenu, $"Recent Projects", p };
574 MenuDivider { fileMenu };
575 MenuItem exitItem { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
577 bool FileRecentFile(MenuItem selection, Modifiers mods)
580 for(file : ideSettings.recentFiles)
582 if(id == selection.id)
584 OpenFile(file, normal, true, null, no, normal);
592 bool FileRecentProject(MenuItem selection, Modifiers mods)
595 for(file : ideSettings.recentProjects)
597 if(id == selection.id)
599 OpenFile(file, normal, true, null, no, normal);
607 MenuPlacement editMenu { menu, $"Edit", e };
609 Menu projectMenu { menu, $"Menu"."Project", p };
610 MenuItem projectNewItem
612 projectMenu, $"New...", n, Key { n, true, true };
613 bool NotifySelect(MenuItem selection, Modifiers mods)
615 if(!DontTerminateDebugSession($"New Project"))
616 if(MenuWindowCloseAll(null, 0))
618 NewProjectDialog newProjectDialog;
622 projectView.visible = false;
623 if(!projectView.Destroy(0))
627 newProjectDialog = { master = this };
628 newProjectDialog.Modal();
631 ideSettings.AddRecentProject(projectView.fileName);
632 ide.UpdateRecentMenus();
633 settingsContainer.Save();
639 MenuItem projectOpenItem
641 projectMenu, $"Open...", o, Key { o, true, true };
642 bool NotifySelect(MenuItem selection, Modifiers mods)
644 if(ideSettings.ideProjectFileDialogLocation)
645 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
647 ideProjectFileDialog.text = openProjectFileDialogTitle;
648 if(ideProjectFileDialog.Modal() == ok)
650 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
651 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
656 MenuItem projectQuickItem
658 projectMenu, $"Quick...", q, f7;
659 bool NotifySelect(MenuItem selection, Modifiers mods)
662 QuickProjectDialog{ this }.Modal();
666 MenuItem projectAddItem
668 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
670 bool NotifySelect(MenuItem selection, Modifiers mods)
672 if(ideSettings.ideProjectFileDialogLocation)
673 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
675 ideProjectFileDialog.text = addProjectFileDialogTitle;
678 if(ideProjectFileDialog.Modal() == ok)
680 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
682 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
683 contents = $"Add a different project?" }.Modal() == no)
694 MenuItem projectCloseItem
696 projectMenu, $"Close", c, disabled = true;
697 bool NotifySelect(MenuItem selection, Modifiers mods)
701 if(!ide.DontTerminateDebugSession($"Project Close"))
703 if(findInFilesDialog)
704 findInFilesDialog.SearchStop();
705 projectView.visible = false;
706 if(projectView.Destroy(0))
707 MenuWindowCloseAll(null, 0);
709 char workingDir[MAX_LOCATION];
710 GetWorkingDir(workingDir, MAX_LOCATION);
711 findInFilesDialog.currentDirectory = workingDir;
718 MenuDivider { projectMenu };
719 MenuItem activeCompilerItem
721 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
722 bool NotifySelect(MenuItem selection, Modifiers mods)
724 projectView.MenuCompiler(null, mods);
728 MenuItem projectActiveConfigItem
730 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
731 bool NotifySelect(MenuItem selection, Modifiers mods)
733 projectView.MenuConfig(projectView.active ? selection : null, mods);
737 MenuItem projectSettingsItem
739 projectMenu, $"Settings...", s, altF7, disabled = true;
740 bool NotifySelect(MenuItem selection, Modifiers mods)
742 projectView.MenuSettings(projectView.active ? selection : null, mods);
746 MenuDivider { projectMenu };
747 MenuItem projectBrowseFolderItem
749 projectMenu, $"Browse Project Folder", p, disabled = true;
750 bool NotifySelect(MenuItem selection, Modifiers mods)
753 projectView.MenuBrowseFolder(null, mods);
757 MenuDivider { projectMenu };
758 MenuItem projectRunItem
760 projectMenu, $"Run", r, ctrlF5, disabled = true;
761 bool NotifySelect(MenuItem selection, Modifiers mods)
764 projectView.Run(null, mods);
768 MenuItem projectBuildItem
770 projectMenu, $"Build", b, f7, disabled = true;
771 bool NotifySelect(MenuItem selection, Modifiers mods)
774 projectView.ProjectBuild(projectView.active ? selection : null, mods);
778 MenuItem projectLinkItem
780 projectMenu, $"Relink", l, disabled = true;
781 bool NotifySelect(MenuItem selection, Modifiers mods)
784 projectView.ProjectLink(projectView.active ? selection : null, mods);
788 MenuItem projectRebuildItem
790 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
791 bool NotifySelect(MenuItem selection, Modifiers mods)
794 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
798 MenuItem projectCleanItem
800 projectMenu, $"Clean", e, disabled = true;
801 bool NotifySelect(MenuItem selection, Modifiers mods)
806 projectView.ProjectClean(projectView.active ? selection : null, mods);
811 MenuItem projectRegenerateItem
813 projectMenu, $"Regenerate Makefile", m, disabled = true;
814 bool NotifySelect(MenuItem selection, Modifiers mods)
817 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
821 MenuItem projectCompileItem;
822 Menu debugMenu { menu, $"Debug", d };
823 MenuItem debugStartResumeItem
825 debugMenu, $"Start", s, f5, disabled = true;
826 NotifySelect = MenuDebugStart;
828 bool MenuDebugStart(MenuItem selection, Modifiers mods)
832 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
833 if(!projectView.DebugStart())
834 debugStartResumeItem.disabled = false; // same exception
838 bool MenuDebugResume(MenuItem selection, Modifiers mods)
841 projectView.DebugResume();
844 MenuItem debugRestartItem
846 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
847 bool NotifySelect(MenuItem selection, Modifiers mods)
850 projectView.DebugRestart();
854 MenuItem debugBreakItem
856 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
857 bool NotifySelect(MenuItem selection, Modifiers mods)
860 projectView.DebugBreak();
864 MenuItem debugStopItem
866 debugMenu, $"Stop", p, shiftF5, disabled = true;
867 bool NotifySelect(MenuItem selection, Modifiers mods)
870 projectView.DebugStop();
874 MenuDivider { debugMenu };
875 MenuItem debugStepIntoItem
877 debugMenu, $"Step Into", i, f11, disabled = true;
878 bool NotifySelect(MenuItem selection, Modifiers mods)
881 projectView.DebugStepInto();
885 MenuItem debugStepOverItem
887 debugMenu, $"Step Over", v, f10, disabled = true;
888 bool NotifySelect(MenuItem selection, Modifiers mods)
891 projectView.DebugStepOver(false);
895 MenuItem debugStepOutItem
897 debugMenu, $"Step Out", o, shiftF11, disabled = true;
898 bool NotifySelect(MenuItem selection, Modifiers mods)
901 projectView.DebugStepOut(false);
905 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
906 MenuItem debugSkipStepOverItem
908 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
909 bool NotifySelect(MenuItem selection, Modifiers mods)
912 projectView.DebugStepOver(true);
916 MenuItem debugSkipStepOutItem
918 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
919 bool NotifySelect(MenuItem selection, Modifiers mods)
922 projectView.DebugStepOut(true);
926 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
927 //MenuDivider { debugMenu };
928 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
929 MenuPlacement imageMenu { menu, $"Image", i };
930 Menu viewMenu { menu, $"View", v };
931 MenuItem viewProjectItem
933 viewMenu, $"Project View", j, alt0, disabled = true;
934 bool NotifySelect(MenuItem selection, Modifiers mods)
938 projectView.visible = true;
939 projectView.Activate();
944 MenuPlacement { viewMenu, $"View Designer" };
945 MenuPlacement { viewMenu, $"View Code" };
946 MenuPlacement { viewMenu, $"View Properties" };
947 MenuPlacement { viewMenu, $"View Methods" };
948 MenuItem viewDesignerItem
950 viewMenu, $"View Designer", d, f8;
951 bool NotifySelect(MenuItem selection, Modifiers mods)
953 Window client = activeClient;
954 Class dataType = client._class;
955 if(!strcmp(dataType.name, "Designer"))
957 client.visible = true;
961 ((CodeEditor)client).ViewDesigner();
965 MenuItem viewCodeItem
967 viewMenu, $"View Code", c, f8;
968 bool NotifySelect(MenuItem selection, Modifiers mods)
970 Window client = activeClient;
971 Class dataType = client._class;
972 if(!strcmp(dataType.name, "Designer"))
973 client = ((Designer)client).codeEditor;
976 // Do this after so the caret isn't moved yet...
977 client.visible = true;
981 MenuItem viewPropertiesItem
983 viewMenu, $"View Properties", p, f4;
984 bool NotifySelect(MenuItem selection, Modifiers mods)
986 sheet.visible = true;
987 sheet.sheetSelected = properties;
992 MenuItem viewMethodsItem
994 viewMenu, $"View Methods", m, f4;
995 bool NotifySelect(MenuItem selection, Modifiers mods)
997 sheet.visible = true;
998 sheet.sheetSelected = methods;
1003 MenuItem viewToolBoxItem
1005 viewMenu, $"View Toolbox", x, f12;
1006 bool NotifySelect(MenuItem selection, Modifiers mods)
1008 toolBox.visible = true;
1013 MenuItem viewOutputItem
1015 viewMenu, $"Output", o, alt2;
1016 bool NotifySelect(MenuItem selection, Modifiers mods)
1022 MenuItem viewWatchesItem
1024 viewMenu, $"Watches", w, alt3;
1025 bool NotifySelect(MenuItem selection, Modifiers mods)
1031 MenuItem viewThreadsItem
1033 viewMenu, $"Threads", t, alt4;
1034 bool NotifySelect(MenuItem selection, Modifiers mods)
1040 MenuItem viewBreakpointsItem
1042 viewMenu, $"Breakpoints", b, alt5;
1043 bool NotifySelect(MenuItem selection, Modifiers mods)
1045 breakpointsView.Show();
1049 MenuItem viewCallStackItem
1051 viewMenu, $"Call Stack", s, alt7;
1052 bool NotifySelect(MenuItem selection, Modifiers mods)
1054 callStackView.Show();
1058 MenuItem viewAllDebugViews
1060 viewMenu, $"All Debug Views", a, alt9;
1061 bool NotifySelect(MenuItem selection, Modifiers mods)
1066 callStackView.Show();
1067 breakpointsView.Show();
1071 #ifdef GDB_DEBUG_GUI
1072 MenuDivider { viewMenu };
1073 MenuItem viewGDBItem
1075 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1076 bool NotifySelect(MenuItem selection, Modifiers mods)
1083 MenuDivider { viewMenu };
1084 MenuItem viewColorPicker
1086 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1087 bool NotifySelect(MenuItem selection, Modifiers mods)
1089 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1090 colorPicker.Create();
1094 MenuDivider { viewMenu };
1098 viewMenu, "Full Screen", f, checkable = true;
1100 bool NotifySelect(MenuItem selection, Modifiers mods)
1102 app.fullScreen ^= true;
1104 anchor = { 0, 0, 0, 0 };
1109 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1110 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1111 Menu windowMenu { menu, $"Window", w };
1112 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1113 MenuDivider { windowMenu };
1114 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1115 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1116 MenuDivider { windowMenu };
1117 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1118 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1119 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1120 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1121 MenuDivider { windowMenu };
1122 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1123 Menu helpMenu { menu, $"Help", h };
1126 helpMenu, $"API Reference", r, f1;
1127 bool NotifySelect(MenuItem selection, Modifiers mods)
1129 Execute("documentor");
1133 MenuDivider { helpMenu };
1136 helpMenu, $"About...", a;
1137 bool NotifySelect(MenuItem selection, Modifiers mods)
1139 AboutIDE { master = this }.Modal();
1144 property ToolBox toolBox
1146 get { return toolBox; }
1149 property Sheet sheet
1151 get { return sheet; }
1154 property Project project
1156 get { return projectView ? projectView.project : null; }
1159 property Workspace workspace
1161 get { return projectView ? projectView.workspace : null; }
1164 FindInFilesDialog findInFilesDialog
1166 master = this, parent = this;
1167 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1171 #ifdef GDB_DEBUG_GUI
1174 master = this, parent = this;
1175 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1177 void OnCommand(char * string)
1180 ide.debugger.SendGDBCommand(string);
1185 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1187 //app.driver = app.drivers[selection.id];
1189 app.driver = selection.id ? "OpenGL" : "X";
1191 app.driver = selection.id ? "OpenGL" : "GDI";
1193 delete ideSettings.displayDriver;
1194 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1196 settingsContainer.Save();
1197 //SetDriverAndSkin();
1201 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1203 app.skin = app.skins[selection.id];
1208 void SetDriverAndSkin()
1211 for(c = 0; c < app.numSkins; c++)
1212 if(!strcmp(app.skins[c], app.skin))
1214 skinItems[c].checked = true;
1217 for(c = 0; c < app.numDrivers; c++)
1218 if(!strcmp(app.drivers[c], app.driver))
1220 driverItems[c].checked = true;
1225 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1227 Project project = workspace.projects.firstIterator.data;
1228 projectView = ProjectView
1231 fileName = fileName;
1233 void NotifyDestroyed(Window window, DialogResult result)
1236 text = titleECEREIDE;
1241 projectView.Create();
1242 RepositionWindows(false);
1244 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1245 projectView.workspace = workspace;
1246 projectView.project = project;
1247 SetText("%s - %s", project.topNode.name, titleECEREIDE);
1251 ide.breakpointsView.LoadFromWorkspace();
1252 ide.watchesView.LoadFromWorkspace();
1254 findInFilesDialog.projectNodeField.userData = projectView;
1257 char fileName[MAX_LOCATION];
1258 strcpy(fileName, project.topNode.path);
1259 PathCat(fileName, project.topNode.name);
1264 bool GetDebugMenusDisabled()
1268 Project project = projectView.project;
1270 if(project.GetTargetType(project.config) == executable)
1277 void RepositionWindows(bool expand)
1282 bool inDebugMode = debugger.isActive;
1283 bool callStackVisible = expand ? false : callStackView.visible;
1284 bool threadsVisible = expand ? false : threadsView.visible;
1285 bool watchesVisible = expand ? false : watchesView.visible;
1286 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1287 bool toolBoxVisible = toolBox.visible;
1288 bool outputVisible = expand ? false : outputView.visible;
1289 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1290 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1292 for(child = firstChild; child; child = child.next)
1294 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1295 child._class == class(Sheet) || child._class == class(ProjectView))
1297 Anchor anchor = child.anchor;
1298 anchor.top = topDistance;
1299 anchor.bottom = bottomDistance;
1300 if(child._class == class(CodeEditor) || child._class == class(Designer))
1302 anchor.right = toolBoxVisible ? 150 : 0;
1304 child.anchor = anchor;
1308 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1309 child._class == class(BreakpointsView))
1310 child.visible = false;
1313 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1318 bool ShowCodeEditor()
1321 activeClient.Activate();
1322 else if(projectView)
1324 projectView.visible = true;
1325 projectView.Activate();
1329 sheet.visible = true;
1335 bool ShouldStopBuild()
1337 return projectView.stopBuild;
1340 void DocumentSaved(Window document, char * fileName)
1342 ideSettings.AddRecentFile(fileName);
1343 ide.UpdateRecentMenus();
1344 settingsContainer.Save();
1347 bool Window::OnFileModified(FileChange fileChange, char * param)
1350 sprintf(temp, $"The document %s was modified by another application.\n"
1351 "Would you like to reload it and lose your changes?", this.fileName);
1352 if(MessageBox { type = yesNo, master = this/*.parent*/,
1353 text = $"Document has been modified", contents = temp }.Modal() == yes)
1355 char * fileName = CopyString(this.fileName);
1356 WindowState state = this.state;
1357 Anchor anchor = this.anchor;
1358 Size size = this.size;
1360 this.modifiedDocument = false;
1362 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1365 this.anchor = anchor;
1367 this.SetState(state, true, 0);
1375 void UpdateMakefiles()
1379 for(prj : workspace.projects)
1381 bool first = prj == workspace.projects.firstIterator.data;
1382 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1389 bool unavailable = !project;
1391 projectQuickItem.disabled = !unavailable;
1393 projectAddItem.disabled = unavailable;
1395 activeCompilerItem.disabled = unavailable;
1396 projectActiveConfigItem.disabled = unavailable;
1397 projectSettingsItem.disabled = unavailable;
1399 projectBrowseFolderItem.disabled = unavailable;
1401 viewProjectItem.disabled = unavailable;
1407 void AdjustBuildMenus()
1409 bool unavailable = project && projectView.buildInProgress;
1411 projectNewItem.disabled = unavailable;
1412 projectOpenItem.disabled = unavailable;
1414 unavailable = !project || projectView.buildInProgress;
1416 projectCloseItem.disabled = unavailable;
1418 projectRunItem.disabled = unavailable || project.GetTargetType(project.config) != executable;
1419 projectBuildItem.disabled = unavailable;
1420 projectLinkItem.disabled = unavailable;
1421 projectRebuildItem.disabled = unavailable;
1422 projectCleanItem.disabled = unavailable;
1423 projectRegenerateItem.disabled = unavailable;
1424 projectCompileItem.disabled = unavailable;
1427 void AdjustDebugMenus()
1429 bool unavailable = !project || project.GetTargetType(project.config) != executable ||
1430 projectView.buildInProgress == buildingMainProject;
1431 bool active = ide.debugger.isActive;
1432 bool executing = ide.debugger.state == running;
1433 //bool holding = ide.debugger.state == stopped;
1435 debugStartResumeItem.disabled = unavailable || executing;
1437 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1438 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1440 debugBreakItem.disabled = unavailable || !executing;
1441 debugStopItem.disabled = unavailable || !active;
1442 debugRestartItem.disabled = unavailable || !active;
1444 debugStepIntoItem.disabled = unavailable || executing;
1445 debugStepOverItem.disabled = unavailable || executing;
1446 debugStepOutItem.disabled = unavailable || executing || !active;
1447 debugSkipStepOverItem.disabled = unavailable || executing;
1448 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1450 if((Designer)GetActiveDesigner())
1452 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1455 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1456 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1461 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1463 char tempString[MAX_LOCATION];
1464 strcpy(tempString, directory);
1465 if(saveSettings && !projectView)
1467 ideSettings.ideFileDialogLocation = directory;
1468 settingsContainer.Save();
1471 ideFileDialog.currentDirectory = tempString;
1472 codeEditorFileDialog.currentDirectory = tempString;
1473 codeEditorFormFileDialog.currentDirectory = tempString;
1476 void ChangeProjectFileDialogDirectory(char * directory)
1478 ideSettings.ideProjectFileDialogLocation = directory;
1479 settingsContainer.Save();
1482 Window FindWindow(char * filePath)
1484 Window document = null;
1486 // TOCHECK: Do we need to change slashes here?
1487 for(document = firstChild; document; document = document.next)
1489 char * fileName = document.fileName;
1490 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1492 document.visible = true;
1493 document.Activate();
1500 bool DontTerminateDebugSession(char * title)
1502 if(debugger.isActive)
1504 if(MessageBox { type = yesNo, master = ide,
1505 contents = $"Do you want to terminate the debugging session in progress?",
1506 text = title }.Modal() == no)
1509 MessageBox msg { type = yesNo, master = ide,
1510 contents = "Do you want to terminate the debugging session in progress?",
1512 if(msg.Modal() == no)
1524 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1526 char extension[MAX_EXTENSION] = "";
1527 Window document = null;
1528 bool isProject = false;
1529 bool needFileModified = true;
1530 char winFilePath[MAX_LOCATION];
1531 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1535 GetExtension(filePath, extension);
1539 strcpy(extension, type);
1541 if(strcmp(extension, ProjectExtension))
1543 for(document = firstChild; document; document = document.next)
1545 char * fileName = document.fileName;
1546 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1548 document.visible = true;
1549 document.Activate();
1555 if(createIfFails == whatever)
1557 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1559 if(openMethod == normal)
1561 if(DontTerminateDebugSession($"Open Project"))
1564 if(MenuWindowCloseAll(null, 0))
1568 projectView.visible = false;
1569 projectView.Destroy(0);
1570 // Where did this come from? projectView = null;
1577 Workspace workspace = null;
1579 if(FileExists(filePath))
1581 if(!strcmp(extension, ProjectExtension))
1583 char workspaceFile[MAX_LOCATION];
1584 strcpy(workspaceFile, filePath);
1585 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1586 workspace = LoadWorkspace(workspaceFile, filePath);
1588 else if(!strcmp(extension, WorkspaceExtension))
1589 workspace = LoadWorkspace(filePath, null);
1592 //project = LoadProject(filePath);
1597 char absolutePath[MAX_LOCATION];
1598 CreateProjectView(workspace, filePath);
1599 document = projectView;
1601 workspace.DropInvalidBreakpoints();
1604 ide.projectView.ShowOutputBuildLog(true);
1606 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1607 ide.projectView.DisplayCompiler(compiler, false);
1612 char newWorkingDir[MAX_LOCATION];
1613 StripLastDirectory(filePath, newWorkingDir);
1614 ChangeFileDialogsDirectory(newWorkingDir, false);
1617 document.fileName = filePath;
1619 SetText("%s - %s", filePath, titleECEREIDE);
1621 // this crashes on starting ide with epj file, solution please?
1622 // app.UpdateDisplay();
1624 workspace.holdTracking = true;
1625 for(ofi : workspace.openedFiles)
1627 if(ofi.state != closed)
1629 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1632 char fileName[MAX_LOCATION];
1634 GetLastDirectory(ofi.path, fileName);
1635 node = projectView.project.topNode.Find(fileName, true);
1637 node.EnsureVisible();
1641 workspace.holdTracking = false;
1643 workspace.timer.Start();
1645 findInFilesDialog.mode = FindInFilesMode::project;
1646 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1649 char location[MAX_LOCATION];
1650 StripLastDirectory(ide.project.topNode.path, location);
1651 ChangeProjectFileDialogDirectory(location);
1655 if(projectView.debugger)
1656 projectView.debugger.EvaluateWatches();
1663 if(MessageBox { type = yesNo, parent = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1665 ideProjectFileDialog.text = openProjectFileDialogTitle;
1666 if(ideProjectFileDialog.Modal() == cancel)
1668 filePath = ideProjectFileDialog.filePath;
1669 GetExtension(filePath, extension);
1680 else if(openMethod == add)
1685 char slashFilePath[MAX_LOCATION];
1686 GetSlashPathBuffer(slashFilePath, filePath);
1687 for(p : workspace.projects)
1689 if(!fstrcmp(p.filePath, slashFilePath))
1697 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1698 contents = $"This project is already present in workspace." }.Modal();
1702 prj = LoadProject(filePath);
1705 workspace.projects.Add(prj);
1707 projectView.AddNode(prj.topNode, null);
1708 workspace.modified = true;
1710 findInFilesDialog.AddProjectItem(prj);
1711 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1714 char location[MAX_LOCATION];
1715 StripLastDirectory(prj.topNode.path, location);
1716 ChangeProjectFileDialogDirectory(location);
1719 // projectView is associated with the main project and not with the one just added but
1720 return projectView; // just to let the caller know something was opened
1728 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1729 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1730 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1732 if(FileExists(filePath))
1733 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1734 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1735 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1738 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1741 else if(!strcmp(extension, "3ds"))
1743 if(FileExists(filePath))
1744 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1745 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1746 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1750 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1753 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1754 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1755 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1756 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1757 !strcmp(extension, "js"))
1759 CodeEditor editor { parent = this, state = state, visible = false };
1760 editor.updatingCode = true;
1761 if(editor.LoadFile(filePath))
1764 editor.visible = true;
1768 needFileModified = false;
1772 CodeEditor editor { parent = this, state = state, visible = false };
1773 if(editor.LoadFile(filePath))
1776 editor.visible = true;
1780 needFileModified = false;
1783 if(document && (document._class == class(PictureEdit) ||
1784 document._class == class(ModelView)))
1789 document.fileName = filePath;
1790 if(workspace && !workspace.holdTracking)
1791 workspace.UpdateOpenedFileInfo(filePath, opened);
1795 if(!document && createIfFails != no)
1797 if(createIfFails != yes && !needFileModified &&
1798 MessageBox { type = yesNo, parent = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1799 createIfFails = yes;
1800 if(createIfFails == yes || createIfFails == whatever)
1802 document = (Window)NewCodeEditor(this, state, true);
1804 document.fileName = filePath;
1810 if(projectView && document._class == class(CodeEditor) && workspace)
1812 int lineNumber, position;
1814 CodeEditor editor = (CodeEditor)document;
1815 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1816 editor.openedFileInfo.holdTracking = true;
1817 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1818 position = Max(editor.openedFileInfo.position - 1, 0);
1819 editor.editBox.GoToLineNum(lineNumber);
1820 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1821 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1822 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1823 editor.editBox.scroll = scroll;
1824 editor.openedFileInfo.holdTracking = false;
1827 if(needFileModified)
1828 document.OnFileModified = OnFileModified;
1829 document.NotifySaved = DocumentSaved;
1832 ideSettings.AddRecentProject(document.fileName);
1834 ideSettings.AddRecentFile(document.fileName);
1835 ide.UpdateRecentMenus();
1836 settingsContainer.Save();
1844 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
1845 /*bool Window::GenericDocumentOnClose(bool parentClosing)
1847 if(!parentClosing && ide.workspace)
1848 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1851 bool ModelView::ModelViewOnClose(bool parentClosing)
1853 if(!parentClosing && ide.workspace)
1854 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1857 bool PictureEdit::PictureEditOnClose(bool parentClosing)
1859 if(!parentClosing && ide.workspace)
1860 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1865 void OnUnloadGraphics(Window window)
1867 display.ClearMaterials();
1868 display.ClearTextures();
1869 display.ClearMeshes();
1873 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
1875 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1876 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1880 bool OnKeyDown(Key key, unichar ch)
1885 projectView.Update(null);
1888 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1891 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1897 void GoToError(const char * line)
1900 projectView.GoToError(line);
1903 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
1906 char *colon = strchr(text, ':');
1907 char filePath[MAX_LOCATION];
1908 char completePath[MAX_LOCATION];
1909 int line = 0, col = 0;
1914 char * close = strchr(text, ')');
1918 strncpy(name, &text[4], close - text - 4);
1919 name[close - text - 4] = '\0';
1920 for(p : ide.workspace.projects)
1922 if(!strcmp(p.name, name))
1932 prj = project ? project : (dir ? null : ide.project);
1933 if(colon && (colon[1] == '/' || colon[1] == '\\'))
1935 path = (colon - 1 > path) ? colon - 1 : path;
1936 colon = strstr(colon + 1, ":");
1938 while(isspace(*path)) path++;
1941 strncpy(filePath, path, colon - path);
1942 filePath[colon - path] = '\0';
1943 line = atoi(colon + 1);
1944 colon = strstr(colon + 1, ":");
1946 col = atoi(colon + 1);
1948 else if(path - 1 >= path && *(path - 1) == '\"')
1950 colon = strchr(path, '\"');
1953 strncpy(filePath, path, colon - path);
1954 filePath[colon - path] = '\0';
1959 strcpy(completePath, prj.topNode.path);
1960 else if(dir && dir[0])
1961 strcpy(completePath, dir);
1963 completePath[0] = '\0';
1964 PathCat(completePath, filePath);
1966 if(FileExists(completePath).isFile)
1968 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
1969 if(codeEditor && line)
1971 EditBox editBox = codeEditor.editBox;
1972 editBox.GoToLineNum(line - 1);
1973 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
1978 void OnRedraw(Surface surface)
1980 Bitmap bitmap = back.bitmap;
1982 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
1985 void SheetSelected(SheetType sheetSelected)
1987 if(activeChild == sheet)
1989 if(sheetSelected == methods)
1991 viewPropertiesItem.accelerator = f4;
1992 viewPropertiesItem.parent = viewMenu;
1993 viewMethodsItem.parent = null;
1997 viewMethodsItem.accelerator = f4;
1998 viewMethodsItem.parent = viewMenu;
1999 viewPropertiesItem.parent = null;
2004 viewMethodsItem.parent = viewMenu;
2005 viewPropertiesItem.parent = viewMenu;
2006 if(sheetSelected == methods)
2008 viewMethodsItem.accelerator = f4;
2009 viewPropertiesItem.accelerator = 0;
2013 viewMethodsItem.accelerator = 0;
2014 viewPropertiesItem.accelerator = f4;
2019 void OnActivateClient(Window client, Window previous)
2021 //if(!client || client != previous)
2024 if(!client || client != previous)
2027 dataType = previous._class;
2028 if(previous && !strcmp(dataType.name, "CodeEditor"))
2030 ((CodeEditor)previous).UpdateFormCode();
2032 else if(previous && !strcmp(dataType.name, "Designer"))
2034 ((Designer)previous).codeEditor.UpdateFormCode();
2039 dataType = client._class;
2040 if(client && !strcmp(dataType.name, "CodeEditor"))
2042 CodeEditor codeEditor = (CodeEditor)client;
2043 SetPrivateModule(codeEditor.privateModule);
2044 SetCurrentContext(codeEditor.globalContext);
2045 SetTopContext(codeEditor.globalContext);
2046 SetGlobalContext(codeEditor.globalContext);
2048 SetDefines(&codeEditor.defines);
2049 SetImports(&codeEditor.imports);
2051 SetActiveDesigner(codeEditor.designer);
2053 sheet.codeEditor = codeEditor;
2054 toolBox.codeEditor = codeEditor;
2056 viewDesignerItem.parent = viewMenu;
2057 if(activeChild != codeEditor)
2059 viewCodeItem.parent = viewMenu;
2060 viewDesignerItem.accelerator = 0;
2061 viewCodeItem.accelerator = f8;
2065 viewCodeItem.parent = null;
2066 viewDesignerItem.accelerator = f8;
2069 else if(client && !strcmp(dataType.name, "Designer"))
2071 CodeEditor codeEditor = ((Designer)client).codeEditor;
2074 SetPrivateModule(codeEditor.privateModule);
2075 SetCurrentContext(codeEditor.globalContext);
2076 SetTopContext(codeEditor.globalContext);
2077 SetGlobalContext(codeEditor.globalContext);
2078 SetDefines(&codeEditor.defines);
2079 SetImports(&codeEditor.imports);
2083 SetPrivateModule(null);
2084 SetCurrentContext(null);
2085 SetTopContext(null);
2086 SetGlobalContext(null);
2091 SetActiveDesigner((Designer)client);
2093 sheet.codeEditor = codeEditor;
2094 toolBox.codeEditor = codeEditor;
2096 viewCodeItem.parent = viewMenu;
2097 if(activeChild != client)
2099 viewDesignerItem.parent = viewMenu;
2100 viewDesignerItem.accelerator = f8;
2101 viewCodeItem.accelerator = 0;
2105 viewDesignerItem.parent = null;
2106 viewCodeItem.accelerator = f8;
2112 sheet.codeEditor = null;
2113 toolBox.codeEditor = null;
2114 SetActiveDesigner(null);
2116 viewDesignerItem.parent = null;
2117 viewCodeItem.parent = null;
2120 SheetSelected(sheet.sheetSelected);
2123 projectCompileItem = null;
2128 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2130 CodeEditor codeEditor = (CodeEditor)client;
2131 EditBox editBox = codeEditor.editBox;
2133 statusBar.AddField(pos);
2135 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2136 statusBar.AddField(caps);
2138 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2139 statusBar.AddField(ovr);
2141 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2142 statusBar.AddField(num);
2144 //statusBar.text = "Ready";
2146 if(projectView && projectView.project)
2148 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2152 sprintf(name, $"Compile %s", node.name);
2153 projectCompileItem =
2155 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2157 bool NotifySelect(MenuItem selection, Modifiers mods)
2161 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2163 projectView.Compile(node);
2168 projectMenu.AddDynamic(projectCompileItem, null, false);
2174 caps = ovr = num = null;
2179 bool OnClose(bool parentClosing)
2181 //return !projectView.buildInProgress;
2182 if(projectView && projectView.buildInProgress)
2184 if(DontTerminateDebugSession($"Close IDE"))
2186 if(findInFilesDialog)
2187 findInFilesDialog.SearchStop();
2190 workspace.timer.Stop();
2199 for(c = 1; c<app.argc; c++)
2201 char fullPath[MAX_LOCATION];
2202 GetWorkingDir(fullPath, MAX_LOCATION);
2203 PathCat(fullPath, app.argv[c]);
2204 if(FileExists(fullPath))
2205 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2212 // IS THIS NEEDED? WASN'T HERE BEFORE...
2215 projectView.visible = false;
2216 projectView.Destroy(0);
2219 #ifdef GDB_DEBUG_GUI
2220 gdbDialog.Destroy(0);
2225 void SetPath(bool projectsDirs, CompilerConfig compiler, ProjectConfig config)
2229 char * oldPaths[128];
2230 String oldList = new char[maxPathLen];
2231 Array<String> newExePaths { };
2232 //Map<String, bool> exePathExists { };
2234 #if defined(__unix__) || defined(__APPLE__)
2235 Array<String> newLibPaths { };
2236 Map<String, bool> libPathExists { };
2241 for(prj : workspace.projects)
2243 DirExpression targetDirExp;
2245 // SKIP FIRST PROJECT...
2246 if(prj == workspace.projects.firstIterator.data) continue;
2248 targetDirExp = prj.GetTargetDir(compiler, config);
2250 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2254 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2255 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2259 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2260 if(cfg.targetType == sharedLibrary && cfg.debug)
2264 if(targetDirExp.dir)
2266 char buffer[MAX_LOCATION];
2267 #if defined(__WIN32__)
2268 Array<String> paths = newExePaths;
2270 Array<String> paths = newLibPaths;
2272 GetSystemPathBuffer(buffer, prj.topNode.path);
2273 PathCat(buffer, targetDirExp.dir);
2276 if(!fstrcmp(p, buffer))
2283 paths.Add(CopyString(buffer));
2285 delete targetDirExp;
2289 for(item : compiler.executableDirs)
2292 for(p : newExePaths)
2294 if(!fstrcmp(p, item))
2301 newExePaths.Add(CopySystemPath(item));
2304 GetEnvironment("PATH", oldList, maxPathLen);
2306 printf("Old value of PATH: %s\n", oldList);
2308 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2309 for(c = 0; c < count; c++)
2312 for(p : newExePaths)
2314 if(!fstrcmp(p, oldPaths[c]))
2321 newExePaths.Add(CopySystemPath(oldPaths[c]));
2325 for(path : newExePaths)
2326 len += strlen(path) + 1;
2327 newList = new char[len + 1];
2329 for(path : newExePaths)
2331 strcat(newList, path);
2332 strcat(newList, pathListSep);
2334 newList[len - 1] = '\0';
2335 SetEnvironment("PATH", newList);
2337 printf("New value of PATH: %s\n", newList);
2344 #if defined(__unix__) || defined(__APPLE__)
2346 for(item : compiler.libraryDirs)
2348 if(!libPathExists[item]) // fstrcmp should be used
2350 newLibPaths.Add(item);
2351 libPathExists[item] = true;
2355 #if defined(__APPLE__)
2356 GetEnvironment("DYLD_LIBRARY_PATH", oldList, maxPathLen);
2358 GetEnvironment("LD_LIBRARY_PATH", oldList, maxPathLen);
2361 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2363 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2364 for(c = 0; c < count; c++)
2366 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2368 newLibPaths.Add(oldPaths[c]);
2369 libPathExists[oldPaths[c]] = true;
2374 for(path : newLibPaths)
2375 len += strlen(path) + 1;
2376 newList = new char[len + 1];
2378 for(path : newLibPaths)
2380 strcat(newList, path);
2381 strcat(newList, pathListSep);
2383 newList[len - 1] = '\0';
2384 #if defined(__APPLE__)
2385 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2387 SetEnvironment("LD_LIBRARY_PATH", newList);
2390 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2395 delete libPathExists;
2398 if(compiler.distccEnabled && compiler.distccHosts)
2399 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2404 void DestroyTemporaryProjectDir()
2406 if(tmpPrjDir && tmpPrjDir[0])
2408 if(FileExists(tmpPrjDir).isDirectory)
2409 DestroyDir(tmpPrjDir);
2410 property::tmpPrjDir = null;
2416 // Graphics Driver Menu
2420 app.currentSkin.selectionColor = selectionColor;
2421 app.currentSkin.selectionText = selectionText;
2425 driverItems = new MenuItem[app.numDrivers];
2426 for(c = 0; c < app.numDrivers; c++)
2428 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2429 driverItems[c].id = c;
2430 driverItems[c].isRadio = true;
2433 driverItems = new MenuItem[2];
2434 #if defined(__unix__)
2435 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2436 driverItems[0].id = 0;
2437 driverItems[0].isRadio = true;
2439 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2440 driverItems[0].id = 0;
2441 driverItems[0].isRadio = true;
2443 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2444 driverItems[1].id = 1;
2445 driverItems[1].isRadio = true;
2447 /* skinItems = new MenuItem[app.numSkins];
2448 for(c = 0; c < app.numSkins; c++)
2450 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2451 skinItems[c].id = c;
2452 skinItems[c].isRadio = true;
2455 ideFileDialog.master = this;
2456 ideProjectFileDialog.master = this;
2458 //SetDriverAndSkin();
2462 void UpdateRecentMenus()
2465 Menu fileMenu = menu.FindMenu($"File");
2466 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2467 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2468 char itemName[MAX_LOCATION + 4];
2471 recentFiles.Clear();
2474 for(recent : ideSettings.recentFiles)
2476 sprintf(itemName, "%d %s", 1 + c, recent);
2477 MakeSystemPath(itemName);
2478 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, null, true);
2482 recentProjects.Clear();
2484 for(recent : ideSettings.recentProjects)
2486 sprintf(itemName, "%d %s", 1 + c, recent);
2487 MakeSystemPath(itemName);
2488 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, null, true);
2501 void DestroyDir(char * path)
2503 RecursiveDeleteFolderFSI fsi { };
2508 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2510 bool preserveRootFolder;
2512 void OutFolder(char * folderPath, bool isRoot)
2514 if(!(preserveRootFolder && isRoot))
2515 RemoveDir(folderPath);
2518 bool OnFile(char * filePath)
2520 DeleteFile(filePath);
2525 class IDEApp : GuiApplication
2527 //driver = "Win32Console";
2528 // driver = "OpenGL";
2533 SetLoggingMode(stdOut, null);
2534 //SetLoggingMode(debug, null);
2536 settingsContainer.Load();
2537 #if defined(__unix__) || defined(__APPLE__)
2538 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2540 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2542 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2546 desktop.text = titleECEREIDE;
2549 for(c = 1; c<app.argc; c++)
2551 char fullPath[MAX_LOCATION];
2552 GetWorkingDir(fullPath, MAX_LOCATION);
2553 PathCat(fullPath, app.argv[c]);
2554 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2563 define app = ((IDEApp)__thisModule);
2565 define titleECEREIDE = $"ECERE IDE (Debug)";
2567 define titleECEREIDE = $"ECERE IDE";