diff --git a/include/eepp/ui/tools/uicodeeditorsplitter.hpp b/include/eepp/ui/tools/uicodeeditorsplitter.hpp index eb7a145cc..ca759b6aa 100644 --- a/include/eepp/ui/tools/uicodeeditorsplitter.hpp +++ b/include/eepp/ui/tools/uicodeeditorsplitter.hpp @@ -272,6 +272,10 @@ class EE_API UICodeEditorSplitter { bool curEditorExists() const; + bool hasSplit() const; + + UIOrientation getMainSplitOrientation() const; + protected: UISceneNode* mUISceneNode{ nullptr }; UICodeEditor* mCurEditor{ nullptr }; diff --git a/src/eepp/ui/tools/uicodeeditorsplitter.cpp b/src/eepp/ui/tools/uicodeeditorsplitter.cpp index b99382dcd..266388c9b 100644 --- a/src/eepp/ui/tools/uicodeeditorsplitter.cpp +++ b/src/eepp/ui/tools/uicodeeditorsplitter.cpp @@ -1065,6 +1065,25 @@ bool UICodeEditorSplitter::curEditorExists() const { return found || mCurEditor == nullptr || mAboutToAddEditor == mCurEditor || mFirstCodeEditor; } +bool UICodeEditorSplitter::hasSplit() const { + return mTabWidgets.size() > 1; +} + +UIOrientation UICodeEditorSplitter::getMainSplitOrientation() const { + if ( !hasSplit() ) + return UIOrientation::Vertical; + + UITab* tab = nullptr; + if ( mTabWidgets[0]->getTabCount() > 0 && ( tab = mTabWidgets[0]->getTab( 0 ) ) && + tab->getOwnedWidget() && tab->getOwnedWidget()->isWidget() ) { + UISplitter* splitter = splitterFromWidget( tab->getOwnedWidget()->asType() ); + if ( splitter ) + return splitter->getOrientation(); + } + + return UIOrientation::Vertical; +} + bool UICodeEditorSplitter::curWidgetExists() const { bool found = false; forEachWidgetStoppable( [&]( UIWidget* widget ) { diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index e872442c9..5e1007ad2 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -145,6 +145,8 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, term.shell = ini.getValue( "terminal", "shell" ); term.fontSize = ini.getValue( "terminal", "font_size", "11dp" ); term.colorScheme = ini.getValue( "terminal", "colorscheme", "eterm" ); + term.newTerminalOrientation = NewTerminalOrientation::fromString( + ini.getValue( "terminal", "new_terminal_orientation", "vertical" ) ); workspace.restoreLastSession = ini.getValueB( "workspace", "restore_last_session", false ); workspace.checkForUpdatesAtStartup = @@ -250,6 +252,8 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValue( "terminal", "shell", term.shell ); ini.setValue( "terminal", "font_size", term.fontSize.toString() ); ini.setValue( "terminal", "colorscheme", term.colorScheme ); + ini.setValue( "terminal", "new_terminal_orientation", + NewTerminalOrientation::toString( term.newTerminalOrientation ) ); ini.setValueB( "window", "vsync", context.VSync ); ini.setValue( "window", "glversion", diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index 4410fda80..f557ce699 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -105,10 +105,37 @@ struct ProjectDocumentConfig { ProjectDocumentConfig( const DocumentConfig& doc ) { this->doc = doc; } }; +class NewTerminalOrientation { + public: + enum Orientation { Same, Vertical, Horizontal }; + + static NewTerminalOrientation::Orientation fromString( const std::string& orientation ) { + if ( "same" == orientation ) + return Orientation::Same; + if ( "horizontal" == orientation ) + return Orientation::Horizontal; + return Orientation::Vertical; + } + + static std::string toString( const Orientation& orientation ) { + switch ( orientation ) { + case Orientation::Vertical: + return "vertical"; + case Orientation::Horizontal: + return "horizontal"; + case Orientation::Same: + default: + return "same"; + } + } +}; + struct TerminalConfig { std::string shell; std::string colorScheme{ "eterm" }; StyleSheetLength fontSize{ 11, StyleSheetLength::Dp }; + NewTerminalOrientation::Orientation newTerminalOrientation{ + NewTerminalOrientation::Horizontal }; }; struct WorkspaceConfig { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index eb3913290..5631c3f45 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2118,6 +2118,40 @@ void App::toggleSettingsMenu() { mSettings->toggleSettingsMenu(); } +void App::createNewTerminal() { + if ( mSplitter->hasSplit() ) { + if ( mSplitter->getTabWidgets().size() == 2 ) { + UIOrientation orientation = mSplitter->getMainSplitOrientation(); + if ( mConfig.term.newTerminalOrientation == NewTerminalOrientation::Vertical && + orientation == UIOrientation::Horizontal ) { + mTerminalManager->createNewTerminal( "", mSplitter->getTabWidgets()[1] ); + return; + } + if ( mConfig.term.newTerminalOrientation == NewTerminalOrientation::Horizontal && + orientation == UIOrientation::Vertical ) { + mTerminalManager->createNewTerminal( "", mSplitter->getTabWidgets()[1] ); + return; + } + } + mTerminalManager->createNewTerminal(); + } else { + switch ( mConfig.term.newTerminalOrientation ) { + case NewTerminalOrientation::Vertical: { + runCommand( "terminal-split-right" ); + break; + } + case NewTerminalOrientation::Horizontal: { + runCommand( "terminal-split-bottom" ); + break; + } + case NewTerminalOrientation::Same: { + mTerminalManager->createNewTerminal(); + break; + } + } + } +} + std::string App::getNewFilePath( const FileInfo& file, UIMessageBox* msgBox, bool keepDir ) { auto fileName( msgBox->getTextInput()->getText().toUtf8() ); auto folderPath( file.getDirectoryPath() ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index d189a11c9..b177c7c7d 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -169,6 +169,8 @@ class App : public UICodeEditorSplitter::Client { void toggleSettingsMenu(); + void createNewTerminal(); + template void registerUnlockedCommands( T& t ) { t.setCommand( "keybindings", [&] { loadFileFromPath( mKeybindingsPath ); } ); t.setCommand( "debug-draw-boxes-toggle", [&] { debugDrawBoxesToggle(); } ); @@ -180,7 +182,7 @@ class App : public UICodeEditorSplitter::Client { t.setCommand( "download-file-web", [&] { downloadFileWebDialog(); } ); t.setCommand( "move-panel-left", [&] { panelPosition( PanelPosition::Left ); } ); t.setCommand( "move-panel-right", [&] { panelPosition( PanelPosition::Right ); } ); - t.setCommand( "create-new-terminal", [&] { mTerminalManager->createNewTerminal(); } ); + t.setCommand( "create-new-terminal", [&] { createNewTerminal(); } ); t.setCommand( "terminal-split-right", [&] { auto cwd = getCurrentWorkingDir(); mSplitter->split( UICodeEditorSplitter::SplitDirection::Right, diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index 666f49a79..db36825a4 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -347,7 +347,7 @@ UIMenu* SettingsMenu::createDocumentMenu() { } ); // **** GLOBAL SETTINGS **** - mDocMenu->addSeparator(); + mDocMenu->addSeparator()->setId( "end_current_document" ); UIPopUpMenu* globalMenu = UIPopUpMenu::New(); mDocMenu->addSubMenu( i18n( "global_settings", "Global Settings" ), @@ -703,19 +703,13 @@ UIMenu* SettingsMenu::createDocumentMenu() { UIMenu* SettingsMenu::createTerminalMenu() { mTerminalMenu = UIPopUpMenu::New(); -#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN - UIMenuSubMenu* termColorSchemeMenu = mTerminalMenu->addSubMenu( - i18n( "terminal_color_scheme", "Terminal Color Scheme" ), findIcon( "palette" ), - mApp->getTerminalManager()->createColorSchemeMenu() ); - termColorSchemeMenu->addEventListener( - Event::OnMenuShow, [&, termColorSchemeMenu]( const Event* ) { - mApp->getTerminalManager()->updateMenuColorScheme( termColorSchemeMenu ); - } ); -#endif + mTerminalMenu->add( i18n( "current_terminal", "Current Terminal" ) ) + ->setTextAlign( UI_HALIGN_CENTER ); UIMenuCheckBox* exclusiveChk = mTerminalMenu->addCheckBox( i18n( "exclusive_mode", "Exclusive Mode" ), false, getKeybind( UITerminal::getExclusiveModeToggleCommandName() ) ); + exclusiveChk ->setTooltipText( i18n( "exclusive_mode_tooltip", @@ -728,13 +722,48 @@ UIMenu* SettingsMenu::createTerminalMenu() { getKeybind( "terminal-rename" ) ) ->setId( "terminal-rename" ); - mTerminalMenu->addSeparator(); + mTerminalMenu->addSeparator()->setId( "end_current_terminal" ); + +#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN + UIMenuSubMenu* termColorSchemeMenu = mTerminalMenu->addSubMenu( + i18n( "terminal_color_scheme", "Terminal Color Scheme" ), findIcon( "palette" ), + mApp->getTerminalManager()->createColorSchemeMenu() ); + termColorSchemeMenu->addEventListener( + Event::OnMenuShow, [&, termColorSchemeMenu]( const Event* ) { + mApp->getTerminalManager()->updateMenuColorScheme( termColorSchemeMenu ); + } ); +#endif + + UIPopUpMenu* newTerminalBehaviorSubMenu = UIPopUpMenu::New(); + auto currentOrientation = + NewTerminalOrientation::toString( mApp->getConfig().term.newTerminalOrientation ); + + newTerminalBehaviorSubMenu + ->addRadioButton( i18n( "open_in_same_tabbar", "Open In Current Tab Bar" ) ) + ->setActive( currentOrientation == "same" ) + ->setId( "same" ); + newTerminalBehaviorSubMenu + ->addRadioButton( i18n( "open_in_vertical_split", "Open In New Vertical Split" ) ) + ->setActive( currentOrientation == "vertical" ) + ->setId( "vertical" ); + newTerminalBehaviorSubMenu + ->addRadioButton( i18n( "open_in_horizontal_split", "Open In New Horizontal Split" ) ) + ->setActive( currentOrientation == "horizontal" ) + ->setId( "horizontal" ); + + mTerminalMenu->addSubMenu( i18n( "new_terminal_behavior", "New Terminal Behavior" ), + findIcon( "terminal" ), newTerminalBehaviorSubMenu ); mTerminalMenu ->add( i18n( "configure_terminal_shell", "Configure Terminal Shell" ), findIcon( "terminal" ), getKeybind( "configure-terminal-shell" ) ) ->setId( "configure-terminal-shell" ); + newTerminalBehaviorSubMenu->on( Event::OnItemClicked, [&]( const Event* event ) { + const std::string& id( event->getNode()->getId() ); + mApp->getConfig().term.newTerminalOrientation = NewTerminalOrientation::fromString( id ); + } ); + mTerminalMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) { const std::string& id( event->getNode()->getId() ); if ( mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) { @@ -745,6 +774,8 @@ UIMenu* SettingsMenu::createTerminalMenu() { } else { terminal->execute( id ); } + } else { + runCommand( id ); } } ); @@ -1235,13 +1266,6 @@ UIPopUpMenu* SettingsMenu::createToolsMenu() { mToolsMenu->addSeparator(); - mToolsMenu - ->add( i18n( "configure_terminal_shell", "Configure Terminal Shell" ), - findIcon( "terminal" ), getKeybind( "configure-terminal-shell" ) ) - ->setId( "configure-terminal-shell" ); - - mToolsMenu->addSeparator(); - mToolsMenu ->add( i18n( "load_cur_dir_as_folder", "Load current document directory as folder" ), findIcon( "folder" ), getKeybind( "load-current-dir" ) ) @@ -1350,21 +1374,33 @@ void SettingsMenu::updateProjectSettingsMenu() { void SettingsMenu::updateTerminalMenu() { bool enabled = mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ); - mSettingsMenu->getItemId( "term-menu" )->setEnabled( enabled ); + + Node* child = mTerminalMenu->getFirstChild(); + while ( child && child->getId() != "end_current_terminal" ) { + child->setEnabled( enabled ); + child = child->getNextNode(); + } + if ( !enabled ) return; + mTerminalMenu->getItemId( "exclusive-mode" ) ->asType() ->setActive( mSplitter->getCurWidget()->asType()->getExclusiveMode() ); } void SettingsMenu::updateDocumentMenu() { - if ( !mSplitter->getCurWidget() || !mSplitter->getCurWidget()->isType( UI_TYPE_CODEEDITOR ) ) { - mSettingsMenu->getItemId( "doc-menu" )->setEnabled( false ); - return; + bool enabled = + mSplitter->getCurWidget() && mSplitter->getCurWidget()->isType( UI_TYPE_CODEEDITOR ); + + Node* child = mDocMenu->getFirstChild(); + while ( child && child->getId() != "end_current_document" ) { + child->setEnabled( enabled ); + child = child->getNextNode(); } - mSettingsMenu->getItemId( "doc-menu" )->setEnabled( true ); + if ( !enabled ) + return; const TextDocument& doc = mSplitter->getCurEditor()->getDocument(); diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 4eb825bd4..d35c5bc72 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -143,6 +143,10 @@ void TerminalManager::configureTerminalShell() { "sure that the shell is visible in your PATH" ) ); } }; + if ( shellCombo->getListBox()->getVerticalScrollBar() && + found.size() > shellCombo->getDropDownList()->getMaxNumVisibleItems() ) + shellCombo->getListBox()->getVerticalScrollBar()->setClickStep( + shellCombo->getDropDownList()->getMaxNumVisibleItems() / (Float)found.size() ); ok->setFocus(); ok->addMouseClickListener( [&, window, shellCombo]( const MouseEvent* ) { setShellFn( mApp, window, shellCombo ); }, @@ -154,9 +158,7 @@ void TerminalManager::configureTerminalShell() { window->closeWindow(); } ); window->center(); - window->on( Event::OnWindowReady, [ok] ( const Event* ) { - ok->setFocus(); - } ); + window->on( Event::OnWindowReady, [ok]( const Event* ) { ok->setFocus(); } ); } UIMenu* TerminalManager::createColorSchemeMenu() {