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 enum OpenCreateIfFails { no, yes, something, whatever };
56 enum OpenMethod { normal, add };
58 static Array<FileFilter> fileFilters
60 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
61 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
62 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
63 { $"Text files (*.txt, *.text, *.nfo, *.info)", "txt, text, nfo, info" },
64 { $"Web files (*.html, *.htm, *.xhtml, *.css, *.php, *.js, *.jsi, *.rb, *.xml)", "html, htm, xhtml, css, php, js, jsi, rb, xml" },
65 { $"Image Files (*.jpg, *.jpeg, *.bmp, *.pcx, *.png, *.gif)", "jpg, jpeg, bmp, pcx, png, gif" },
66 { $"3D Studio Model Files (*.3ds)", "3ds" },
67 { $"All files", null }
70 static Array<FileType> fileTypes
72 { $"Based on extension", null },
75 { $"3D Studio Model", "3ds" }
78 static Array<FileFilter> projectFilters
80 { $"Project Files (*.epj)", ProjectExtension }
83 static Array<FileType> projectTypes
85 { $"Project File", ProjectExtension }
88 static Array<FileFilter> findInFilesFileFilters
90 { $"eC Files (*.ec, *.eh)", "ec, eh" },
91 { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
92 { $"Header Files for eC/C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
93 { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
94 { $"Text files (*.txt)", "txt" },
95 { $"All files", null }
98 FileDialog ideFileDialog
100 type = multiOpen, text = $"Open";
101 types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType), filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter);
104 FileDialog ideProjectFileDialog
106 type = open, text = $"Open Project";
107 types = projectTypes.array, sizeTypes = projectTypes.count * sizeof(FileType), filters = projectFilters.array, sizeFilters = projectFilters.count * sizeof(FileFilter);
110 GlobalSettingsDialog globalSettingsDialog
112 ideSettings = ideSettings;
113 settingsContainer = settingsContainer;
115 void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange)
117 switch(globalSettingsChange)
122 for(child = ide.firstChild; child; child = child.next)
124 if(child._class == class(CodeEditor))
126 CodeEditor codeEditor = (CodeEditor) child;
127 codeEditor.editBox.freeCaret = ideSettings.useFreeCaret;
128 // codeEditor.editBox.lineNumbers = ideSettings.showLineNumbers;
129 codeEditor.editBox.caretFollowsScrolling = ideSettings.caretFollowsScrolling;
130 codeEditor.OnPostCreate(); // Update editBox margin size
137 case compilerSettings:
139 ide.UpdateMakefiles();
146 void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
151 lineY = (line - 1) * lineH;
152 if(lineY + lineH > scrollY && lineY + lineH < scrollY + boxH)
154 Bitmap bitmap = resource.bitmap;
156 surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
163 nativeDecorations = true;
164 icon = { ":icon.png" };
165 text = titleECEREIDE;
166 background = Color { 85, 85, 85 };
167 borderStyle = sizable;
172 hasVertScroll = true;
173 hasHorzScroll = true;
179 anchor = { top = 0, right = 0, bottom = 0 };
182 anchor = { left = 0, top = 0, right = 0, bottom = 0 };
186 MenuItem * driverItems, * skinItems;
187 StatusField pos { width = 150 };
188 StatusField ovr, caps, num;
190 BitmapResource back { ":ecereBack.jpg", window = this };
191 BitmapResource bmpBp { ":codeMarks/breakpoint.png", window = this };
192 BitmapResource bmpBpDisabled { ":codeMarks/breakpointDisabled.png", window = this };
193 BitmapResource bmpBpHalf { ":codeMarks/breakpointHalf.png", window = this };
194 BitmapResource bmpBpHalfDisabled { ":codeMarks/breakpointHalfDisabled.png", window = this };
195 BitmapResource bmpCursor { ":codeMarks/cursor.png", window = this };
196 BitmapResource bmpCursorError { ":codeMarks/cursorError.png", window = this };
197 BitmapResource bmpTopFrame { ":codeMarks/topFrame.png", window = this };
198 BitmapResource bmpTopFrameError { ":codeMarks/topFrameError.png", window = this };
199 BitmapResource bmpTopFrameHalf { ":codeMarks/topFrameHalf.png", window = this };
200 BitmapResource bmpTopFrameHalfError { ":codeMarks/topFrameHalfError.png", window = this };
202 Debugger debugger { };
204 ProjectView projectView;
206 OutputView outputView
210 void OnGotoError(char * line)
215 void OnCodeLocationParseAndGoTo(char * line)
217 ide.CodeLocationParseAndGoTo(line, ide.findInFilesDialog.findProject, ide.findInFilesDialog.findDir);
220 bool OnKeyDown(Key key, unichar ch)
225 if(!ide.findInFilesDialog || !ide.findInFilesDialog.SearchAbort())
226 ide.ShowCodeEditor();
229 ide.projectView.stopBuild = true;
233 OutputView::OnKeyDown(key, ch);
240 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
243 ide.RepositionWindows(false);
247 bool OnClose(bool parentClosing)
251 ide.RepositionWindows(false);
252 return parentClosing;
256 CallStackView callStackView
258 parent = this, font = { panelFont.faceName, panelFont.size };
260 void OnGotoLine(char * line)
263 stackLvl = atoi(line);
264 ide.debugger.GoToStackFrameLine(stackLvl, true);
267 void OnSelectFrame(int lineNumber)
269 ide.debugger.SelectFrame(lineNumber);
272 void OnToggleBreakpoint()
274 Debugger debugger = ide.debugger;
275 if(debugger.activeFrame && debugger.activeFrame.absoluteFile)
277 int line = debugger.activeFrame.line;
278 char name[MAX_LOCATION];
280 // TOFIX: Improve on this, don't use only filename, make a function
281 GetLastDirectory(debugger.activeFrame.absoluteFile, name);
282 if(ide && ide.workspace)
284 for(p : ide.workspace.projects)
286 if(p.topNode.Find(name, false))
294 for(p : ide.workspace.projects)
296 if(eString_PathInsideOf(debugger.activeFrame.absoluteFile, p.topNode.path))
304 debugger.ToggleBreakpoint(debugger.activeFrame.absoluteFile, line, prj);
307 CodeEditor codeEditor = (CodeEditor)ide.FindWindow(debugger.activeFrame.absoluteFile);
308 if(codeEditor) { codeEditor.Update(null); Activate(); }
313 bool OnKeyDown(Key key, unichar ch)
317 case escape: ide.ShowCodeEditor(); break;
322 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
325 ide.RepositionWindows(false);
329 bool OnClose(bool parentClosing)
333 ide.RepositionWindows(false);
334 return parentClosing;
337 void OnRedraw(Surface surface)
340 int lineCursor, lineTopFrame, activeThread, hitThread;
341 int lineH, scrollY, boxH;
343 Breakpoint bp = null;
344 Debugger debugger = ide.debugger;
345 Frame activeFrame = debugger.activeFrame;
348 scrollY = editBox.scroll.y;
349 displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
351 activeThread = debugger.activeThread;
352 hitThread = debugger.hitThread;
353 debugger.GetCallStackCursorLine(&error, &lineCursor, &lineTopFrame);
355 if(activeFrame && activeFrame.absoluteFile)
357 for(i : ide.workspace.breakpoints; i.type == user)
359 if(i.absoluteFilePath && i.absoluteFilePath[0] &&
360 !fstrcmp(i.absoluteFilePath, activeFrame.absoluteFile) &&
361 activeFrame.line == i.line)
370 DrawLineMarginIcon(surface,
371 /*(lineCursor == 1 || lineTopFrame == 1) ? */ide.bmpBpHalf/* : ide.bmpBp*/,
372 lineCursor /*1*/, lineH, scrollY, boxH);
375 if(activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
376 DrawLineMarginIcon(surface,
377 (lineCursor == 1 || lineTopFrame == 1) ? ide.bmpBpHalf : ide.bmpBp,
378 1, lineH, scrollY, boxH);
380 DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
381 if(bp && lineCursor == 1) //activeThread && activeThread == hitThread && debugger.bpHit && debugger.bpHit.type == user)
382 bmp = error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf;
384 bmp = error ? ide.bmpTopFrameError : ide.bmpTopFrame;
385 DrawLineMarginIcon(surface, bmp, lineTopFrame, lineH, scrollY, boxH);
386 if(editBox.horzScroll && editBox.horzScroll.visible)
388 surface.SetBackground(control);
389 surface.Area(0, editBox.clientSize.h, 20 - 1, clientSize.h - 1);
394 WatchesView watchesView { parent = this };
395 ThreadsView threadsView
397 parent = this, font = { panelFont.faceName, panelFont.size };
399 bool OnKeyDown(Key key, unichar ch)
403 case escape: ide.ShowCodeEditor(); break;
408 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
411 ide.RepositionWindows(false);
415 bool OnClose(bool parentClosing)
419 ide.RepositionWindows(false);
420 return parentClosing;
423 void OnSelectThread(int threadId)
426 ide.debugger.SelectThread(threadId);
429 bool OnGetThreadsInfo(int * activeThread, int * hitThread, int * signalThread)
432 Debugger debugger = ide.debugger;
433 *activeThread = debugger.activeThread;
434 *hitThread = debugger.hitThread;
435 *signalThread = debugger.signalThread;
440 BreakpointsView breakpointsView { parent = this };
442 ToolBox toolBox { parent = this };
443 Sheet sheet { parent = this };
446 property char * tmpPrjDir { set { delete tmpPrjDir; if(value) tmpPrjDir = CopyString(value); } get { return tmpPrjDir; } };
448 Menu fileMenu { menu, $"File", f };
451 fileMenu, $"New", n, ctrlN;
452 bool NotifySelect(MenuItem selection, Modifiers mods)
454 Window document = (Window)NewCodeEditor(this, normal, false);
455 document.NotifySaved = DocumentSaved;
459 MenuItem fileOpenItem
461 fileMenu, $"Open...", o, ctrlO;
462 bool NotifySelect(MenuItem selection, Modifiers mods)
464 if(!projectView && ideSettings.ideFileDialogLocation)
465 ideFileDialog.currentDirectory = ideSettings.ideFileDialogLocation;
468 if(ideFileDialog.Modal() == ok)
470 bool gotWhatWeWant = false;
472 int numSelections = ideFileDialog.numSelections;
473 char ** multiFilePaths = ideFileDialog.multiFilePaths;
475 for(c = 0; c < numSelections; c++)
477 if(OpenFile(multiFilePaths[c], normal, true, fileTypes[ideFileDialog.fileType].typeExtension, no, normal))
478 gotWhatWeWant = true;
481 MessageBox { type = yesNo, master = this, text = $"Error opening file",
482 contents = $"Open a different file?" }.Modal() == no)
484 if(!projectView && gotWhatWeWant)
485 ChangeFileDialogsDirectory(ideFileDialog.currentDirectory, true);
495 MenuItem fileCloseItem { fileMenu, $"Close", c, ctrlF4, NotifySelect = MenuFileClose };
496 MenuDivider { fileMenu };
497 MenuItem fileSaveItem { fileMenu, $"Save", s, ctrlS };
498 MenuItem fileSaveAsItem { fileMenu, $"Save As...", a };
499 MenuItem fileSaveAllItem { fileMenu, $"Save All", l, NotifySelect = MenuFileSaveAll };
500 MenuDivider { fileMenu };
503 fileMenu, $"Find In Files...", f, Key { f, ctrl = true , shift = true };
504 bool NotifySelect(MenuItem selection, Modifiers mods)
506 findInFilesDialog.replaceMode = false;
507 findInFilesDialog.Show();
511 MenuItem replaceInFiles
513 fileMenu, $"Replace In Files...", e, Key { r, ctrl = true , shift = true };
514 bool NotifySelect(MenuItem selection, Modifiers mods)
516 findInFilesDialog.replaceMode = true;
517 findInFilesDialog.Show();
521 MenuDivider { fileMenu };
522 MenuItem globalSettingsItem
524 fileMenu, $"Global Settings...", g;
525 bool NotifySelect(MenuItem selection, Modifiers mods)
527 globalSettingsDialog.master = this;
528 if(ide.workspace && ide.workspace.compiler)
529 globalSettingsDialog.workspaceActiveCompiler = ide.workspace.compiler;
530 else if(ideSettings.defaultCompiler)
531 globalSettingsDialog.workspaceActiveCompiler = ideSettings.defaultCompiler;
532 globalSettingsDialog.Modal();
536 MenuDivider { fileMenu };
537 Menu recentFiles { fileMenu, $"Recent Files", r };
538 Menu recentProjects { fileMenu, $"Recent Projects", p };
539 MenuDivider { fileMenu };
540 MenuItem exitItem { fileMenu, $"Exit", x, altF4, NotifySelect = MenuFileExit };
542 bool FileRecentFile(MenuItem selection, Modifiers mods)
545 for(file : ideSettings.recentFiles)
547 if(id == selection.id)
549 OpenFile(file, normal, true, null, no, normal);
557 bool FileRecentProject(MenuItem selection, Modifiers mods)
560 for(file : ideSettings.recentProjects)
562 if(id == selection.id)
564 OpenFile(file, normal, true, null, no, normal);
572 MenuPlacement editMenu { menu, $"Edit", e };
574 Menu projectMenu { menu, $"Menu"."Project", p };
575 MenuItem projectNewItem
577 projectMenu, $"New...", n, Key { n, true, true };
578 bool NotifySelect(MenuItem selection, Modifiers mods)
580 if(!DontTerminateDebugSession($"New Project"))
581 if(MenuWindowCloseAll(null, 0))
583 NewProjectDialog newProjectDialog;
587 projectView.visible = false;
588 if(!projectView.Destroy(0))
592 newProjectDialog = { master = this };
593 newProjectDialog.Modal();
596 ideSettings.AddRecentProject(projectView.fileName);
597 ide.UpdateRecentMenus();
598 settingsContainer.Save();
604 MenuItem projectOpenItem
606 projectMenu, $"Open...", o, Key { o, true, true };
607 bool NotifySelect(MenuItem selection, Modifiers mods)
609 if(ideSettings.ideProjectFileDialogLocation)
610 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
612 if(ideProjectFileDialog.Modal() == ok)
614 OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, normal);
615 //ChangeProjectFileDialogDirectory(ideProjectFileDialog.currentDirectory);
620 MenuItem projectQuickItem
622 projectMenu, $"Quick...", q, f7;
623 bool NotifySelect(MenuItem selection, Modifiers mods)
626 QuickProjectDialog{ this }.Modal();
630 MenuItem projectAddItem
632 projectMenu, $"Add project to workspace...", a, Key { a, true, true };
634 bool NotifySelect(MenuItem selection, Modifiers mods)
636 if(ideSettings.ideProjectFileDialogLocation)
637 ideProjectFileDialog.currentDirectory = ideSettings.ideProjectFileDialogLocation;
641 if(ideProjectFileDialog.Modal() == ok)
643 if(OpenFile(ideProjectFileDialog.filePath, normal, true, projectTypes[ideProjectFileDialog.fileType].typeExtension, no, add))
645 if(MessageBox { type = yesNo, master = this, text = $"Error opening project file",
646 contents = $"Add a different project?" }.Modal() == no)
657 MenuItem projectCloseItem
659 projectMenu, $"Close", c, disabled = true;
660 bool NotifySelect(MenuItem selection, Modifiers mods)
664 if(!ide.DontTerminateDebugSession($"Project Close"))
666 if(findInFilesDialog)
667 findInFilesDialog.SearchStop();
668 projectView.visible = false;
669 if(projectView.Destroy(0))
670 MenuWindowCloseAll(null, 0);
672 char workingDir[MAX_LOCATION];
673 GetWorkingDir(workingDir, MAX_LOCATION);
674 findInFilesDialog.currentDirectory = workingDir;
681 MenuDivider { projectMenu };
682 MenuItem activeCompilerItem
684 projectMenu, $"Active Compiler...", g, /*altF5, */disabled = true;
685 bool NotifySelect(MenuItem selection, Modifiers mods)
687 projectView.MenuCompiler(null, mods);
691 MenuItem projectActiveConfigItem
693 projectMenu, $"Active Configuration...", g, altF5, disabled = true;
694 bool NotifySelect(MenuItem selection, Modifiers mods)
696 projectView.MenuConfig(projectView.active ? selection : null, mods);
700 MenuItem projectSettingsItem
702 projectMenu, $"Settings...", s, altF7, disabled = true;
703 bool NotifySelect(MenuItem selection, Modifiers mods)
705 projectView.MenuSettings(projectView.active ? selection : null, mods);
709 MenuDivider { projectMenu };
710 MenuItem projectBrowseFolderItem
712 projectMenu, $"Browse Project Folder", p, disabled = true;
713 bool NotifySelect(MenuItem selection, Modifiers mods)
716 projectView.MenuBrowseFolder(null, mods);
720 MenuDivider { projectMenu };
721 MenuItem projectRunItem
723 projectMenu, $"Run", r, ctrlF5, disabled = true;
724 bool NotifySelect(MenuItem selection, Modifiers mods)
727 projectView.Run(null, mods);
731 MenuItem projectBuildItem
733 projectMenu, $"Build", b, f7, disabled = true;
734 bool NotifySelect(MenuItem selection, Modifiers mods)
737 projectView.ProjectBuild(projectView.active ? selection : null, mods);
741 MenuItem projectLinkItem
743 projectMenu, $"Relink", l, disabled = true;
744 bool NotifySelect(MenuItem selection, Modifiers mods)
747 projectView.ProjectLink(projectView.active ? selection : null, mods);
751 MenuItem projectRebuildItem
753 projectMenu, $"Rebuild", d, shiftF7, disabled = true;
754 bool NotifySelect(MenuItem selection, Modifiers mods)
757 projectView.ProjectRebuild(projectView.active ? selection : null, mods);
761 MenuItem projectCleanItem
763 projectMenu, $"Clean", e, disabled = true;
764 bool NotifySelect(MenuItem selection, Modifiers mods)
769 projectView.ProjectClean(projectView.active ? selection : null, mods);
774 MenuItem projectRegenerateItem
776 projectMenu, $"Regenerate Makefile", m, disabled = true;
777 bool NotifySelect(MenuItem selection, Modifiers mods)
780 projectView.ProjectRegenerate(projectView.active ? selection : null, mods);
784 MenuItem projectCompileItem;
785 Menu debugMenu { menu, $"Debug", d };
786 MenuItem debugStartResumeItem
788 debugMenu, $"Start", s, f5, disabled = true;
789 NotifySelect = MenuDebugStart;
791 bool MenuDebugStart(MenuItem selection, Modifiers mods)
795 debugStartResumeItem.disabled = true; // a very rare exception to calling AdjustDebugMenus
796 if(!projectView.DebugStart())
797 debugStartResumeItem.disabled = false; // same exception
801 bool MenuDebugResume(MenuItem selection, Modifiers mods)
804 projectView.DebugResume();
807 MenuItem debugRestartItem
809 debugMenu, $"Restart", r, Key { f5, ctrl = true, shift = true }, disabled = true;
810 bool NotifySelect(MenuItem selection, Modifiers mods)
813 projectView.DebugRestart();
817 MenuItem debugBreakItem
819 debugMenu, $"Break", b, Key { pauseBreak, ctrl = true }, disabled = true;
820 bool NotifySelect(MenuItem selection, Modifiers mods)
823 projectView.DebugBreak();
827 MenuItem debugStopItem
829 debugMenu, $"Stop", p, shiftF5, disabled = true;
830 bool NotifySelect(MenuItem selection, Modifiers mods)
833 projectView.DebugStop();
837 MenuDivider { debugMenu };
838 MenuItem debugStepIntoItem
840 debugMenu, $"Step Into", i, f11, disabled = true;
841 bool NotifySelect(MenuItem selection, Modifiers mods)
844 projectView.DebugStepInto();
848 MenuItem debugStepOverItem
850 debugMenu, $"Step Over", v, f10, disabled = true;
851 bool NotifySelect(MenuItem selection, Modifiers mods)
854 projectView.DebugStepOver(false);
858 MenuItem debugStepOutItem
860 debugMenu, $"Step Out", o, shiftF11, disabled = true;
861 bool NotifySelect(MenuItem selection, Modifiers mods)
864 projectView.DebugStepOut(false);
868 MenuPlacement debugRunToCursorItem { debugMenu, $"Run To Cursor", c };
869 MenuItem debugSkipStepOverItem
871 debugMenu, $"Step Over Skipping Breakpoints", e, shiftF10, disabled = true;
872 bool NotifySelect(MenuItem selection, Modifiers mods)
875 projectView.DebugStepOver(true);
879 MenuItem debugSkipStepOutItem
881 debugMenu, $"Step Out Skipping Breakpoints", t, Key { f11, ctrl = true, shift = true }, disabled = true;
882 bool NotifySelect(MenuItem selection, Modifiers mods)
885 projectView.DebugStepOut(true);
889 MenuPlacement debugSkipRunToCursorItem { debugMenu, $"Run To Cursor Skipping Breakpoints", u };
890 //MenuDivider { debugMenu };
891 //MenuPlacement debugToggleBreakpoint { debugMenu, "Toggle Breakpoint", t };
892 MenuPlacement imageMenu { menu, $"Image", i };
893 Menu viewMenu { menu, $"View", v };
894 MenuItem viewProjectItem
896 viewMenu, $"Project View", j, alt0, disabled = true;
897 bool NotifySelect(MenuItem selection, Modifiers mods)
901 projectView.visible = true;
902 projectView.Activate();
907 MenuPlacement { viewMenu, $"View Designer" };
908 MenuPlacement { viewMenu, $"View Code" };
909 MenuPlacement { viewMenu, $"View Properties" };
910 MenuPlacement { viewMenu, $"View Methods" };
911 MenuItem viewDesignerItem
913 viewMenu, $"View Designer", d, f8;
914 bool NotifySelect(MenuItem selection, Modifiers mods)
916 Window client = activeClient;
917 Class dataType = client._class;
918 if(!strcmp(dataType.name, "Designer"))
920 client.visible = true;
924 ((CodeEditor)client).ViewDesigner();
928 MenuItem viewCodeItem
930 viewMenu, $"View Code", c, f8;
931 bool NotifySelect(MenuItem selection, Modifiers mods)
933 Window client = activeClient;
934 Class dataType = client._class;
935 if(!strcmp(dataType.name, "Designer"))
936 client = ((Designer)client).codeEditor;
939 // Do this after so the caret isn't moved yet...
940 client.visible = true;
944 MenuItem viewPropertiesItem
946 viewMenu, $"View Properties", p, f4;
947 bool NotifySelect(MenuItem selection, Modifiers mods)
949 sheet.visible = true;
950 sheet.sheetSelected = properties;
955 MenuItem viewMethodsItem
957 viewMenu, $"View Methods", m, f4;
958 bool NotifySelect(MenuItem selection, Modifiers mods)
960 sheet.visible = true;
961 sheet.sheetSelected = methods;
966 MenuItem viewToolBoxItem
968 viewMenu, $"View Toolbox", x, f12;
969 bool NotifySelect(MenuItem selection, Modifiers mods)
971 toolBox.visible = true;
976 MenuItem viewOutputItem
978 viewMenu, $"Output", o, alt2;
979 bool NotifySelect(MenuItem selection, Modifiers mods)
985 MenuItem viewWatchesItem
987 viewMenu, $"Watches", w, alt3;
988 bool NotifySelect(MenuItem selection, Modifiers mods)
994 MenuItem viewThreadsItem
996 viewMenu, $"Threads", t, alt4;
997 bool NotifySelect(MenuItem selection, Modifiers mods)
1003 MenuItem viewBreakpointsItem
1005 viewMenu, $"Breakpoints", b, alt5;
1006 bool NotifySelect(MenuItem selection, Modifiers mods)
1008 breakpointsView.Show();
1012 MenuItem viewCallStackItem
1014 viewMenu, $"Call Stack", s, alt7;
1015 bool NotifySelect(MenuItem selection, Modifiers mods)
1017 callStackView.Show();
1021 MenuItem viewAllDebugViews
1023 viewMenu, $"All Debug Views", a, alt9;
1024 bool NotifySelect(MenuItem selection, Modifiers mods)
1029 callStackView.Show();
1030 breakpointsView.Show();
1034 #ifdef GDB_DEBUG_GUI
1035 MenuDivider { viewMenu };
1036 MenuItem viewGDBItem
1038 viewMenu, $"GDB Dialog", g, Key { f9, shift = true, ctrl = true };
1039 bool NotifySelect(MenuItem selection, Modifiers mods)
1046 MenuDivider { viewMenu };
1047 MenuItem viewColorPicker
1049 viewMenu, $"Color Picker...", c, Key { c, ctrl = true , shift = true };
1050 bool NotifySelect(MenuItem selection, Modifiers mods)
1052 ColorPicker colorPicker { master = this, parent = this, stayOnTop = true };
1053 colorPicker.Create();
1057 MenuDivider { viewMenu };
1061 viewMenu, "Full Screen", f, checkable = true;
1063 bool NotifySelect(MenuItem selection, Modifiers mods)
1065 app.fullScreen ^= true;
1067 anchor = { 0, 0, 0, 0 };
1072 Menu driversMenu { viewMenu, $"Graphics Driver", v };
1073 //Menu skinsMenu { viewMenu, "GUI Skins", k };
1074 Menu windowMenu { menu, $"Window", w };
1075 MenuItem { windowMenu, $"Close All", l, NotifySelect = MenuWindowCloseAll };
1076 MenuDivider { windowMenu };
1077 MenuItem { windowMenu, $"Next", n, f6, NotifySelect = MenuWindowNext };
1078 MenuItem { windowMenu, $"Previous", p, shiftF6, NotifySelect = MenuWindowPrevious };
1079 MenuDivider { windowMenu };
1080 MenuItem { windowMenu, $"Cascade", c, NotifySelect = MenuWindowCascade };
1081 MenuItem { windowMenu, $"Tile Horizontally", h, NotifySelect = MenuWindowTileHorz };
1082 MenuItem { windowMenu, $"Tile Vertically", v, NotifySelect = MenuWindowTileVert };
1083 MenuItem { windowMenu, $"Arrange Icons", a, NotifySelect = MenuWindowArrangeIcons };
1084 MenuDivider { windowMenu };
1085 MenuItem { windowMenu, $"Windows...", w, NotifySelect = MenuWindowWindows };
1086 Menu helpMenu { menu, $"Help", h };
1089 helpMenu, $"API Reference", r, f1;
1090 bool NotifySelect(MenuItem selection, Modifiers mods)
1092 Execute("documentor");
1096 MenuDivider { helpMenu };
1099 helpMenu, $"About...", a;
1100 bool NotifySelect(MenuItem selection, Modifiers mods)
1102 AboutIDE { master = this }.Modal();
1107 property ToolBox toolBox
1109 get { return toolBox; }
1112 property Sheet sheet
1114 get { return sheet; }
1117 property Project project
1119 get { return projectView ? projectView.project : null; }
1122 property Workspace workspace
1124 get { return projectView ? projectView.workspace : null; }
1127 FindInFilesDialog findInFilesDialog
1129 master = this, parent = this;
1130 filters = findInFilesFileFilters.array, sizeFilters = findInFilesFileFilters.count * sizeof(FileFilter);
1134 #ifdef GDB_DEBUG_GUI
1137 master = this, parent = this;
1138 anchor = { left = 100, top = 100, right = 100, bottom = 100 };
1140 void OnCommand(char * string)
1143 ide.debugger.SendGDBCommand(string);
1148 bool NotifySelectDisplayDriver(MenuItem selection, Modifiers mods)
1150 //app.driver = app.drivers[selection.id];
1152 app.driver = selection.id ? "OpenGL" : "X";
1154 app.driver = selection.id ? "OpenGL" : "GDI";
1156 delete ideSettings.displayDriver;
1157 ideSettings.displayDriver = CopyString(selection.id ? "OpenGL" : "Default");
1159 settingsContainer.Save();
1160 //SetDriverAndSkin();
1164 bool NotifySelectDisplaySkin(MenuItem selection, Modifiers mods)
1166 app.skin = app.skins[selection.id];
1171 void SetDriverAndSkin()
1174 for(c = 0; c < app.numSkins; c++)
1175 if(!strcmp(app.skins[c], app.skin))
1177 skinItems[c].checked = true;
1180 for(c = 0; c < app.numDrivers; c++)
1181 if(!strcmp(app.drivers[c], app.driver))
1183 driverItems[c].checked = true;
1188 ProjectView CreateProjectView(Workspace workspace, char * fileName)
1190 Project project = workspace.projects.firstIterator.data;
1191 projectView = ProjectView
1194 fileName = fileName;
1196 void NotifyDestroyed(Window window, DialogResult result)
1199 text = titleECEREIDE;
1204 projectView.Create();
1205 RepositionWindows(false);
1207 // Leave it after Create to avoid flicker due to seeing IDE without a project view
1208 projectView.workspace = workspace;
1209 projectView.project = project;
1210 SetText("%s - %s", project.topNode.name, titleECEREIDE);
1214 ide.breakpointsView.LoadFromWorkspace();
1215 ide.watchesView.LoadFromWorkspace();
1217 findInFilesDialog.projectNodeField.userData = projectView;
1220 char fileName[MAX_LOCATION];
1221 strcpy(fileName, project.topNode.path);
1222 PathCat(fileName, project.topNode.name);
1227 bool GetDebugMenusDisabled()
1231 Project project = projectView.project;
1233 if(project.targetType == executable)
1240 void RepositionWindows(bool expand)
1245 bool inDebugMode = debugger.isActive;
1246 bool callStackVisible = expand ? false : callStackView.visible;
1247 bool threadsVisible = expand ? false : threadsView.visible;
1248 bool watchesVisible = expand ? false : watchesView.visible;
1249 bool breakpointsVisible = expand ? false : breakpointsView.visible;
1250 bool toolBoxVisible = toolBox.visible;
1251 bool outputVisible = expand ? false : outputView.visible;
1252 int topDistance = (callStackVisible || threadsVisible) ? 200 : 0;
1253 int bottomDistance = (outputVisible || watchesVisible || breakpointsVisible) ? 240 : 0;
1255 for(child = firstChild; child; child = child.next)
1257 if(child._class == class(CodeEditor) || child._class == class(Designer) ||
1258 child._class == class(Sheet) || child._class == class(ProjectView))
1260 Anchor anchor = child.anchor;
1261 anchor.top = topDistance;
1262 anchor.bottom = bottomDistance;
1263 if(child._class == class(CodeEditor) || child._class == class(Designer))
1265 anchor.right = toolBoxVisible ? 150 : 0;
1267 child.anchor = anchor;
1271 if(child._class == class(OutputView) || child._class == class(CallStackView) || child._class == class(ThreadsView) || child._class == class(WatchesView) ||
1272 child._class == class(BreakpointsView))
1273 child.visible = false;
1276 // If this is not here, the IDE is not updated when doing Debug/Break then Alt-4 to show call stack (IDE not updated)
1281 bool ShowCodeEditor()
1284 activeClient.Activate();
1285 else if(projectView)
1287 projectView.visible = true;
1288 projectView.Activate();
1292 sheet.visible = true;
1298 bool ShouldStopBuild()
1300 return projectView.stopBuild;
1303 void DocumentSaved(Window document, char * fileName)
1305 ideSettings.AddRecentFile(fileName);
1306 ide.UpdateRecentMenus();
1307 settingsContainer.Save();
1310 bool Window::OnFileModified(FileChange fileChange, char * param)
1313 sprintf(temp, $"The document %s was modified by another application.\n"
1314 "Would you like to reload it and lose your changes?", this.fileName);
1315 if(MessageBox { type = yesNo, master = this/*.parent*/,
1316 text = $"Document has been modified", contents = temp }.Modal() == yes)
1318 char * fileName = CopyString(this.fileName);
1319 WindowState state = this.state;
1320 Anchor anchor = this.anchor;
1321 Size size = this.size;
1323 this.modifiedDocument = false;
1325 this = ide.OpenFile(fileName, normal, true, null, no, normal);
1328 this.anchor = anchor;
1330 this.SetState(state, true, 0);
1338 void UpdateMakefiles()
1342 for(prj : workspace.projects)
1344 bool first = prj == workspace.projects.firstIterator.data;
1345 projectView.ProjectUpdateMakefileForAllConfigs(prj, first, first);
1352 bool unavailable = !project;
1354 projectQuickItem.disabled = !unavailable;
1356 projectAddItem.disabled = unavailable;
1358 activeCompilerItem.disabled = unavailable;
1359 projectActiveConfigItem.disabled = unavailable;
1360 projectSettingsItem.disabled = unavailable;
1362 projectBrowseFolderItem.disabled = unavailable;
1364 viewProjectItem.disabled = unavailable;
1370 void AdjustBuildMenus()
1372 bool unavailable = project && projectView.buildInProgress;
1374 projectNewItem.disabled = unavailable;
1375 projectOpenItem.disabled = unavailable;
1377 unavailable = !project || projectView.buildInProgress;
1379 projectCloseItem.disabled = unavailable;
1381 projectRunItem.disabled = unavailable || project.targetType != executable;
1382 projectBuildItem.disabled = unavailable;
1383 projectLinkItem.disabled = unavailable;
1384 projectRebuildItem.disabled = unavailable;
1385 projectCleanItem.disabled = unavailable;
1386 projectRegenerateItem.disabled = unavailable;
1387 projectCompileItem.disabled = unavailable;
1390 void AdjustDebugMenus()
1392 bool unavailable = !project || project.targetType != executable ||
1393 projectView.buildInProgress == buildingMainProject;
1394 bool active = ide.debugger.isActive;
1395 bool executing = ide.debugger.state == running;
1396 //bool holding = ide.debugger.state == stopped;
1398 debugStartResumeItem.disabled = unavailable || executing;
1400 debugStartResumeItem.text = active ? $"Resume" : $"Start";
1401 debugStartResumeItem.NotifySelect = active ? MenuDebugResume : MenuDebugStart;
1403 debugBreakItem.disabled = unavailable || !executing;
1404 debugStopItem.disabled = unavailable || !active;
1405 debugRestartItem.disabled = unavailable || !active;
1407 debugStepIntoItem.disabled = unavailable || executing;
1408 debugStepOverItem.disabled = unavailable || executing;
1409 debugStepOutItem.disabled = unavailable || executing || !active;
1410 debugSkipStepOverItem.disabled = unavailable || executing;
1411 debugSkipStepOutItem.disabled = unavailable || executing || !active;
1413 if((Designer)GetActiveDesigner())
1415 CodeEditor codeEditor = ((Designer)GetActiveDesigner()).codeEditor;
1418 codeEditor.debugRunToCursor.disabled = unavailable || executing;
1419 codeEditor.debugSkipRunToCursor.disabled = unavailable || executing;
1424 void ChangeFileDialogsDirectory(char * directory, bool saveSettings)
1426 char tempString[MAX_LOCATION];
1427 strcpy(tempString, directory);
1428 if(saveSettings && !projectView)
1430 ideSettings.ideFileDialogLocation = directory;
1431 settingsContainer.Save();
1434 ideFileDialog.currentDirectory = tempString;
1435 codeEditorFileDialog.currentDirectory = tempString;
1436 codeEditorFormFileDialog.currentDirectory = tempString;
1439 void ChangeProjectFileDialogDirectory(char * directory)
1441 ideSettings.ideProjectFileDialogLocation = directory;
1442 settingsContainer.Save();
1445 Window FindWindow(char * filePath)
1447 Window document = null;
1449 // TOCHECK: Do we need to change slashes here?
1450 for(document = firstChild; document; document = document.next)
1452 char * fileName = document.fileName;
1453 if(document.isDocument && fileName && !fstrcmp(fileName, filePath))
1455 document.visible = true;
1456 document.Activate();
1463 bool DontTerminateDebugSession(char * title)
1465 if(debugger.isActive)
1467 if(MessageBox { type = yesNo, master = ide,
1468 contents = $"Do you want to terminate the debugging session in progress?",
1469 text = title }.Modal() == no)
1472 MessageBox msg { type = yesNo, master = ide,
1473 contents = "Do you want to terminate the debugging session in progress?",
1475 if(msg.Modal() == no)
1487 Window OpenFile(char * origFilePath, WindowState state, bool visible, char * type, OpenCreateIfFails createIfFails, OpenMethod openMethod)
1489 char extension[MAX_EXTENSION] = "";
1490 Window document = null;
1491 bool isProject = false;
1492 bool needFileModified = true;
1493 char winFilePath[MAX_LOCATION];
1494 char * filePath = strstr(origFilePath, "http://") == origFilePath ? strcpy(winFilePath, origFilePath) : GetSystemPathBuffer(winFilePath, origFilePath);
1498 GetExtension(filePath, extension);
1502 strcpy(extension, type);
1504 if(strcmp(extension, ProjectExtension))
1506 for(document = firstChild; document; document = document.next)
1508 char * fileName = document.fileName;
1509 if(document.isDocument && fileName && !fstrcmp(fileName, filePath) && document.created)
1511 document.visible = true;
1512 document.Activate();
1518 if(createIfFails == whatever)
1520 else if(!strcmp(extension, ProjectExtension) || !strcmp(extension, WorkspaceExtension))
1522 if(openMethod == normal)
1524 if(DontTerminateDebugSession($"Open Project"))
1527 if(MenuWindowCloseAll(null, 0))
1531 projectView.visible = false;
1532 projectView.Destroy(0);
1533 // Where did this come from? projectView = null;
1540 Workspace workspace = null;
1542 if(FileExists(filePath))
1544 if(!strcmp(extension, ProjectExtension))
1546 char workspaceFile[MAX_LOCATION];
1547 strcpy(workspaceFile, filePath);
1548 ChangeExtension(workspaceFile, WorkspaceExtension, workspaceFile);
1549 workspace = LoadWorkspace(workspaceFile, filePath);
1551 else if(!strcmp(extension, WorkspaceExtension))
1552 workspace = LoadWorkspace(filePath, null);
1555 //project = LoadProject(filePath);
1560 char absolutePath[MAX_LOCATION];
1561 CreateProjectView(workspace, filePath);
1562 document = projectView;
1564 workspace.DropInvalidBreakpoints();
1567 ide.projectView.ShowOutputBuildLog(true);
1568 ide.projectView.DisplayCompiler(false);
1571 char newWorkingDir[MAX_LOCATION];
1572 StripLastDirectory(filePath, newWorkingDir);
1573 ChangeFileDialogsDirectory(newWorkingDir, false);
1576 document.fileName = filePath;
1578 SetText("%s - %s", filePath, titleECEREIDE);
1580 // this crashes on starting ide with epj file, solution please?
1581 // app.UpdateDisplay();
1583 workspace.holdTracking = true;
1584 for(ofi : workspace.openedFiles)
1586 if(ofi.state != closed)
1588 Window file = OpenFile(ofi.path, normal, true, null, no, normal);
1591 char fileName[MAX_LOCATION];
1593 GetLastDirectory(ofi.path, fileName);
1594 node = projectView.project.topNode.Find(fileName, true);
1596 node.EnsureVisible();
1600 workspace.holdTracking = false;
1602 workspace.timer.Start();
1604 findInFilesDialog.mode = FindInFilesMode::project;
1605 findInFilesDialog.currentDirectory = ide.project.topNode.path;
1608 char location[MAX_LOCATION];
1609 StripLastDirectory(ide.project.topNode.path, location);
1610 ChangeProjectFileDialogDirectory(location);
1614 if(projectView.debugger)
1615 projectView.debugger.EvaluateWatches();
1622 if(MessageBox { type = yesNo, parent = this, text = $"Error opening project", contents = $"Open a different project?" }.Modal() == yes)
1624 if(ideProjectFileDialog.Modal() == cancel)
1626 filePath = ideProjectFileDialog.filePath;
1627 GetExtension(filePath, extension);
1638 else if(openMethod == add)
1643 char slashFilePath[MAX_LOCATION];
1644 GetSlashPathBuffer(slashFilePath, filePath);
1645 for(p : workspace.projects)
1647 if(!fstrcmp(p.filePath, slashFilePath))
1655 MessageBox { type = ok, parent = parent, master = this, text = $"Same Project",
1656 contents = $"This project is already present in workspace." }.Modal();
1660 prj = LoadProject(filePath);
1663 workspace.projects.Add(prj);
1665 projectView.AddNode(prj.topNode, null);
1666 workspace.modified = true;
1668 findInFilesDialog.AddProjectItem(prj);
1669 projectView.ProjectUpdateMakefileForAllConfigs(prj, true, true);
1670 // projectView is associated with the main project and not with the one just added but
1671 return projectView; // just to let the caller know something was opened
1679 else if(!strcmp(extension, "bmp") || !strcmp(extension, "pcx") ||
1680 !strcmp(extension, "jpg") || !strcmp(extension, "gif") ||
1681 !strcmp(extension, "jpeg") || !strcmp(extension, "png"))
1683 if(FileExists(filePath))
1684 document = PictureEdit { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1685 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1686 visible = visible, bitmapFile = filePath, OnClose = PictureEditOnClose/*why?--GenericDocumentOnClose*/;
1689 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1692 else if(!strcmp(extension, "3ds"))
1694 if(FileExists(filePath))
1695 document = ModelView { hasMaximize = true, hasMinimize = true, hasClose = true, borderStyle = sizable,
1696 hasVertScroll = true, hasHorzScroll = true, parent = this, state = state,
1697 visible = visible, modelFile = filePath, OnClose = ModelViewOnClose/*why?--GenericDocumentOnClose*/
1701 MessageBox { type = ok, parent = this, text = filePath, contents = $"File doesn't exist." }.Modal();
1704 else if(!strcmp(extension, "txt") || !strcmp(extension, "text") ||
1705 !strcmp(extension, "nfo") || !strcmp(extension, "info") ||
1706 !strcmp(extension, "htm") || !strcmp(extension, "html") ||
1707 !strcmp(extension, "css") || !strcmp(extension, "php") ||
1708 !strcmp(extension, "js"))
1710 CodeEditor editor { parent = this, state = state, visible = false };
1711 editor.updatingCode = true;
1712 if(editor.LoadFile(filePath))
1715 editor.visible = true;
1719 needFileModified = false;
1723 CodeEditor editor { parent = this, state = state, visible = false };
1724 if(editor.LoadFile(filePath))
1727 editor.visible = true;
1731 needFileModified = false;
1734 if(document && (document._class == class(PictureEdit) ||
1735 document._class == class(ModelView)))
1740 document.fileName = filePath;
1741 if(workspace && !workspace.holdTracking)
1742 workspace.UpdateOpenedFileInfo(filePath, opened);
1746 if(!document && createIfFails != no)
1748 if(createIfFails != yes && !needFileModified &&
1749 MessageBox { type = yesNo, parent = this, text = filePath, contents = $"File doesn't exist. Create?" }.Modal() == yes)
1750 createIfFails = yes;
1751 if(createIfFails == yes || createIfFails == whatever)
1753 document = (Window)NewCodeEditor(this, state, true);
1755 document.fileName = filePath;
1761 if(projectView && document._class == class(CodeEditor) && workspace)
1763 int lineNumber, position;
1765 CodeEditor editor = (CodeEditor)document;
1766 editor.openedFileInfo = workspace.UpdateOpenedFileInfo(filePath, opened);
1767 editor.openedFileInfo.holdTracking = true;
1768 lineNumber = Max(editor.openedFileInfo.lineNumber - 1, 0);
1769 position = Max(editor.openedFileInfo.position - 1, 0);
1770 editor.editBox.GoToLineNum(lineNumber);
1771 editor.editBox.GoToPosition(editor.editBox.line, lineNumber, position);
1772 scroll.x = Max(editor.openedFileInfo.scroll.x, 0);
1773 scroll.y = Max(editor.openedFileInfo.scroll.y, 0);
1774 editor.editBox.scroll = scroll;
1775 editor.openedFileInfo.holdTracking = false;
1778 if(needFileModified)
1779 document.OnFileModified = OnFileModified;
1780 document.NotifySaved = DocumentSaved;
1783 ideSettings.AddRecentProject(document.fileName);
1785 ideSettings.AddRecentFile(document.fileName);
1786 ide.UpdateRecentMenus();
1787 settingsContainer.Save();
1795 // TOCHECK: I can't use a generic one for both ModelView and PictureEdit both derived from Window
1796 /*bool Window::GenericDocumentOnClose(bool parentClosing)
1798 if(!parentClosing && ide.workspace)
1799 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1802 bool ModelView::ModelViewOnClose(bool parentClosing)
1804 if(!parentClosing && ide.workspace)
1805 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1808 bool PictureEdit::PictureEditOnClose(bool parentClosing)
1810 if(!parentClosing && ide.workspace)
1811 ide.workspace.UpdateOpenedFileInfo(fileName, unknown);
1816 void OnUnloadGraphics(Window window)
1818 display.ClearMaterials();
1819 display.ClearTextures();
1820 display.ClearMeshes();
1824 bool OnActivate(bool active, Window swap, bool * goOnWithActivation, bool direct)
1826 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1827 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1831 bool OnKeyDown(Key key, unichar ch)
1836 projectView.Update(null);
1839 caps.color = app.GetKeyState(capsState) ? black : Color { 128,128,128 };
1842 num.color = app.GetKeyState(numState) ? black : Color { 128,128,128 };
1848 void GoToError(const char * line)
1851 projectView.GoToError(line);
1854 void CodeLocationParseAndGoTo(const char * text, Project project, const char * dir)
1857 char *colon = strchr(text, ':');
1858 char filePath[MAX_LOCATION];
1859 char completePath[MAX_LOCATION];
1860 int line = 0, col = 0;
1865 char * close = strchr(text, ')');
1869 strncpy(name, &text[4], close - text - 4);
1870 name[close - text - 4] = '\0';
1871 for(p : ide.workspace.projects)
1873 if(!strcmp(p.name, name))
1883 prj = project ? project : (dir ? null : ide.project);
1884 if(colon && (colon[1] == '/' || colon[1] == '\\'))
1886 path = (colon - 1 > path) ? colon - 1 : path;
1887 colon = strstr(colon + 1, ":");
1889 while(isspace(*path)) path++;
1892 strncpy(filePath, path, colon - path);
1893 filePath[colon - path] = '\0';
1894 line = atoi(colon + 1);
1895 colon = strstr(colon + 1, ":");
1897 col = atoi(colon + 1);
1899 else if(path - 1 >= path && *(path - 1) == '\"')
1901 colon = strchr(path, '\"');
1904 strncpy(filePath, path, colon - path);
1905 filePath[colon - path] = '\0';
1910 strcpy(completePath, prj.topNode.path);
1911 else if(dir && dir[0])
1912 strcpy(completePath, dir);
1914 completePath[0] = '\0';
1915 PathCat(completePath, filePath);
1917 if(FileExists(completePath).isFile)
1919 CodeEditor codeEditor = (CodeEditor)OpenFile(completePath, normal, true, "", no, normal);
1920 if(codeEditor && line)
1922 EditBox editBox = codeEditor.editBox;
1923 editBox.GoToLineNum(line - 1);
1924 editBox.GoToPosition(editBox.line, line - 1, col ? (col - 1) : 0);
1929 void OnRedraw(Surface surface)
1931 Bitmap bitmap = back.bitmap;
1933 surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2, (clientSize.h - bitmap.height) / 2, 0, 0, bitmap.width, bitmap.height);
1936 void SheetSelected(SheetType sheetSelected)
1938 if(activeChild == sheet)
1940 if(sheetSelected == methods)
1942 viewPropertiesItem.accelerator = f4;
1943 viewPropertiesItem.parent = viewMenu;
1944 viewMethodsItem.parent = null;
1948 viewMethodsItem.accelerator = f4;
1949 viewMethodsItem.parent = viewMenu;
1950 viewPropertiesItem.parent = null;
1955 viewMethodsItem.parent = viewMenu;
1956 viewPropertiesItem.parent = viewMenu;
1957 if(sheetSelected == methods)
1959 viewMethodsItem.accelerator = f4;
1960 viewPropertiesItem.accelerator = 0;
1964 viewMethodsItem.accelerator = 0;
1965 viewPropertiesItem.accelerator = f4;
1970 void OnActivateClient(Window client, Window previous)
1972 //if(!client || client != previous)
1975 if(!client || client != previous)
1978 dataType = previous._class;
1979 if(previous && !strcmp(dataType.name, "CodeEditor"))
1981 ((CodeEditor)previous).UpdateFormCode();
1983 else if(previous && !strcmp(dataType.name, "Designer"))
1985 ((Designer)previous).codeEditor.UpdateFormCode();
1990 dataType = client._class;
1991 if(client && !strcmp(dataType.name, "CodeEditor"))
1993 CodeEditor codeEditor = (CodeEditor)client;
1994 SetPrivateModule(codeEditor.privateModule);
1995 SetCurrentContext(codeEditor.globalContext);
1996 SetTopContext(codeEditor.globalContext);
1997 SetGlobalContext(codeEditor.globalContext);
1999 SetDefines(&codeEditor.defines);
2000 SetImports(&codeEditor.imports);
2002 SetActiveDesigner(codeEditor.designer);
2004 sheet.codeEditor = codeEditor;
2005 toolBox.codeEditor = codeEditor;
2007 viewDesignerItem.parent = viewMenu;
2008 if(activeChild != codeEditor)
2010 viewCodeItem.parent = viewMenu;
2011 viewDesignerItem.accelerator = 0;
2012 viewCodeItem.accelerator = f8;
2016 viewCodeItem.parent = null;
2017 viewDesignerItem.accelerator = f8;
2020 else if(client && !strcmp(dataType.name, "Designer"))
2022 CodeEditor codeEditor = ((Designer)client).codeEditor;
2025 SetPrivateModule(codeEditor.privateModule);
2026 SetCurrentContext(codeEditor.globalContext);
2027 SetTopContext(codeEditor.globalContext);
2028 SetGlobalContext(codeEditor.globalContext);
2029 SetDefines(&codeEditor.defines);
2030 SetImports(&codeEditor.imports);
2034 SetPrivateModule(null);
2035 SetCurrentContext(null);
2036 SetTopContext(null);
2037 SetGlobalContext(null);
2042 SetActiveDesigner((Designer)client);
2044 sheet.codeEditor = codeEditor;
2045 toolBox.codeEditor = codeEditor;
2047 viewCodeItem.parent = viewMenu;
2048 if(activeChild != client)
2050 viewDesignerItem.parent = viewMenu;
2051 viewDesignerItem.accelerator = f8;
2052 viewCodeItem.accelerator = 0;
2056 viewDesignerItem.parent = null;
2057 viewCodeItem.accelerator = f8;
2063 sheet.codeEditor = null;
2064 toolBox.codeEditor = null;
2065 SetActiveDesigner(null);
2067 viewDesignerItem.parent = null;
2068 viewCodeItem.parent = null;
2071 SheetSelected(sheet.sheetSelected);
2074 projectCompileItem = null;
2079 if(client && client._class == eSystem_FindClass(__thisModule, "CodeEditor")) // !strcmp(client._class.name, "CodeEditor")
2081 CodeEditor codeEditor = (CodeEditor)client;
2082 EditBox editBox = codeEditor.editBox;
2084 statusBar.AddField(pos);
2086 caps = { width = 40, text = $"CAPS", color = app.GetKeyState(capsState) ? black : Color { 128, 128, 128 } };
2087 statusBar.AddField(caps);
2089 ovr = { width = 30, text = $"OVR", color = editBox.overwrite ? black : Color { 128, 128, 128 } };
2090 statusBar.AddField(ovr);
2092 num = { width = 30, text = $"NUM", color = app.GetKeyState(numState) ? black : Color { 128, 128, 128 } };
2093 statusBar.AddField(num);
2095 //statusBar.text = "Ready";
2097 if(projectView && projectView.project)
2099 ProjectNode node = projectView.GetNodeFromWindow(client, null);
2103 sprintf(name, $"Compile %s", node.name);
2104 projectCompileItem =
2106 copyText = true, text = name, c, ctrlF7, disabled = projectView.buildInProgress;
2108 bool NotifySelect(MenuItem selection, Modifiers mods)
2112 ProjectNode node = projectView.GetNodeFromWindow(activeClient, null);
2114 projectView.Compile(node);
2119 projectMenu.AddDynamic(projectCompileItem, null, false);
2125 caps = ovr = num = null;
2130 bool OnClose(bool parentClosing)
2132 //return !projectView.buildInProgress;
2133 if(projectView && projectView.buildInProgress)
2135 if(DontTerminateDebugSession($"Close IDE"))
2137 if(findInFilesDialog)
2138 findInFilesDialog.SearchStop();
2141 workspace.timer.Stop();
2150 for(c = 1; c<app.argc; c++)
2152 char fullPath[MAX_LOCATION];
2153 GetWorkingDir(fullPath, MAX_LOCATION);
2154 PathCat(fullPath, app.argv[c]);
2155 if(FileExists(fullPath))
2156 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2163 // IS THIS NEEDED? WASN'T HERE BEFORE...
2166 projectView.visible = false;
2167 projectView.Destroy(0);
2170 #ifdef GDB_DEBUG_GUI
2171 gdbDialog.Destroy(0);
2176 void SetPath(bool projectsDirs)
2180 char * oldPaths[128];
2181 char oldList[MAX_LOCATION * 128];
2182 Array<String> newExePaths { };
2183 //Map<String, bool> exePathExists { };
2185 #if defined(__unix__) || defined(__APPLE__)
2186 Array<String> newLibPaths { };
2187 Map<String, bool> libPathExists { };
2189 CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
2193 for(prj : workspace.projects)
2195 DirExpression targetDirExp;
2197 // SKIP FIRST PROJECT...
2198 if(prj == workspace.projects.firstIterator.data) continue;
2200 targetDirExp = prj.targetDir;
2202 /*if(prj.config.targetType == sharedLibrary && prj.config.debug)
2206 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2207 if(cfg.targetType == sharedLibrary && cfg.debug && !strcmpi(cfg.name, "Debug"))
2211 for(cfg = prj.configurations.first; cfg; cfg = cfg.next)
2212 if(cfg.targetType == sharedLibrary && cfg.debug)
2216 if(targetDirExp.dir)
2218 char buffer[MAX_LOCATION];
2219 #if defined(__WIN32__)
2220 Array<String> paths = newExePaths;
2222 Array<String> paths = newLibPaths;
2224 GetSystemPathBuffer(buffer, prj.topNode.path);
2225 PathCat(buffer, targetDirExp.dir);
2228 if(!fstrcmp(p, buffer))
2235 paths.Add(CopyString(buffer));
2237 delete targetDirExp;
2241 for(item : compiler.executableDirs)
2244 for(p : newExePaths)
2246 if(!fstrcmp(p, item))
2253 newExePaths.Add(CopySystemPath(item));
2256 GetEnvironment("PATH", oldList, sizeof(oldList));
2258 printf("Old value of PATH: %s\n", oldList);
2260 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2261 for(c = 0; c < count; c++)
2264 for(p : newExePaths)
2266 if(!fstrcmp(p, oldPaths[c]))
2273 newExePaths.Add(CopySystemPath(oldPaths[c]));
2277 for(path : newExePaths)
2278 len += strlen(path) + 1;
2279 newList = new char[len + 1];
2281 for(path : newExePaths)
2283 strcat(newList, path);
2284 strcat(newList, pathListSep);
2286 newList[len - 1] = '\0';
2287 SetEnvironment("PATH", newList);
2289 printf("New value of PATH: %s\n", newList);
2296 #if defined(__unix__) || defined(__APPLE__)
2298 for(item : compiler.libraryDirs)
2300 if(!libPathExists[item]) // fstrcmp should be used
2302 newLibPaths.Add(item);
2303 libPathExists[item] = true;
2307 #if defined(__APPLE__)
2308 GetEnvironment("DYLD_LIBRARY_PATH", oldList, sizeof(oldList));
2310 GetEnvironment("LD_LIBRARY_PATH", oldList, sizeof(oldList));
2313 printf("Old value of [DY]LD_LIBRARY_PATH: %s\n", oldList);
2315 count = TokenizeWith(oldList, sizeof(oldPaths) / sizeof(char *), oldPaths, pathListSep, false);
2316 for(c = 0; c < count; c++)
2318 if(!libPathExists[oldPaths[c]]) // fstrcmp should be used
2320 newLibPaths.Add(oldPaths[c]);
2321 libPathExists[oldPaths[c]] = true;
2326 for(path : newLibPaths)
2327 len += strlen(path) + 1;
2328 newList = new char[len + 1];
2330 for(path : newLibPaths)
2332 strcat(newList, path);
2333 strcat(newList, pathListSep);
2335 newList[len - 1] = '\0';
2336 #if defined(__APPLE__)
2337 SetEnvironment("DYLD_LIBRARY_PATH", newList);
2339 SetEnvironment("LD_LIBRARY_PATH", newList);
2342 printf("New value of [DY]LD_LIBRARY_PATH: %s\n", newList);
2347 delete libPathExists;
2350 if(compiler.distccEnabled && compiler.distccHosts)
2351 SetEnvironment("DISTCC_HOSTS", compiler.distccHosts);
2356 void DestroyTemporaryProjectDir()
2358 if(tmpPrjDir && tmpPrjDir[0])
2360 if(FileExists(tmpPrjDir).isDirectory)
2361 DestroyDir(tmpPrjDir);
2362 property::tmpPrjDir = null;
2368 // Graphics Driver Menu
2372 app.currentSkin.selectionColor = selectionColor;
2373 app.currentSkin.selectionText = selectionText;
2377 driverItems = new MenuItem[app.numDrivers];
2378 for(c = 0; c < app.numDrivers; c++)
2380 driverItems[c] = MenuItem { driversMenu, app.drivers[c], NotifySelect = NotifySelectDisplayDriver };
2381 driverItems[c].id = c;
2382 driverItems[c].isRadio = true;
2385 driverItems = new MenuItem[2];
2386 #if defined(__unix__)
2387 driverItems[0] = MenuItem { driversMenu, "X", NotifySelect = NotifySelectDisplayDriver };
2388 driverItems[0].id = 0;
2389 driverItems[0].isRadio = true;
2391 driverItems[0] = MenuItem { driversMenu, "GDI", NotifySelect = NotifySelectDisplayDriver };
2392 driverItems[0].id = 0;
2393 driverItems[0].isRadio = true;
2395 driverItems[1] = MenuItem { driversMenu, "OpenGL", NotifySelect = NotifySelectDisplayDriver };
2396 driverItems[1].id = 1;
2397 driverItems[1].isRadio = true;
2399 /* skinItems = new MenuItem[app.numSkins];
2400 for(c = 0; c < app.numSkins; c++)
2402 skinItems[c] = MenuItem {skinsMenu, app.skins[c], NotifySelect = NotifySelectDisplaySkin };
2403 skinItems[c].id = c;
2404 skinItems[c].isRadio = true;
2407 ideFileDialog.master = this;
2408 ideProjectFileDialog.master = this;
2410 //SetDriverAndSkin();
2414 void UpdateRecentMenus()
2417 Menu fileMenu = menu.FindMenu($"File");
2418 Menu recentFiles = fileMenu.FindMenu($"Recent Files");
2419 Menu recentProjects = fileMenu.FindMenu($"Recent Projects");
2420 char itemName[MAX_LOCATION + 4];
2423 recentFiles.Clear();
2426 for(recent : ideSettings.recentFiles)
2428 sprintf(itemName, "%d %s", 1 + c, recent);
2429 MakeSystemPath(itemName);
2430 recentFiles.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentFile }, null, true);
2434 recentProjects.Clear();
2436 for(recent : ideSettings.recentProjects)
2438 sprintf(itemName, "%d %s", 1 + c, recent);
2439 MakeSystemPath(itemName);
2440 recentProjects.AddDynamic(MenuItem { copyText = true, text = itemName, (Key)k1 + c, id = c, NotifySelect = ide.FileRecentProject }, null, true);
2453 void DestroyDir(char * path)
2455 RecursiveDeleteFolderFSI fsi { };
2460 class RecursiveDeleteFolderFSI : NormalFileSystemIterator
2462 bool preserveRootFolder;
2464 void OutFolder(char * folderPath, bool isRoot)
2466 if(!(preserveRootFolder && isRoot))
2467 RemoveDir(folderPath);
2470 bool OnFile(char * filePath)
2472 DeleteFile(filePath);
2477 class IDEApp : GuiApplication
2479 //driver = "Win32Console";
2480 // driver = "OpenGL";
2485 SetLoggingMode(stdOut, null);
2486 //SetLoggingMode(debug, null);
2488 settingsContainer.Load();
2489 #if defined(__unix__) || defined(__APPLE__)
2490 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "X";
2492 app.driver = (ideSettings.displayDriver && !strcmp(ideSettings.displayDriver, "OpenGL")) ? ideSettings.displayDriver : "GDI";
2494 ide.driverItems[ideSettings.displayDriver && !strcmp(ideSettings.displayDriver,"OpenGL")].checked = true;
2498 desktop.text = titleECEREIDE;
2501 for(c = 1; c<app.argc; c++)
2503 char fullPath[MAX_LOCATION];
2504 GetWorkingDir(fullPath, MAX_LOCATION);
2505 PathCat(fullPath, app.argv[c]);
2506 ide.OpenFile(fullPath, (app.argc == 2) * maximized, true, null, yes, normal);
2515 define app = ((IDEApp)__thisModule);
2517 define titleECEREIDE = $"ECERE IDE (Debug)";
2519 define titleECEREIDE = $"ECERE IDE";