#ifndef ECODE_HPP #define ECODE_HPP #include "appconfig.hpp" #include "docsearchcontroller.hpp" #include "featureshealth.hpp" #include "filesystemlistener.hpp" #include "globalsearchcontroller.hpp" #include "notificationcenter.hpp" #include "plugins/pluginmanager.hpp" #include "projectbuild.hpp" #include "projectdirectorytree.hpp" #include "statusbuildoutputcontroller.hpp" #include "statusterminalcontroller.hpp" #include "terminalmanager.hpp" #include "uistatusbar.hpp" #include "universallocator.hpp" #include #include #include #include using namespace eterm::UI; namespace ecode { class AutoCompletePlugin; class LinterPlugin; class FormatterPlugin; class SettingsMenu; class App : public UICodeEditorSplitter::Client { public: explicit App( const size_t& jobs = 0, const std::vector& args = {} ); ~App(); void init( const LogLevel& logLevel, std::string file, const Float& pidelDensity, const std::string& colorScheme, bool terminal, bool frameBuffer, bool benchmarkMode, const std::string& css, bool health, const std::string& healthLang, ecode::FeaturesHealth::OutputFormat healthFormat, const std::string& fileToOpen, bool stdOutLogs, bool disableFileLogs, bool openClean ); void createWidgetInspector(); void setAppTitle( const std::string& title ); void openFileDialog(); void openFolderDialog(); void openFontDialog( std::string& fontPath, bool loadingMonoFont ); void downloadFileWeb( const std::string& url ); UIFileDialog* saveFileDialog( UICodeEditor* editor, bool focusOnClose = true ); void closeApp(); void mainLoop(); void runCommand( const std::string& command ); bool loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool sync, bool stdOutLogs, bool disableFileLogs ); void saveConfig(); std::string getKeybind( const std::string& command ); std::vector getUnlockedCommands(); bool isUnlockedCommand( const std::string& command ); void saveAll(); ProjectDirectoryTree* getDirTree() const; std::shared_ptr getThreadPool() const; void loadFileFromPath( const std::string& path, bool inNewTab = true, UICodeEditor* codeEditor = nullptr, std::function onLoaded = std::function() ); void hideGlobalSearchBar(); void hideSearchBar(); void hideLocateBar(); bool isDirTreeReady() const; NotificationCenter* getNotificationCenter() const; void fullscreenToggle(); void downloadFileWebDialog(); void showGlobalSearch( bool searchAndReplace ); void showFindView(); void toggleHiddenFiles(); void newFile( const FileInfo& file ); void newFolder( const FileInfo& file ); void consoleToggle(); String i18n( const std::string& key, const String& def ); UICodeEditorSplitter* getSplitter() const { return mSplitter; } TerminalConfig& termConfig() { return mConfig.term; } const std::string& resPath() const { return mResPath; } Font* getTerminalFont() const { return mTerminalFont; } Font* getFontMono() const { return mFontMono; } Font* getFallbackFont() const { return mFallbackFont; } const Float& getDisplayDPI() const { return mDisplayDPI; } const std::string& getCurrentProject() const { return mCurrentProject; } std::string getCurrentWorkingDir() const; Drawable* findIcon( const std::string& name ); Drawable* findIcon( const std::string& name, const size_t iconSize ); const std::map& getRealDefaultKeybindings(); std::map getDefaultKeybindings(); std::map getLocalKeybindings(); std::map getMigrateKeybindings(); void switchSidePanel(); void panelPosition( const PanelPosition& panelPosition ); UniversalLocator* getUniversalLocator() const { return mUniversalLocator.get(); } TerminalManager* getTerminalManager() const { return mTerminalManager.get(); } UISceneNode* uiSceneNode() const { return mUISceneNode; } void reopenClosedTab(); void createPluginManagerUI(); void debugDrawHighlightToggle(); void debugDrawBoxesToggle(); void debugDrawData(); void setUIFontSize(); void setEditorFontSize(); void setTerminalFontSize(); void setUIScaleFactor(); void toggleSidePanel(); UIMainLayout* getMainLayout() const { return mMainLayout; } UIMessageBox* errorMsgBox( const String& msg ); UIMessageBox* fileAlreadyExistsMsgBox(); void toggleSettingsMenu(); void createNewTerminal(); UIStatusBar* getStatusBar() const { return mStatusBar; } void showFolderTreeViewTab(); void showBuildTab(); template void registerUnlockedCommands( T& t ) { t.setCommand( "keybindings", [this] { loadFileFromPath( mKeybindingsPath ); } ); t.setCommand( "debug-draw-boxes-toggle", [this] { debugDrawBoxesToggle(); } ); t.setCommand( "debug-draw-highlight-toggle", [this] { debugDrawHighlightToggle(); } ); t.setCommand( "debug-draw-debug-data", [this] { debugDrawData(); } ); t.setCommand( "debug-widget-tree-view", [this] { createWidgetInspector(); } ); t.setCommand( "menu-toggle", [this] { toggleSettingsMenu(); } ); t.setCommand( "switch-side-panel", [this] { switchSidePanel(); } ); t.setCommand( "download-file-web", [this] { downloadFileWebDialog(); } ); t.setCommand( "move-panel-left", [this] { panelPosition( PanelPosition::Left ); } ); t.setCommand( "move-panel-right", [this] { panelPosition( PanelPosition::Right ); } ); t.setCommand( "create-new-terminal", [this] { createNewTerminal(); } ); t.setCommand( "terminal-split-right", [this] { auto cwd = getCurrentWorkingDir(); mSplitter->split( UICodeEditorSplitter::SplitDirection::Right, mSplitter->getCurWidget(), false ); mTerminalManager->createNewTerminal( "", nullptr, cwd ); } ); t.setCommand( "terminal-split-bottom", [this] { auto cwd = getCurrentWorkingDir(); mSplitter->split( UICodeEditorSplitter::SplitDirection::Bottom, mSplitter->getCurWidget(), false ); mTerminalManager->createNewTerminal( "", nullptr, cwd ); } ); t.setCommand( "terminal-split-left", [this] { auto cwd = getCurrentWorkingDir(); mSplitter->split( UICodeEditorSplitter::SplitDirection::Left, mSplitter->getCurWidget(), false ); mTerminalManager->createNewTerminal( "", nullptr, cwd ); } ); t.setCommand( "terminal-split-top", [this] { auto cwd = getCurrentWorkingDir(); mSplitter->split( UICodeEditorSplitter::SplitDirection::Top, mSplitter->getCurWidget(), false ); mTerminalManager->createNewTerminal( "", nullptr, cwd ); } ); t.setCommand( "reopen-closed-tab", [this] { reopenClosedTab(); } ); t.setCommand( "plugin-manager-open", [this] { createPluginManagerUI(); } ); t.setCommand( "close-app", [this] { closeApp(); } ); t.setCommand( "fullscreen-toggle", [this]() { fullscreenToggle(); } ); t.setCommand( "open-file", [this] { openFileDialog(); } ); t.setCommand( "open-folder", [this] { openFolderDialog(); } ); t.setCommand( "console-toggle", [this] { consoleToggle(); } ); t.setCommand( "find-replace", [this] { showFindView(); } ); t.setCommand( "open-global-search", [this] { showGlobalSearch( false ); } ); t.setCommand( "toggle-status-global-search-bar", [this] { mGlobalSearchController->toggleGlobalSearchBar(); } ); t.setCommand( "toggle-status-build-output", [this] { mStatusBuildOutputController->toggle(); } ); t.setCommand( "toggle-status-terminal", [this] { mStatusTerminalController->toggle(); } ); t.setCommand( "open-locatebar", [this] { mUniversalLocator->showLocateBar(); } ); t.setCommand( "toggle-status-locate-bar", [this] { mUniversalLocator->toggleLocateBar(); } ); t.setCommand( "open-command-palette", [this] { mUniversalLocator->showCommandPalette(); } ); t.setCommand( "show-open-documents", [this] { mUniversalLocator->showOpenDocuments(); } ); t.setCommand( "project-build-start", [this] { if ( mProjectBuildManager && mStatusBuildOutputController ) { if ( mProjectBuildManager->isBuilding() ) { mProjectBuildManager->cancelBuild(); } mProjectBuildManager->buildCurrentConfig( mStatusBuildOutputController.get() ); } } ); t.setCommand( "project-build-cancel", [this] { if ( mProjectBuildManager && mProjectBuildManager->isBuilding() ) { mProjectBuildManager->cancelBuild(); } } ); t.setCommand( "show-folder-treeview-tab", [this] { showFolderTreeViewTab(); } ); t.setCommand( "show-build-tab", [this] { showBuildTab(); } ); t.setCommand( "open-workspace-symbol-search", [this] { mUniversalLocator->showWorkspaceSymbol(); } ); t.setCommand( "open-document-symbol-search", [this] { mUniversalLocator->showDocumentSymbol(); } ); t.setCommand( "editor-set-line-breaking-column", [this] { setLineBreakingColumn(); } ); t.setCommand( "editor-set-line-spacing", [this] { setLineSpacing(); } ); t.setCommand( "editor-set-cursor-blinking-time", [this] { setCursorBlinkingTime(); } ); t.setCommand( "check-for-updates", [this] { checkForUpdates(); } ); t.setCommand( "about-ecode", [this] { aboutEcode(); } ); t.setCommand( "ecode-source", [this] { ecodeSource(); } ); t.setCommand( "ui-scale-factor", [this] { setUIScaleFactor(); } ); t.setCommand( "show-side-panel", [this] { switchSidePanel(); } ); t.setCommand( "toggle-status-bar", [this] { switchStatusBar(); } ); t.setCommand( "editor-font-size", [this] { setEditorFontSize(); } ); t.setCommand( "terminal-font-size", [this] { setTerminalFontSize(); } ); t.setCommand( "ui-font-size", [this] { setUIFontSize(); } ); t.setCommand( "ui-panel-font-size", [this] { setUIPanelFontSize(); } ); t.setCommand( "serif-font", [this] { openFontDialog( mConfig.ui.serifFont, false ); } ); t.setCommand( "monospace-font", [this] { openFontDialog( mConfig.ui.monospaceFont, true ); } ); t.setCommand( "terminal-font", [this] { openFontDialog( mConfig.ui.terminalFont, false ); } ); t.setCommand( "fallback-font", [this] { openFontDialog( mConfig.ui.fallbackFont, false ); } ); t.setCommand( "tree-view-configure-ignore-files", [this] { treeViewConfigureIgnoreFiles(); } ); t.setCommand( "check-languages-health", [this] { checkLanguagesHealth(); } ); t.setCommand( "configure-terminal-shell", [this] { if ( mTerminalManager ) mTerminalManager->configureTerminalShell(); } ); t.setCommand( "configure-terminal-scrollback", [this] { if ( mTerminalManager ) mTerminalManager->configureTerminalScrollback(); } ); t.setCommand( "check-for-updates", [this] { checkForUpdates( false ); } ); t.setCommand( "create-new-window", [this] { std::string processPath = Sys::getProcessFilePath(); if ( !processPath.empty() ) { std::string cmd( processPath + " -x" ); Sys::execute( cmd ); } } ); mSplitter->registerSplitterCommands( t ); } PluginManager* getPluginManager() const; void loadFileFromPathOrFocus( const std::string& path ); UISceneNode* getUISceneNode() const { return mUISceneNode; } void setLineBreakingColumn(); void setLineSpacing(); void setCursorBlinkingTime(); void checkForUpdates( bool fromStartup = false ); void aboutEcode(); void updateRecentFiles(); void updateRecentFolders(); const CodeEditorConfig& getCodeEditorConfig() const; AppConfig& getConfig(); void updateDocInfo( TextDocument& doc ); std::vector> makeAutoClosePairs( const std::string& strPairs ); ProjectDocumentConfig& getProjectDocConfig(); const std::string& getWindowTitle() const; void setFocusEditorOnClose( UIMessageBox* msgBox ); void setUIColorScheme( const ColorSchemePreference& colorScheme ); ColorSchemePreference getUIColorScheme() const; EE::Window::Window* getWindow() const; UITextView* getDocInfo() const; UITreeView* getProjectTreeView() const; void loadCurrentDirectory(); GlobalSearchController* getGlobalSearchController() const; const std::shared_ptr& getFileSystemModel() const; void renameFile( const FileInfo& file ); UIMessageBox* newInputMsgBox( const String& title, const String& msg ); std::string getNewFilePath( const FileInfo& file, UIMessageBox* msgBox, bool keepDir = true ); const std::stack& getRecentClosedFiles() const; void updateTerminalMenu(); void ecodeSource(); void setUIPanelFontSize(); void refreshFolderView(); bool isFileVisibleInTreeView( const std::string& filePath ); void treeViewConfigureIgnoreFiles(); void loadFileSystemMatcher( const std::string& folderPath ); void checkLanguagesHealth(); void loadFileDelayed(); const std::vector& getRecentFolders() const { return mRecentFolders; }; const std::vector& getRecentFiles() const { return mRecentFiles; }; const std::string& getThemesPath() const; std::string getThemePath() const; std::string getDefaultThemePath() const; void setTheme( const std::string& path ); void loadImageFromMedium( const std::string& path, bool isMemory ); void loadImageFromPath( const std::string& path ); void loadImageFromMemory( const std::string& content ); void createAndShowRecentFolderPopUpMenu( Node* recentFoldersBut ); void createAndShowRecentFilesPopUpMenu( Node* recentFilesBut ); UISplitter* getMainSplitter() const; StatusTerminalController* getStatusTerminalController() const; void hideStatusTerminal(); void hideStatusBuildOutput(); StatusBuildOutputController* getStatusBuildOutputController() const; void switchStatusBar(); void showStatusBar( bool show ); ProjectBuildManager* getProjectBuildManager() const; UITabWidget* getSidePanel() const; const std::map& getRealLocalKeybindings() const; const std::map& getRealSplitterKeybindings() const; const std::map& getRealTerminalKeybindings() const; const std::string& getFileToOpen() const; void saveProject(); protected: std::vector mArgs; EE::Window::Window* mWindow{ nullptr }; UISceneNode* mUISceneNode{ nullptr }; UIConsole* mConsole{ nullptr }; std::string mCurWindowTitle; std::string mWindowTitle{ "ecode" }; UIMainLayout* mMainLayout{ nullptr }; UILayout* mBaseLayout{ nullptr }; UILayout* mImageLayout{ nullptr }; UITextView* mDocInfo{ nullptr }; std::vector mRecentFiles; std::stack mRecentClosedFiles; std::vector mRecentFolders; AppConfig mConfig; UISplitter* mProjectSplitter{ nullptr }; UITabWidget* mSidePanel{ nullptr }; UICodeEditorSplitter* mSplitter{ nullptr }; std::string mInitColorScheme; std::unordered_map mKeybindings; std::unordered_map mKeybindingsInvert; std::unordered_map mGlobalSearchKeybindings; std::unordered_map mDocumentSearchKeybindings; std::map mRealLocalKeybindings; std::map mRealSplitterKeybindings; std::map mRealTerminalKeybindings; std::map mRealDefaultKeybindings; std::string mConfigPath; std::string mPluginsPath; std::string mColorSchemesPath; std::string mKeybindingsPath; std::string mResPath; std::string mLanguagesPath; std::string mThemesPath; std::string mLogsPath; Float mDisplayDPI{ 96 }; std::shared_ptr mThreadPool; std::shared_ptr mDirTree; UITreeView* mProjectTreeView{ nullptr }; UILinearLayout* mProjectViewEmptyCont{ nullptr }; std::shared_ptr mFileSystemModel; std::shared_ptr mFileSystemMatcher; size_t mMenuIconSize{ 16 }; bool mDirTreeReady{ false }; bool mUseFrameBuffer{ false }; bool mBenchmarkMode{ false }; Time mFrameTime{ Time::Zero }; Clock mLastRender; Clock mSecondsCounter; ProjectDocumentConfig mProjectDocConfig; std::unordered_set mTmpDocs; std::string mCurrentProject; std::string mCurrentProjectName; FontTrueType* mFont{ nullptr }; FontTrueType* mFontMono{ nullptr }; FontTrueType* mTerminalFont{ nullptr }; FontTrueType* mFallbackFont{ nullptr }; efsw::FileWatcher* mFileWatcher{ nullptr }; FileSystemListener* mFileSystemListener{ nullptr }; Mutex mWatchesLock; std::unordered_map mFolderWatches; std::unordered_map mFilesFolderWatches; std::unique_ptr mGlobalSearchController; std::unique_ptr mDocSearchController; std::unique_ptr mUniversalLocator; std::unique_ptr mNotificationCenter; std::unique_ptr mStatusTerminalController; std::unique_ptr mStatusBuildOutputController; std::unique_ptr mProjectBuildManager; std::string mLastFileFolder; ColorSchemePreference mUIColorScheme; std::unique_ptr mTerminalManager; std::unique_ptr mPluginManager; std::unique_ptr mSettings; std::string mFileToOpen; UITheme* mTheme{ nullptr }; UIStatusBar* mStatusBar{ nullptr }; UISplitter* mMainSplitter{ nullptr }; void saveAllProcess(); void initLocateBar(); void initProjectTreeView( std::string path, bool openClean ); void initImageView(); void loadDirTree( const std::string& path ); void showSidePanel( bool show ); void onFileDropped( String file ); void onTextDropped( String text ); void updateEditorTitle( UICodeEditor* editor ); void updateEditorTabTitle( UICodeEditor* editor ); std::string titleFromEditor( UICodeEditor* editor ); bool onCloseRequestCallback( EE::Window::Window* ); void addRemainingTabWidgets( Node* widget ); void updateEditorState(); void saveDoc(); void loadFolder( const std::string& path ); void loadKeybindings(); void reloadKeybindings(); void onDocumentStateChanged( UICodeEditor*, TextDocument& ); void onDocumentModified( UICodeEditor* editor, TextDocument& ); void onColorSchemeChanged( const std::string& ); void onRealDocumentLoaded( UICodeEditor* editor, const std::string& path ); void onDocumentLoaded( UICodeEditor* editor, const std::string& path ); void onCodeEditorCreated( UICodeEditor*, TextDocument& doc ); void onDocumentSelectionChange( UICodeEditor* editor, TextDocument& ); void onDocumentCursorPosChange( UICodeEditor* editor, TextDocument& ); void onWidgetFocusChange( UIWidget* widget ); void onCodeEditorFocusChange( UICodeEditor* editor ); bool trySendUnlockedCmd( const KeyEvent& keyEvent ); FontTrueType* loadFont( const std::string& name, std::string fontPath, const std::string& fallback = "" ); void closeFolder(); void closeEditors(); void removeFolderWatches(); void createDocDirtyAlert( UICodeEditor* editor ); void createDocManyLangsAlert( UICodeEditor* editor ); void syncProjectTreeWithEditor( UICodeEditor* editor ); void initPluginManager(); void onPluginEnabled( UICodeEditorPlugin* plugin ); void checkForUpdatesResponse( Http::Response response, bool fromStartup ); std::string getLastUsedFolder(); void insertRecentFolder( const std::string& rpath ); void cleanUpRecentFolders(); void cleanUpRecentFiles(); void updateOpenRecentFolderBtn(); void updateDocInfoLocation(); void onReady(); bool dirInFolderWatches( const std::string& dir ); }; } // namespace ecode #endif // ECODE_HPP