From 3d86c2e1e326ad2969c6cbb1687980fc1050b2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Fri, 7 Apr 2023 20:01:16 -0300 Subject: [PATCH] Status Bar + Build WIP --- projects/linux/ee.files | 6 + src/eepp/ui/tools/uicodeeditorsplitter.cpp | 10 - src/eepp/ui/uiwidget.cpp | 20 +- .../src/eterm/terminal/terminaldisplay.cpp | 1 + src/tools/ecode/appconfig.cpp | 9 +- src/tools/ecode/appconfig.hpp | 6 +- src/tools/ecode/ecode.cpp | 212 +++++++++++++++--- src/tools/ecode/ecode.hpp | 36 ++- src/tools/ecode/globalsearchcontroller.cpp | 12 + src/tools/ecode/globalsearchcontroller.hpp | 2 + src/tools/ecode/projectbuild.cpp | 6 + src/tools/ecode/projectbuild.hpp | 3 + src/tools/ecode/settingsmenu.cpp | 4 + .../ecode/statusbuildoutputcontroller.cpp | 71 ++++++ .../ecode/statusbuildoutputcontroller.hpp | 39 ++++ src/tools/ecode/statusterminalcontroller.cpp | 131 +++++++++++ src/tools/ecode/statusterminalcontroller.hpp | 41 ++++ src/tools/ecode/terminalmanager.cpp | 5 +- src/tools/ecode/terminalmanager.hpp | 2 + src/tools/ecode/uistatusbar.cpp | 90 ++++++++ src/tools/ecode/uistatusbar.hpp | 35 +++ src/tools/ecode/universallocator.cpp | 15 ++ src/tools/ecode/universallocator.hpp | 2 + 23 files changed, 693 insertions(+), 65 deletions(-) create mode 100644 src/tools/ecode/statusbuildoutputcontroller.cpp create mode 100644 src/tools/ecode/statusbuildoutputcontroller.hpp create mode 100644 src/tools/ecode/statusterminalcontroller.cpp create mode 100644 src/tools/ecode/statusterminalcontroller.hpp create mode 100644 src/tools/ecode/uistatusbar.cpp create mode 100644 src/tools/ecode/uistatusbar.hpp diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 4bb872e29..552a52e11 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1206,10 +1206,16 @@ ../../src/tools/ecode/scopedop.hpp ../../src/tools/ecode/settingsmenu.cpp ../../src/tools/ecode/settingsmenu.hpp +../../src/tools/ecode/statusbuildoutputcontroller.cpp +../../src/tools/ecode/statusbuildoutputcontroller.hpp +../../src/tools/ecode/statusterminalcontroller.cpp +../../src/tools/ecode/statusterminalcontroller.hpp ../../src/tools/ecode/terminalmanager.cpp ../../src/tools/ecode/terminalmanager.hpp ../../src/tools/ecode/uicodeeditorsplitter.cpp ../../src/tools/ecode/uicodeeditorsplitter.hpp +../../src/tools/ecode/uistatusbar.cpp +../../src/tools/ecode/uistatusbar.hpp ../../src/tools/ecode/uitreeviewglobalsearch.cpp ../../src/tools/ecode/uitreeviewglobalsearch.hpp ../../src/tools/ecode/uiwelcomescreen.cpp diff --git a/src/eepp/ui/tools/uicodeeditorsplitter.cpp b/src/eepp/ui/tools/uicodeeditorsplitter.cpp index 5cecc1135..3896d20b5 100644 --- a/src/eepp/ui/tools/uicodeeditorsplitter.cpp +++ b/src/eepp/ui/tools/uicodeeditorsplitter.cpp @@ -44,16 +44,6 @@ UICodeEditorSplitter::getLocalDefaultKeybindings() { { { KEY_8, KeyMod::getDefaultModifier() }, "switch-to-tab-8" }, { { KEY_9, KeyMod::getDefaultModifier() }, "switch-to-tab-9" }, { { KEY_0, KeyMod::getDefaultModifier() }, "switch-to-last-tab" }, - { { KEY_1, KEYMOD_LALT }, "switch-to-tab-1" }, - { { KEY_2, KEYMOD_LALT }, "switch-to-tab-2" }, - { { KEY_3, KEYMOD_LALT }, "switch-to-tab-3" }, - { { KEY_4, KEYMOD_LALT }, "switch-to-tab-4" }, - { { KEY_5, KEYMOD_LALT }, "switch-to-tab-5" }, - { { KEY_6, KEYMOD_LALT }, "switch-to-tab-6" }, - { { KEY_7, KEYMOD_LALT }, "switch-to-tab-7" }, - { { KEY_8, KEYMOD_LALT }, "switch-to-tab-8" }, - { { KEY_9, KEYMOD_LALT }, "switch-to-tab-9" }, - { { KEY_0, KEYMOD_LALT }, "switch-to-last-tab" }, }; } diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index 84bacd440..cfb8dd519 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -97,7 +97,7 @@ const Rectf& UIWidget::getLayoutPixelsMargin() const { UIWidget* UIWidget::setLayoutMargin( const Rectf& margin ) { if ( mLayoutMargin != margin ) { mLayoutMargin = margin; - mLayoutMarginPx = PixelDensity::dpToPx( mLayoutMargin ); + mLayoutMarginPx = PixelDensity::dpToPx( mLayoutMargin ).ceil(); onMarginChange(); notifyLayoutAttrChange(); } @@ -108,7 +108,7 @@ UIWidget* UIWidget::setLayoutMargin( const Rectf& margin ) { UIWidget* UIWidget::setLayoutMarginLeft( const Float& marginLeft ) { if ( mLayoutMargin.Left != marginLeft ) { mLayoutMargin.Left = marginLeft; - mLayoutMarginPx.Left = PixelDensity::dpToPx( mLayoutMargin.Left ); + mLayoutMarginPx.Left = eeceil( PixelDensity::dpToPx( mLayoutMargin.Left ) ); onMarginChange(); notifyLayoutAttrChange(); } @@ -119,7 +119,7 @@ UIWidget* UIWidget::setLayoutMarginLeft( const Float& marginLeft ) { UIWidget* UIWidget::setLayoutMarginRight( const Float& marginRight ) { if ( mLayoutMargin.Right != marginRight ) { mLayoutMargin.Right = marginRight; - mLayoutMarginPx.Right = PixelDensity::dpToPx( mLayoutMargin.Right ); + mLayoutMarginPx.Right = eeceil( PixelDensity::dpToPx( mLayoutMargin.Right ) ); onMarginChange(); notifyLayoutAttrChange(); } @@ -130,7 +130,7 @@ UIWidget* UIWidget::setLayoutMarginRight( const Float& marginRight ) { UIWidget* UIWidget::setLayoutMarginTop( const Float& marginTop ) { if ( mLayoutMargin.Top != marginTop ) { mLayoutMargin.Top = marginTop; - mLayoutMarginPx.Top = PixelDensity::dpToPx( mLayoutMargin.Top ); + mLayoutMarginPx.Top = eeceil( PixelDensity::dpToPx( mLayoutMargin.Top ) ); onMarginChange(); notifyLayoutAttrChange(); } @@ -141,7 +141,7 @@ UIWidget* UIWidget::setLayoutMarginTop( const Float& marginTop ) { UIWidget* UIWidget::setLayoutMarginBottom( const Float& marginBottom ) { if ( mLayoutMargin.Bottom != marginBottom ) { mLayoutMargin.Bottom = marginBottom; - mLayoutMarginPx.Bottom = PixelDensity::dpToPx( mLayoutMargin.Bottom ); + mLayoutMarginPx.Bottom = eeceil( PixelDensity::dpToPx( mLayoutMargin.Bottom ) ); onMarginChange(); notifyLayoutAttrChange(); } @@ -604,7 +604,7 @@ const Rectf& UIWidget::getPixelsPadding() const { UIWidget* UIWidget::setPadding( const Rectf& padding ) { if ( padding != mPadding ) { mPadding = padding; - mPaddingPx = PixelDensity::dpToPx( mPadding ); + mPaddingPx = PixelDensity::dpToPx( mPadding ).ceil(); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange(); @@ -616,7 +616,7 @@ UIWidget* UIWidget::setPadding( const Rectf& padding ) { UIWidget* UIWidget::setPaddingLeft( const Float& paddingLeft ) { if ( paddingLeft != mPadding.Left ) { mPadding.Left = paddingLeft; - mPaddingPx.Left = PixelDensity::dpToPx( mPadding.Left ); + mPaddingPx.Left = eeceil( PixelDensity::dpToPx( mPadding.Left ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange(); @@ -628,7 +628,7 @@ UIWidget* UIWidget::setPaddingLeft( const Float& paddingLeft ) { UIWidget* UIWidget::setPaddingRight( const Float& paddingRight ) { if ( paddingRight != mPadding.Right ) { mPadding.Right = paddingRight; - mPaddingPx.Right = PixelDensity::dpToPx( mPadding.Right ); + mPaddingPx.Right = eeceil( PixelDensity::dpToPx( mPadding.Right ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange(); @@ -640,7 +640,7 @@ UIWidget* UIWidget::setPaddingRight( const Float& paddingRight ) { UIWidget* UIWidget::setPaddingTop( const Float& paddingTop ) { if ( paddingTop != mPadding.Top ) { mPadding.Top = paddingTop; - mPaddingPx.Top = PixelDensity::dpToPx( mPadding.Top ); + mPaddingPx.Top = eeceil( PixelDensity::dpToPx( mPadding.Top ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange(); @@ -652,7 +652,7 @@ UIWidget* UIWidget::setPaddingTop( const Float& paddingTop ) { UIWidget* UIWidget::setPaddingBottom( const Float& paddingBottom ) { if ( paddingBottom != mPadding.Bottom ) { mPadding.Bottom = paddingBottom; - mPaddingPx.Bottom = PixelDensity::dpToPx( mPadding.Bottom ); + mPaddingPx.Bottom = eeceil( PixelDensity::dpToPx( mPadding.Bottom ) ); onAutoSize(); onPaddingChange(); notifyLayoutAttrChange(); diff --git a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp index 853d38f17..e23af9ed7 100644 --- a/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp +++ b/src/modules/eterm/src/eterm/terminal/terminaldisplay.cpp @@ -1444,6 +1444,7 @@ void TerminalDisplay::onSizeChange() { mFrameBuffer->resize( fboSize.getWidth(), fboSize.getHeight() ); } } + invalidateLines(); } void TerminalDisplay::onProcessExit( int exitCode ) { diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index cc206c1da..3b9e0a0eb 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -72,6 +72,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, windowState.pixelDensity = iniState.getValueF( "window", "pixeldensity" ); windowState.winIcon = ini.getValue( "window", "winicon", resPath + "icon/ecode.png" ); windowState.panelPartition = iniState.getValue( "window", "panel_partition", "15%" ); + windowState.statusBarPartition = iniState.getValue( "window", "status_bar_partition", "85%" ); windowState.displayIndex = iniState.getValueI( "window", "display_index", 0 ); windowState.position.x = iniState.getValueI( "window", "x", -1 ); windowState.position.y = iniState.getValueI( "window", "y", -1 ); @@ -87,6 +88,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, ui.fontSize = ini.getValue( "ui", "font_size", "11dp" ); ui.panelFontSize = ini.getValue( "ui", "panel_font_size", "11dp" ); ui.showSidePanel = ini.getValueB( "ui", "show_side_panel", true ); + ui.showStatusBar = ini.getValueB( "ui", "show_status_bar", true ); ui.panelPosition = panelPositionFromString( ini.getValue( "ui", "panel_position", "left" ) ); ui.serifFont = ini.getValue( "ui", "serif_font", "fonts/NotoSans-Regular.ttf" ); ui.monospaceFont = ini.getValue( "ui", "monospace_font", "fonts/DejaVuSansMono.ttf" ); @@ -168,8 +170,9 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, void AppConfig::save( const std::vector& recentFiles, const std::vector& recentFolders, - const std::string& panelPartition, EE::Window::Window* win, - const std::string& colorSchemeName, const SearchBarConfig& searchBarConfig, + const std::string& panelPartition, const std::string& statusBarPartition, + EE::Window::Window* win, const std::string& colorSchemeName, + const SearchBarConfig& searchBarConfig, const GlobalSearchBarConfig& globalSearchBarConfig, PluginManager* pluginManager ) { @@ -194,6 +197,7 @@ void AppConfig::save( const std::vector& recentFiles, iniState.setValueB( "window", "maximized", windowState.maximized ); iniState.setValueF( "window", "pixeldensity", windowState.pixelDensity ); iniState.setValue( "window", "panel_partition", panelPartition ); + iniState.setValue( "window", "status_bar_partition", statusBarPartition ); iniState.setValueI( "window", "display_index", windowState.displayIndex ); iniState.setValueI( "window", "x", windowState.position.x ); iniState.setValueI( "window", "y", windowState.position.y ); @@ -212,6 +216,7 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValue( "ui", "font_size", ui.fontSize.toString() ); ini.setValue( "ui", "panel_font_size", ui.panelFontSize.toString() ); ini.setValueB( "ui", "show_side_panel", ui.showSidePanel ); + ini.setValueB( "ui", "show_status_bar", ui.showStatusBar ); ini.setValue( "ui", "panel_position", panelPositionToString( ui.panelPosition ) ); ini.setValue( "ui", "serif_font", ui.serifFont ); ini.setValue( "ui", "monospace_font", ui.monospaceFont ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index 0b1145f7f..6504c0eda 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -29,6 +29,7 @@ struct UIConfig { StyleSheetLength fontSize{ 11, StyleSheetLength::Dp }; StyleSheetLength panelFontSize{ 11, StyleSheetLength::Dp }; bool showSidePanel{ true }; + bool showStatusBar{ true }; PanelPosition panelPosition{ PanelPosition::Left }; std::string serifFont; std::string monospaceFont; @@ -44,6 +45,7 @@ struct WindowStateConfig { std::string winIcon; bool maximized{ false }; std::string panelPartition; + std::string statusBarPartition; int displayIndex{ 0 }; Vector2i position{ -1, -1 }; }; @@ -168,8 +170,8 @@ class AppConfig { void save( const std::vector& recentFiles, const std::vector& recentFolders, const std::string& panelPartition, - EE::Window::Window* win, const std::string& colorSchemeName, - const SearchBarConfig& searchBarConfig, + const std::string& statusBarPartition, EE::Window::Window* win, + const std::string& colorSchemeName, const SearchBarConfig& searchBarConfig, const GlobalSearchBarConfig& globalSearchBarConfig, PluginManager* pluginManager ); void saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter, diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 418dafa28..21b308ced 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -493,7 +493,7 @@ void App::loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool s void App::saveConfig() { mConfig.save( mRecentFiles, mRecentFolders, mProjectSplitter ? mProjectSplitter->getSplitPartition().toString() : "15%", - mWindow, + mMainSplitter ? mMainSplitter->getSplitPartition().toString() : "85%", mWindow, mSplitter ? mSplitter->getCurrentColorSchemeName() : mConfig.editor.colorScheme, mDocSearchController->getSearchBarConfig(), mGlobalSearchController->getGlobalSearchBarConfig(), mPluginManager.get() ); @@ -742,6 +742,12 @@ void App::showSidePanel( bool show ) { } } +void App::showStatusBar( bool show ) { + if ( show == mStatusBar->isVisible() ) + return; + mStatusBar->setVisible( show ); +} + void App::switchSidePanel() { mConfig.ui.showSidePanel = !mConfig.ui.showSidePanel; mSettings->getWindowMenu() @@ -751,6 +757,15 @@ void App::switchSidePanel() { showSidePanel( mConfig.ui.showSidePanel ); } +void App::switchStatusBar() { + mConfig.ui.showStatusBar = !mConfig.ui.showStatusBar; + mSettings->getWindowMenu() + ->getItemId( "toggle-status-bar" ) + ->asType() + ->setActive( mConfig.ui.showStatusBar ); + showStatusBar( mConfig.ui.showStatusBar ); +} + void App::panelPosition( const PanelPosition& panelPosition ) { mConfig.ui.panelPosition = panelPosition; @@ -1678,6 +1693,10 @@ std::map App::getLocalKeybindings() { { { KEY_K, KEYMOD_CTRL | KEYMOD_LALT | KEYMOD_SHIFT }, "terminal-split-bottom" }, { { KEY_S, KEYMOD_CTRL | KEYMOD_LALT | KEYMOD_SHIFT }, "terminal-split-swap" }, { { KEY_T, KEYMOD_CTRL | KEYMOD_LALT | KEYMOD_SHIFT }, "reopen-closed-tab" }, + { { KEY_1, KEYMOD_LALT }, "toggle-locatebar" }, + { { KEY_2, KEYMOD_LALT }, "toggle-global-search" }, + { { KEY_3, KEYMOD_LALT }, "toggle-status-build-output" }, + { { KEY_4, KEYMOD_LALT }, "toggle-status-terminal" }, }; } @@ -1685,7 +1704,12 @@ std::map App::getLocalKeybindings() { // keybindind std::map App::getMigrateKeybindings() { return { - { "fullscreen-toggle", "alt+return" }, + { "fullscreen-toggle", "alt+return" }, { "switch-to-tab-1", "alt+1" }, + { "switch-to-tab-2", "alt+2" }, { "switch-to-tab-3", "alt+3" }, + { "switch-to-tab-4", "alt+4" }, { "switch-to-tab-5", "alt+5" }, + { "switch-to-tab-6", "alt+6" }, { "switch-to-tab-7", "alt+7" }, + { "switch-to-tab-8", "alt+8" }, { "switch-to-tab-9", "alt+9" }, + { "switch-to-last-tab", "alt+0" }, }; } @@ -1701,8 +1725,13 @@ std::vector App::getUnlockedCommands() { "open-locatebar", "open-command-palette", "open-global-search", + "toggle-locatebar", + "toggle-global-search", + "toggle-status-build-output", + "toggle-status-terminal", "menu-toggle", "switch-side-panel", + "toggle-status-bar", "download-file-web", "create-new-terminal", "terminal-split-left", @@ -1745,6 +1774,7 @@ void App::closeEditors() { mRecentClosedFiles = {}; mSplitter->removeTabWithOwnedWidgetId( "welcome_ecode" ); + mStatusBar->setVisible( mConfig.ui.showStatusBar ); mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig ); std::vector editors = mSplitter->getAllEditors(); @@ -1783,6 +1813,9 @@ void App::closeFolder() { if ( mCurrentProject.empty() ) return; + if ( mProjectBuildManager ) + mProjectBuildManager.reset(); + if ( mSplitter->isAnyEditorDirty() ) { UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::OK_CANCEL, @@ -1800,6 +1833,7 @@ void App::closeFolder() { mFileSystemModel->setRootPath( "" ); updateOpenRecentFolderBtn(); UIWelcomeScreen::createWelcomeScreen( this ); + mStatusBar->setVisible( false ); } void App::createDocAlert( UICodeEditor* editor ) { @@ -1936,6 +1970,18 @@ void App::hideLocateBar() { mUniversalLocator->hideLocateBar(); } +void App::hideStatusTerminal() { + mStatusTerminalController->hide(); +} + +void App::hideStatusBuildOutput() { + mStatusBuildOutputController->hide(); +} + +StatusBuildOutputController* App::getStatusBuildOutputController() const { + return mStatusBuildOutputController.get(); +} + bool App::isDirTreeReady() const { return mDirTreeReady && mDirTree != nullptr; } @@ -2475,6 +2521,14 @@ void App::createAndShowRecentFilesPopUpMenu( Node* recentFilesBut ) { menu->show(); } +UISplitter* App::getMainSplitter() const { + return mMainSplitter; +} + +StatusTerminalController* App::getStatusTerminalController() const { + return mStatusTerminalController.get(); +} + void App::updateOpenRecentFolderBtn() { if ( mProjectViewEmptyCont ) { Node* recentFolderBtn = mProjectViewEmptyCont->find( "open_recent_folder" ); @@ -2637,6 +2691,7 @@ void App::initProjectTreeView( std::string path ) { updateOpenRecentFolderBtn(); UIWelcomeScreen::createWelcomeScreen( this ); + mStatusBar->setVisible( false ); } mProjectTreeView->setAutoExpandOnSingleColumn( true ); @@ -2786,6 +2841,7 @@ void App::loadFolder( const std::string& path ) { closeEditors(); } else { mSplitter->removeTabWithOwnedWidgetId( "welcome_ecode" ); + mStatusBar->setVisible( mConfig.ui.showStatusBar ); } mProjectViewEmptyCont->setVisible( false ); @@ -2796,6 +2852,8 @@ void App::loadFolder( const std::string& path ) { mCurrentProject = rpath; mPluginManager->setWorkspaceFolder( rpath ); + mProjectBuildManager = std::make_unique( rpath, mThreadPool ); + loadDirTree( rpath ); Clock projClock; @@ -2929,9 +2987,9 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe ecode::Version::getCodename().c_str() ); if ( mWindow->isOpen() ) { - // Only verify GPU driver availability on Windows. - // macOS will have at least a fallback renderer - // Linux will have at least Mesa drivers with LLVM Pipe + // Only verify GPU driver availability on Windows. + // macOS will have at least a fallback renderer + // Linux will have at least Mesa drivers with LLVM Pipe #if EE_PLATFORM == EE_PLATFORM_WIN if ( !GLi->shadersSupported() ) { mWindow->showMessageBox( @@ -3160,6 +3218,24 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe margin-left: 8dp; margin-right: 8dp; } + #status_bar { + background-color: var(--list-back); + padding-top: 1dp; + padding-bottom: 1dp; + } + #status_bar > TextView { + padding-left: 4dp; + padding-right: 5dp; + background-color: var(--list-back); + border-right-color: var(--tab-line); + font-size: 10dp; + } + #status_bar > TextView:hover { + background-color: var(--item-hover); + } + #status_bar > TextView.selected { + background-color: var(--primary); + } @@ -3175,20 +3251,22 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe - - - - - - - - - + + + + + + + + + + + + + - - - + @@ -3248,6 +3326,13 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe + + + + + + + @@ -3402,25 +3487,46 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe if ( codIconFont && codIconFont->loaded() ) { std::unordered_map codIcons = { - { "symbol-text", 0xea93 }, { "symbol-method", 0xea8c }, - { "symbol-function", 0xea8c }, { "symbol-constructor", 0xea8c }, - { "symbol-field", 0xeb5f }, { "symbol-variable", 0xea88 }, - { "symbol-class", 0xeb5b }, { "symbol-interface", 0xeb61 }, - { "symbol-module", 0xea8b }, { "symbol-property", 0xeb65 }, - { "symbol-unit", 0xea96 }, { "symbol-value", 0xea95 }, - { "symbol-enum", 0xea95 }, { "symbol-keyword", 0xeb62 }, - { "symbol-snippet", 0xeb66 }, { "symbol-color", 0xeb5c }, - { "symbol-file", 0xeb60 }, { "symbol-reference", 0xea94 }, - { "symbol-folder", 0xea83 }, { "symbol-enum-member", 0xeb5e }, - { "symbol-constant", 0xeb5d }, { "symbol-struct", 0xea91 }, - { "symbol-event", 0xea86 }, { "symbol-operator", 0xeb64 }, - { "symbol-type-parameter", 0xea92 }, { "expand-all", 0xeb95 }, - { "symbol-namespace", 0xea8b }, { "symbol-package", 0xea8b }, - { "symbol-string", 0xeb8d }, { "symbol-number", 0xea90 }, - { "symbol-boolean", 0xea8f }, { "symbol-array", 0xea8a }, - { "symbol-object", 0xea8b }, { "symbol-key", 0xea93 }, - { "symbol-null", 0xea8f }, { "collapse-all", 0xeac5 }, - { "chevron-right", 0xeab6 }, { "lightbulb-autofix", 0xeb13 } }; + { "symbol-text", 0xea93 }, + { "symbol-method", 0xea8c }, + { "symbol-function", 0xea8c }, + { "symbol-constructor", 0xea8c }, + { "symbol-field", 0xeb5f }, + { "symbol-variable", 0xea88 }, + { "symbol-class", 0xeb5b }, + { "symbol-interface", 0xeb61 }, + { "symbol-module", 0xea8b }, + { "symbol-property", 0xeb65 }, + { "symbol-unit", 0xea96 }, + { "symbol-value", 0xea95 }, + { "symbol-enum", 0xea95 }, + { "symbol-keyword", 0xeb62 }, + { "symbol-snippet", 0xeb66 }, + { "symbol-color", 0xeb5c }, + { "symbol-file", 0xeb60 }, + { "symbol-reference", 0xea94 }, + { "symbol-folder", 0xea83 }, + { "symbol-enum-member", 0xeb5e }, + { "symbol-constant", 0xeb5d }, + { "symbol-struct", 0xea91 }, + { "symbol-event", 0xea86 }, + { "symbol-operator", 0xeb64 }, + { "symbol-type-parameter", 0xea92 }, + { "expand-all", 0xeb95 }, + { "symbol-namespace", 0xea8b }, + { "symbol-package", 0xea8b }, + { "symbol-string", 0xeb8d }, + { "symbol-number", 0xea90 }, + { "symbol-boolean", 0xea8f }, + { "symbol-array", 0xea8a }, + { "symbol-object", 0xea8b }, + { "symbol-key", 0xea93 }, + { "symbol-null", 0xea8f }, + { "collapse-all", 0xeac5 }, + { "chevron-right", 0xeab6 }, + { "lightbulb-autofix", 0xeb13 }, + { "layout-sidebar-left-off", 0xec02 }, + { "layout-sidebar-left", 0xebf3 } }; for ( const auto& icon : codIcons ) iconTheme->add( UIGlyphIcon::New( icon.first, codIconFont, icon.second ) ); @@ -3451,6 +3557,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe UIWidgetCreator::registerWidget( "locatebar", UILocateBar::New ); UIWidgetCreator::registerWidget( "globalsearchbar", UIGlobalSearchBar::New ); UIWidgetCreator::registerWidget( "mainlayout", UIMainLayout::New ); + UIWidgetCreator::registerWidget( "statusbar", UIStatusBar::New ); mUISceneNode->loadLayoutFromString( baseUI ); mUISceneNode->bind( "main_layout", mMainLayout ); mUISceneNode->bind( "code_container", mBaseLayout ); @@ -3501,6 +3608,12 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe Log::info( "Base UI took: %.2f ms", globalClock.getElapsedTime().asMilliseconds() ); + mMainSplitter = mUISceneNode->find( "main_splitter" ); + mMainSplitter->setSplitPartition( + StyleSheetLength( mConfig.windowState.statusBarPartition ) ); + mStatusBar = mUISceneNode->find( "status_bar" ); + mStatusBar->setApp( this ); + #if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN mFileWatcher = new efsw::FileWatcher(); mFileSystemListener = new FileSystemListener( mSplitter, mFileSystemModel ); @@ -3526,6 +3639,12 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe mUniversalLocator->initLocateBar( mUISceneNode->find( "locate_bar" ), mUISceneNode->find( "locate_find" ) ); + mStatusTerminalController = + std::make_unique( mMainSplitter, mUISceneNode, this ); + + mStatusBuildOutputController = + std::make_unique( mMainSplitter, mUISceneNode, this ); + initImageView(); mSettings = std::make_unique(); @@ -3679,6 +3798,8 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { { "convert-lang-output" }, "" ); args::Flag disableFileLogs( parser, "disable-file-logs", "Disables writing logs to a log file", { "disable-file-logs" } ); + args::ValueFlag testBuild( parser, "test-build-path", "Test project build", + { "test-build-path" } ); std::vector args; try { @@ -3700,6 +3821,23 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) { return EXIT_FAILURE; } + if ( !testBuild.Get().empty() ) { + ProjectBuildManager bm( testBuild.Get(), {} ); + auto i18n = []( const std::string&, const String& def ) -> String { return def; }; + auto res = bm.generateBuildCommands( "ecode", i18n, "debug" ); + if ( res.isValid() ) { + for ( const auto& cmd : res.cmds ) { + for ( const auto& env : cmd.envs ) + std::cout << "export " << env.first << "=" << env.second << "\n"; + std::cout << cmd.workingDir << " " << cmd.cmd << " " << cmd.args << "\n"; + } + } else { + std::cout << res.errorMsg.toUtf8() << "\n"; + } + + return EXIT_SUCCESS; + } + if ( convertLangPath && !convertLangPath.Get().empty() ) { Sys::windowAttachConsole(); IOStreamFile sfile( convertLangPath.Get() ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index 543faedf9..518244d27 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -8,8 +8,12 @@ #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 @@ -57,8 +61,8 @@ class App : public UICodeEditorSplitter::Client { void runCommand( const std::string& command ); - void loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool sync, - bool stdOutLogs, bool disableFileLogs ); + void loadConfig( const LogLevel& logLevel, const Sizeu& displaySize, bool sync, bool stdOutLogs, + bool disableFileLogs ); void saveConfig(); @@ -175,6 +179,8 @@ class App : public UICodeEditorSplitter::Client { void createNewTerminal(); + UIStatusBar* getStatusBar() const { return mStatusBar; } + template void registerUnlockedCommands( T& t ) { t.setCommand( "keybindings", [&] { loadFileFromPath( mKeybindingsPath ); } ); t.setCommand( "debug-draw-boxes-toggle", [&] { debugDrawBoxesToggle(); } ); @@ -220,7 +226,13 @@ class App : public UICodeEditorSplitter::Client { t.setCommand( "console-toggle", [&] { consoleToggle(); } ); t.setCommand( "find-replace", [&] { showFindView(); } ); t.setCommand( "open-global-search", [&] { showGlobalSearch( false ); } ); + t.setCommand( "toggle-global-search", + [&] { mGlobalSearchController->toggleGlobalSearchBar(); } ); + t.setCommand( "toggle-status-build-output", + [&] { mStatusBuildOutputController->toggle(); } ); + t.setCommand( "toggle-status-terminal", [&] { mStatusTerminalController->toggle(); } ); t.setCommand( "open-locatebar", [&] { mUniversalLocator->showLocateBar(); } ); + t.setCommand( "toggle-locatebar", [&] { mUniversalLocator->toggleLocateBar(); } ); t.setCommand( "open-command-palette", [&] { mUniversalLocator->showCommandPalette(); } ); t.setCommand( "open-workspace-symbol-search", [&] { mUniversalLocator->showWorkspaceSymbol(); } ); @@ -234,6 +246,7 @@ class App : public UICodeEditorSplitter::Client { t.setCommand( "ecode-source", [&] { ecodeSource(); } ); t.setCommand( "ui-scale-factor", [&] { setUIScaleFactor(); } ); t.setCommand( "show-side-panel", [&] { switchSidePanel(); } ); + t.setCommand( "toggle-status-bar", [&] { switchStatusBar(); } ); t.setCommand( "editor-font-size", [&] { setEditorFontSize(); } ); t.setCommand( "terminal-font-size", [&] { setTerminalFontSize(); } ); t.setCommand( "ui-font-size", [&] { setUIFontSize(); } ); @@ -351,6 +364,20 @@ class App : public UICodeEditorSplitter::Client { void createAndShowRecentFilesPopUpMenu( Node* recentFilesBut ); + UISplitter* getMainSplitter() const; + + StatusTerminalController* getStatusTerminalController() const; + + void hideStatusTerminal(); + + void hideStatusBuildOutput(); + + StatusBuildOutputController* getStatusBuildOutputController() const; + + void switchStatusBar(); + + void showStatusBar( bool show ); + protected: std::vector mArgs; EE::Window::Window* mWindow{ nullptr }; @@ -411,6 +438,9 @@ class App : public UICodeEditorSplitter::Client { 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; @@ -418,6 +448,8 @@ class App : public UICodeEditorSplitter::Client { std::unique_ptr mSettings; std::string mFileToOpen; UITheme* mTheme{ nullptr }; + UIStatusBar* mStatusBar{ nullptr }; + UISplitter* mMainSplitter{ nullptr }; void saveAllProcess(); diff --git a/src/tools/ecode/globalsearchcontroller.cpp b/src/tools/ecode/globalsearchcontroller.cpp index 16f37ff2d..1e0c9f233 100644 --- a/src/tools/ecode/globalsearchcontroller.cpp +++ b/src/tools/ecode/globalsearchcontroller.cpp @@ -306,6 +306,8 @@ void GlobalSearchController::initGlobalSearchBar( void GlobalSearchController::showGlobalSearch( bool searchReplace ) { mApp->hideLocateBar(); mApp->hideSearchBar(); + mApp->hideStatusTerminal(); + mApp->hideStatusBuildOutput(); bool wasReplaceTree = mGlobalSearchTreeReplace == mGlobalSearchTree; mGlobalSearchTree = searchReplace ? mGlobalSearchTreeReplace : mGlobalSearchTreeSearch; mGlobalSearchTreeSearch->setVisible( !searchReplace ); @@ -339,6 +341,7 @@ void GlobalSearchController::showGlobalSearch( bool searchReplace ) { } } updateGlobalSearchBar(); + mApp->getStatusBar()->updateState(); } void GlobalSearchController::updateColorScheme( const SyntaxColorScheme& colorScheme ) { @@ -400,6 +403,15 @@ void GlobalSearchController::hideGlobalSearchBar() { auto* loader = mGlobalSearchTree->getParent()->find( "loader" ); if ( loader ) loader->setVisible( false ); + mApp->getStatusBar()->updateState(); +} + +void GlobalSearchController::toggleGlobalSearchBar() { + if ( mGlobalSearchBarLayout->isVisible() ) { + mGlobalSearchBarLayout->execute( "close-global-searchbar" ); + } else { + showGlobalSearch(); + } } void GlobalSearchController::updateGlobalSearchBarResults( diff --git a/src/tools/ecode/globalsearchcontroller.hpp b/src/tools/ecode/globalsearchcontroller.hpp index 7ff970974..41ec3980c 100644 --- a/src/tools/ecode/globalsearchcontroller.hpp +++ b/src/tools/ecode/globalsearchcontroller.hpp @@ -39,6 +39,8 @@ class GlobalSearchController { void hideGlobalSearchBar(); + void toggleGlobalSearchBar(); + void updateGlobalSearchBarResults( const std::string& search, std::shared_ptr model, bool searchReplace, bool isEscaped ); diff --git a/src/tools/ecode/projectbuild.cpp b/src/tools/ecode/projectbuild.cpp index 6ce886c0b..400e8f3cc 100644 --- a/src/tools/ecode/projectbuild.cpp +++ b/src/tools/ecode/projectbuild.cpp @@ -53,6 +53,12 @@ ProjectBuildManager::ProjectBuildManager( const std::string& projectRoot, } else { load(); } +} + +ProjectBuildManager::~ProjectBuildManager() { + mShuttingDown = true; + while ( mLoading ) + Sys::sleep( Milliseconds( 0.1f ) ); }; static bool isValidType( const std::string& typeStr ) { diff --git a/src/tools/ecode/projectbuild.hpp b/src/tools/ecode/projectbuild.hpp index 476b6f986..99f62e01e 100644 --- a/src/tools/ecode/projectbuild.hpp +++ b/src/tools/ecode/projectbuild.hpp @@ -161,6 +161,8 @@ class ProjectBuildManager { public: ProjectBuildManager( const std::string& projectRoot, std::shared_ptr pool ); + ~ProjectBuildManager(); + ProjectBuildCommandsRes generateBuildCommands( const std::string& buildName, std::function i18n, @@ -183,6 +185,7 @@ class ProjectBuildManager { std::shared_ptr mThreadPool; bool mLoaded{ false }; bool mLoading{ false }; + bool mShuttingDown{ false }; bool load(); }; diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index 86e33bc2e..3d12a37f3 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -889,6 +889,10 @@ UIMenu* SettingsMenu::createWindowMenu() { ->addCheckBox( i18n( "show_side_panel", "Show Side Panel" ), mApp->getConfig().ui.showSidePanel, getKeybind( "switch-side-panel" ) ) ->setId( "show-side-panel" ); + mWindowMenu + ->addCheckBox( i18n( "show_status_bar", "Show Status Bar" ), + mApp->getConfig().ui.showSidePanel, getKeybind( "toggle-status-bar" ) ) + ->setId( "toggle-status-bar" ); mWindowMenu ->add( i18n( "move_panel_left", "Move panel to left..." ), findIcon( "layout-left" ), getKeybind( "layout-left" ) ) diff --git a/src/tools/ecode/statusbuildoutputcontroller.cpp b/src/tools/ecode/statusbuildoutputcontroller.cpp new file mode 100644 index 000000000..5fcea057a --- /dev/null +++ b/src/tools/ecode/statusbuildoutputcontroller.cpp @@ -0,0 +1,71 @@ +#include "statusbuildoutputcontroller.hpp" +#include "ecode.hpp" + +namespace ecode { + +StatusBuildOutputController::StatusBuildOutputController( UISplitter* mainSplitter, + UISceneNode* uiSceneNode, App* app ) : + mMainSplitter( mainSplitter ), + mUISceneNode( uiSceneNode ), + mApp( app ), + mSplitter( mApp->getSplitter() ) {} + +void StatusBuildOutputController::toggle() { + if ( nullptr == mContainer ) { + show(); + return; + } + + if ( mMainSplitter->getLastWidget() != nullptr ) { + if ( mMainSplitter->getLastWidget() == mContainer ) { + hide(); + } else { + show(); + } + } else { + show(); + } +} + +void StatusBuildOutputController::hide() { + if ( mContainer && mContainer->isVisible() ) { + mContainer->setParent( mUISceneNode ); + mContainer->setVisible( false ); + mApp->getStatusBar()->updateState(); + if ( mSplitter->getCurWidget() ) + mSplitter->getCurWidget()->setFocus(); + } +} + +void StatusBuildOutputController::show() { + if ( nullptr == mContainer ) { + mMainSplitter->updateLayout(); + mContainer = createContainer(); + mContainer->setId( "build_output" ); + mContainer->setVisible( false ); + } + + if ( !mContainer->isVisible() ) { + mApp->hideLocateBar(); + mApp->hideSearchBar(); + mApp->hideGlobalSearchBar(); + if ( mMainSplitter->getLastWidget() != nullptr ) { + mMainSplitter->getLastWidget()->setVisible( false ); + mMainSplitter->getLastWidget()->setParent( mUISceneNode ); + } + mContainer->setParent( mMainSplitter ); + mContainer->setVisible( true ); + mContainer->setFocus(); + mApp->getStatusBar()->updateState(); + } +} + +UICodeEditor* StatusBuildOutputController::createContainer() { + UICodeEditor* editor = UICodeEditor::NewOpt( true, true ); + editor->setLocked( true ); + editor->setLineBreakingColumn( 0 ); + editor->setShowLineNumber( false ); + return editor; +} + +} // namespace ecode diff --git a/src/tools/ecode/statusbuildoutputcontroller.hpp b/src/tools/ecode/statusbuildoutputcontroller.hpp new file mode 100644 index 000000000..3c91a086a --- /dev/null +++ b/src/tools/ecode/statusbuildoutputcontroller.hpp @@ -0,0 +1,39 @@ +#ifndef ECODE_STATUSBUILDOUTPUTCONTROLLER_HPP +#define ECODE_STATUSBUILDOUTPUTCONTROLLER_HPP + +#include +#include +#include +#include + +using namespace EE; +using namespace EE::UI; +using namespace EE::UI::Tools; + +namespace ecode { + +class App; + +class StatusBuildOutputController { + public: + StatusBuildOutputController( UISplitter* mainSplitter, UISceneNode* uiSceneNode, App* app ); + + void toggle(); + + void hide(); + + void show(); + + protected: + UISplitter* mMainSplitter{ nullptr }; + UISceneNode* mUISceneNode{ nullptr }; + App* mApp{ nullptr }; + UICodeEditorSplitter* mSplitter{ nullptr }; + UICodeEditor* mContainer{ nullptr }; + + UICodeEditor* createContainer(); +}; + +} // namespace ecode + +#endif // ECODE_STATUSBUILDOUTPUTCONTROLLER_HPP diff --git a/src/tools/ecode/statusterminalcontroller.cpp b/src/tools/ecode/statusterminalcontroller.cpp new file mode 100644 index 000000000..2678270be --- /dev/null +++ b/src/tools/ecode/statusterminalcontroller.cpp @@ -0,0 +1,131 @@ +#include "statusterminalcontroller.hpp" +#include "ecode.hpp" + +namespace ecode { + +StatusTerminalController::StatusTerminalController( UISplitter* mainSplitter, + UISceneNode* uiSceneNode, App* app ) : + mMainSplitter( mainSplitter ), + mUISceneNode( uiSceneNode ), + mApp( app ), + mSplitter( mApp->getSplitter() ) {} + +void StatusTerminalController::toggle() { + if ( nullptr == mUITerminal ) { + show(); + return; + } + + if ( mMainSplitter->getLastWidget() != nullptr ) { + if ( mMainSplitter->getLastWidget() == mUITerminal ) { + hide(); + } else { + show(); + } + } else { + show(); + } +} + +void StatusTerminalController::hide() { + if ( mUITerminal && mUITerminal->isVisible() ) { + mUITerminal->setParent( mUISceneNode ); + mUITerminal->setVisible( false ); + mApp->getStatusBar()->updateState(); + if ( mSplitter->getCurWidget() ) + mSplitter->getCurWidget()->setFocus(); + } +} + +void StatusTerminalController::show() { + if ( nullptr == mUITerminal ) { + mMainSplitter->updateLayout(); + mUITerminal = createTerminal(); + mUITerminal->setId( "terminal" ); + mUITerminal->setVisible( false ); + } + + if ( !mUITerminal->isVisible() ) { + mApp->hideLocateBar(); + mApp->hideSearchBar(); + mApp->hideGlobalSearchBar(); + if ( mMainSplitter->getLastWidget() != nullptr ) { + mMainSplitter->getLastWidget()->setVisible( false ); + mMainSplitter->getLastWidget()->setParent( mUISceneNode ); + } + mUITerminal->setParent( mMainSplitter ); + mUITerminal->setVisible( true ); + mUITerminal->setFocus(); + mApp->getStatusBar()->updateState(); + } +} + +UITerminal* StatusTerminalController::createTerminal( const std::string& workingDir, + std::string program, + const std::vector& args ) { + Sizef initialSize( 16, 16 ); + if ( program.empty() && !mApp->termConfig().shell.empty() ) + program = mApp->termConfig().shell; + + UITerminal* term = UITerminal::New( + mApp->getTerminalFont() ? mApp->getTerminalFont() : mApp->getFontMono(), + mApp->termConfig().fontSize.asPixels( 0, Sizef(), mApp->getDisplayDPI() ), initialSize, + program, args, !workingDir.empty() ? workingDir : mApp->getCurrentWorkingDir(), 10000, + nullptr, false ); + if ( term->getTerm() == nullptr ) { + UIMessageBox* msgBox = UIMessageBox::New( + UIMessageBox::OK, + mApp->i18n( "feature_not_supported_in_os", + "This feature is not supported in this Operating System" ) ); + msgBox->showWhenReady(); + return nullptr; + } + + const auto& terminalColorSchemes = mApp->getTerminalManager()->getTerminalColorSchemes(); + const auto& currentTerminalColorScheme = + mApp->getTerminalManager()->getTerminalCurrentColorScheme(); + auto csIt = terminalColorSchemes.find( currentTerminalColorScheme ); + term->getTerm()->getTerminal()->setAllowMemoryTrimnming( true ); + term->setColorScheme( csIt != terminalColorSchemes.end() + ? terminalColorSchemes.at( currentTerminalColorScheme ) + : TerminalColorScheme::getDefault() ); + term->addKeyBinds( mApp->getLocalKeybindings() ); + term->addKeyBinds( UICodeEditorSplitter::getLocalDefaultKeybindings() ); + term->addKeyBinds( { { { KEY_E, KEYMOD_CTRL | KEYMOD_LALT | KEYMOD_SHIFT }, + UITerminal::getExclusiveModeToggleCommandName() } } ); + // Remove the keybinds that are problematic for a terminal + term->getKeyBindings().removeCommandsKeybind( + { "open-file", "download-file-web", "open-folder", "debug-draw-highlight-toggle", + "debug-draw-boxes-toggle", "debug-draw-debug-data", "debug-widget-tree-view", + "open-locatebar", "open-command-palette", "open-global-search", "menu-toggle", + "console-toggle", "go-to-line" } ); + term->setCommand( "switch-to-previous-colorscheme", [&] { + auto it = mApp->getTerminalManager()->getTerminalColorSchemes().find( + mApp->getTerminalManager()->getTerminalCurrentColorScheme() ); + auto prev = std::prev( it, 1 ); + if ( prev != mApp->getTerminalManager()->getTerminalColorSchemes().end() ) { + mApp->getTerminalManager()->setTerminalColorScheme( prev->first ); + } else { + mApp->getTerminalManager()->setTerminalColorScheme( + mApp->getTerminalManager()->getTerminalColorSchemes().rbegin()->first ); + } + } ); + term->setCommand( "switch-to-next-colorscheme", [&] { + auto it = mApp->getTerminalManager()->getTerminalColorSchemes().find( + mApp->getTerminalManager()->getTerminalCurrentColorScheme() ); + mApp->getTerminalManager()->setTerminalColorScheme( + ++it != mApp->getTerminalManager()->getTerminalColorSchemes().end() + ? it->first + : mApp->getTerminalManager()->getTerminalColorSchemes().begin()->first ); + } ); + term->setCommand( UITerminal::getExclusiveModeToggleCommandName(), [term, this] { + term->setExclusiveMode( !term->getExclusiveMode() ); + mApp->updateTerminalMenu(); + } ); + mApp->registerUnlockedCommands( *term ); + mApp->getSplitter()->registerSplitterCommands( *term ); + term->setFocus(); + return term; +} + +} // namespace ecode diff --git a/src/tools/ecode/statusterminalcontroller.hpp b/src/tools/ecode/statusterminalcontroller.hpp new file mode 100644 index 000000000..167afd5c8 --- /dev/null +++ b/src/tools/ecode/statusterminalcontroller.hpp @@ -0,0 +1,41 @@ +#ifndef ECODE_STATUSTERMINALCONTROLLER_HPP +#define ECODE_STATUSTERMINALCONTROLLER_HPP + +#include +#include +#include +#include + +using namespace EE; +using namespace EE::UI; +using namespace EE::UI::Tools; +using namespace eterm::UI; + +namespace ecode { + +class App; + +class StatusTerminalController { + public: + StatusTerminalController( UISplitter* mainSplitter, UISceneNode* uiSceneNode, App* app ); + + void toggle(); + + void hide(); + + void show(); + + protected: + UISplitter* mMainSplitter{ nullptr }; + UISceneNode* mUISceneNode{ nullptr }; + App* mApp{ nullptr }; + UITerminal* mUITerminal{ nullptr }; + UICodeEditorSplitter* mSplitter{ nullptr }; + + UITerminal* createTerminal( const std::string& workingDir = "", std::string program = "", + const std::vector& args = {} ); +}; + +} // namespace ecode + +#endif // ECODE_STATUSTERMINALCONTROLLER_HPP diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 27f079113..a8c390c8e 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -267,13 +267,14 @@ UITerminal* TerminalManager::createNewTerminal( const std::string& title, UITabW return nullptr; } - term->getTerm()->getTerminal()->setAllowMemoryTrimnming( true ); auto ret = mApp->getSplitter()->createWidgetInTabWidget( tabWidget, term, title.empty() ? mApp->i18n( "shell", "Shell" ).toUtf8() : title, true ); - mApp->getSplitter()->removeUnusedTab( tabWidget, true, false ); ret.first->setIcon( mApp->findIcon( "filetype-bash" ) ); + mApp->getSplitter()->removeUnusedTab( tabWidget, true, false ); + term->setTitle( title ); auto csIt = mTerminalColorSchemes.find( mTerminalCurrentColorScheme ); + term->getTerm()->getTerminal()->setAllowMemoryTrimnming( true ); term->setColorScheme( csIt != mTerminalColorSchemes.end() ? mTerminalColorSchemes.at( mTerminalCurrentColorScheme ) : TerminalColorScheme::getDefault() ); diff --git a/src/tools/ecode/terminalmanager.hpp b/src/tools/ecode/terminalmanager.hpp index c40b87fa0..f039de8ed 100644 --- a/src/tools/ecode/terminalmanager.hpp +++ b/src/tools/ecode/terminalmanager.hpp @@ -48,6 +48,8 @@ class TerminalManager { void configureTerminalShell(); + const std::string& getTerminalCurrentColorScheme() { return mTerminalCurrentColorScheme; } + protected: App* mApp; std::string mTerminalColorSchemesPath; diff --git a/src/tools/ecode/uistatusbar.cpp b/src/tools/ecode/uistatusbar.cpp new file mode 100644 index 000000000..3ed839ea9 --- /dev/null +++ b/src/tools/ecode/uistatusbar.cpp @@ -0,0 +1,90 @@ +#include "uistatusbar.hpp" +#include "ecode.hpp" +#include +#include + +namespace ecode { + +UIStatusBar* UIStatusBar::New() { + return eeNew( UIStatusBar, () ); +} + +UIStatusBar::UIStatusBar() : + UILinearLayout( "statusbar", UIOrientation::Horizontal ), + WidgetCommandExecuter( getUISceneNode()->getWindow()->getInput() ) {} + +void UIStatusBar::updateState() { + getParent()->forEachChild( [this]( Node* node ) { + UIWidget* but = find( "status_" + node->getId() ); + if ( but && but != this ) { + if ( node->isVisible() ) { + but->addClass( "selected" ); + } else { + but->removeClass( "selected" ); + } + } + } ); + + UIWidget* termBut = find( "status_terminal" ); + if ( termBut ) + termBut->removeClass( "selected" ); + UIWidget* boBut = find( "status_build_output" ); + if ( boBut ) + boBut->removeClass( "selected" ); + + if ( mApp->getMainSplitter() ) { + if ( mApp->getMainSplitter()->getLastWidget() ) { + UIWidget* widget = mApp->getMainSplitter()->getLastWidget(); + UIWidget* but = find( "status_" + widget->getId() ); + if ( but && but != this ) { + if ( widget->isVisible() ) { + but->addClass( "selected" ); + } else { + but->removeClass( "selected" ); + } + } + } + } +} + +Uint32 UIStatusBar::onMessage( const NodeMessage* msg ) { + if ( !isVisible() || nullptr == mApp || msg->getMsg() != NodeMessage::MouseClick || + 0 == ( msg->getFlags() & EE_BUTTON_LMASK ) || !msg->getSender()->isWidget() ) + return 0; + + UIWidget* widget = msg->getSender()->asType(); + + if ( !widget->hasClass( "status_but" ) ) + return 0; + + int ret = 0; + + if ( widget->getId() == "status_locate_bar" ) { + mApp->getUniversalLocator()->toggleLocateBar(); + ret = 1; + } else if ( widget->getId() == "status_global_search_bar" ) { + mApp->getGlobalSearchController()->toggleGlobalSearchBar(); + ret = 1; + } else if ( widget->getId() == "status_terminal" ) { + mApp->getStatusTerminalController()->toggle(); + ret = 1; + } else if ( widget->getId() == "status_build_output" ) { + mApp->getStatusBuildOutputController()->toggle(); + ret = 1; + } + + if ( ret ) + updateState(); + return ret; +} + +void UIStatusBar::setApp( App* app ) { + mApp = app; +} + +void UIStatusBar::onVisibilityChange() { + if ( isVisible() ) + updateState(); +} + +} // namespace ecode diff --git a/src/tools/ecode/uistatusbar.hpp b/src/tools/ecode/uistatusbar.hpp new file mode 100644 index 000000000..b867a14dc --- /dev/null +++ b/src/tools/ecode/uistatusbar.hpp @@ -0,0 +1,35 @@ +#ifndef ECODE_UISTATUSBAR_HPP +#define ECODE_UISTATUSBAR_HPP + +#include +#include + +using namespace EE; +using namespace EE::UI; + +namespace ecode { + +class App; + +class UIStatusBar : public UILinearLayout, public WidgetCommandExecuter { + public: + static UIStatusBar* New(); + + UIStatusBar(); + + void updateState(); + + protected: + friend class App; + virtual Uint32 onMessage( const NodeMessage* msg ); + + void setApp( App* app ); + + App* mApp{ nullptr }; + + virtual void onVisibilityChange(); +}; + +} // namespace ecode + +#endif // ECODE_UISTATUSBAR_HPP diff --git a/src/tools/ecode/universallocator.cpp b/src/tools/ecode/universallocator.cpp index e65a8712f..120c7f52d 100644 --- a/src/tools/ecode/universallocator.cpp +++ b/src/tools/ecode/universallocator.cpp @@ -123,6 +123,15 @@ UniversalLocator::UniversalLocator( UICodeEditorSplitter* editorSplitter, UIScen void UniversalLocator::hideLocateBar() { mLocateBarLayout->setVisible( false ); mLocateTable->setVisible( false ); + mApp->getStatusBar()->updateState(); +} + +void UniversalLocator::toggleLocateBar() { + if ( mLocateBarLayout->isVisible() ) { + mLocateBarLayout->execute( "close-locatebar" ); + } else { + showLocateBar(); + } } void UniversalLocator::updateFilesTable() { @@ -379,6 +388,8 @@ void UniversalLocator::updateLocateBar() { void UniversalLocator::showBar() { mApp->hideGlobalSearchBar(); mApp->hideSearchBar(); + mApp->hideStatusTerminal(); + mApp->hideStatusBuildOutput(); mLocateBarLayout->setVisible( true ); mLocateInput->setFocus(); @@ -418,6 +429,7 @@ void UniversalLocator::showLocateBar() { } updateLocateBar(); + mApp->getStatusBar()->updateState(); } void UniversalLocator::showCommandPalette() { @@ -428,6 +440,7 @@ void UniversalLocator::showCommandPalette() { updateCommandPaletteTable(); updateLocateBar(); + mApp->getStatusBar()->updateState(); } void UniversalLocator::showWorkspaceSymbol() { @@ -438,6 +451,7 @@ void UniversalLocator::showWorkspaceSymbol() { requestWorkspaceSymbol(); updateLocateBar(); + mApp->getStatusBar()->updateState(); } void UniversalLocator::showDocumentSymbol() { @@ -448,6 +462,7 @@ void UniversalLocator::showDocumentSymbol() { requestDocumentSymbol(); updateLocateBar(); + mApp->getStatusBar()->updateState(); } void UniversalLocator::onCodeEditorFocusChange( UICodeEditor* editor ) { diff --git a/src/tools/ecode/universallocator.hpp b/src/tools/ecode/universallocator.hpp index ace461099..4c8091d92 100644 --- a/src/tools/ecode/universallocator.hpp +++ b/src/tools/ecode/universallocator.hpp @@ -22,6 +22,8 @@ class UniversalLocator { void hideLocateBar(); + void toggleLocateBar(); + void showCommandPalette(); void goToLine();