Add scrollbar type and mode options for the terminal.

Hack auto-scroll in terminal for Windows 11.
Renamed ScrollViewType and made it global, properties are now `overlay` or `outside`.
Added a couple of goodies for the terminal mode (retain side panel configuration and restore it if no terminals are left).
This commit is contained in:
Martín Lucas Golini
2025-12-21 02:01:37 -03:00
parent 4d6887dbb4
commit 8378f2a1fa
16 changed files with 188 additions and 63 deletions

View File

@@ -1672,11 +1672,11 @@ Defines how the scrollbar should fit inside an scrollable element.
* Applicable to: EE::UI::UIScrollView (ScrollView)
* Data Type: [string-list](#string-list-data-type)
* Value List:
* `inclusive`: The scrollbar is part of the scrollable element container, this means that it will
* `overlay`: The scrollbar is part of the scrollable element container, this means that it will
be on top of the content (scrollbars on mobile usually behave like this).
* `exclusive`: The scrollbar is outside the scrollable element container, this means that it will not
* `outside`: The scrollbar is outside the scrollable element container, this means that it will not
be on top of the content (scrollbars on desktop usually behave like this).
* Default value: `exclusive`
* Default value: `outside`
---

View File

@@ -112,6 +112,8 @@ enum UINodeType {
enum class ScrollBarMode : Uint32 { Auto, AlwaysOn, AlwaysOff };
enum class ScrollViewType { Overlay, Outside };
enum class UIOrientation : Uint32 { Vertical, Horizontal };
enum class SizePolicy : Uint32 { Fixed, MatchParent, WrapContent };

View File

@@ -9,8 +9,6 @@ class UIScrollBar;
class EE_API UIScrollableWidget : public UIWidget {
public:
enum ScrollViewType { Inclusive, Exclusive };
virtual Uint32 getType() const;
virtual bool isType( const Uint32& type ) const;

View File

@@ -9,8 +9,6 @@ class UIScrollBar;
class EE_API UIScrollView : public UITouchDraggableWidget {
public:
enum ScrollViewType { Inclusive, Exclusive };
static UIScrollView* New();
UIScrollView();

View File

@@ -347,11 +347,12 @@ void UIAbstractTableView::columnResizeToContent( const size_t& colIndex ) {
}
Float UIAbstractTableView::getContentSpaceWidth() const {
return eefloor(
getPixelsSize().getWidth() - getPixelsPadding().Left - getPixelsPadding().Right -
( mVScroll->isVisible() && ( mScrollViewType == Exclusive || mVScroll->getAlpha() != 0.f )
? mVScroll->getPixelsSize().getWidth()
: 0 ) );
return eefloor( getPixelsSize().getWidth() - getPixelsPadding().Left -
getPixelsPadding().Right -
( mVScroll->isVisible() && ( mScrollViewType == ScrollViewType::Outside ||
mVScroll->getAlpha() != 0.f )
? mVScroll->getPixelsSize().getWidth()
: 0 ) );
}
void UIAbstractTableView::updateColumnsWidth() {
@@ -360,7 +361,7 @@ void UIAbstractTableView::updateColumnsWidth() {
if ( visibleColumnCount() == 1 && ( col = visibleColumn() ) != -1 ) {
Float width = eemax( getContentSpaceWidth(), getMaxColumnContentWidth( col, true ) );
bool shouldVScrollBeVisible = shouldVerticalScrollBeVisible();
if ( mScrollViewType == Exclusive || mVScroll->getAlpha() != 0.f ) {
if ( mScrollViewType == ScrollViewType::Outside || mVScroll->getAlpha() != 0.f ) {
if ( !mVScroll->isVisible() && shouldVScrollBeVisible )
width -= getVerticalScrollBar()->getPixelsSize().getWidth();
else if ( mVScroll->isVisible() && !shouldVScrollBeVisible )

View File

@@ -6,7 +6,7 @@ namespace EE { namespace UI {
UIScrollableWidget::UIScrollableWidget( const std::string& tag ) :
UIWidget( tag ),
mScrollViewType( Exclusive ),
mScrollViewType( ScrollViewType::Outside ),
mVScrollMode( ScrollBarMode::Auto ),
mHScrollMode( ScrollBarMode::Auto ),
mVScroll( UIScrollBar::NewVertical() ),
@@ -79,7 +79,7 @@ void UIScrollableWidget::setScrollMode( const ScrollBarMode& verticalMode,
}
}
const UIScrollableWidget::ScrollViewType& UIScrollableWidget::getViewType() const {
const ScrollViewType& UIScrollableWidget::getViewType() const {
return mScrollViewType;
}
@@ -109,7 +109,7 @@ void UIScrollableWidget::onContentSizeChange() {
Float totW =
getPixelsSize().getWidth() - getPixelsPadding().Left - getPixelsPadding().Right;
if ( mScrollViewType == Exclusive )
if ( mScrollViewType == ScrollViewType::Outside )
totW -= mVScroll->getPixelsSize().getWidth();
bool visible = contentSize.getWidth() > totW;
@@ -133,12 +133,12 @@ void UIScrollableWidget::onContentSizeChange() {
}
if ( ScrollBarMode::Auto == mHScrollMode ) {
Float totW = getPixelsSize().getWidth() - getPixelsPadding().Left -
getPixelsPadding().Right -
( mVScroll->isVisible() &&
( mScrollViewType == Exclusive || mVScroll->getAlpha() != 0.f )
? mVScroll->getPixelsSize().getWidth()
: 0 );
Float totW =
getPixelsSize().getWidth() - getPixelsPadding().Left - getPixelsPadding().Right -
( mVScroll->isVisible() &&
( mScrollViewType == ScrollViewType::Outside || mVScroll->getAlpha() != 0.f )
? mVScroll->getPixelsSize().getWidth()
: 0 );
bool visible = contentSize.getWidth() > totW;
@@ -147,7 +147,7 @@ void UIScrollableWidget::onContentSizeChange() {
Sizef size = getPixelsSize() - mPaddingPx;
if ( Exclusive == mScrollViewType ) {
if ( ScrollViewType::Outside == mScrollViewType ) {
if ( mVScroll->isVisible() )
size.x -= mVScroll->getPixelsSize().getWidth();
@@ -258,7 +258,7 @@ std::string UIScrollableWidget::getPropertyString( const PropertyDefinition* pro
return mVScroll->getScrollBarType() == UIScrollBar::NoButtons ? "no-buttons"
: "two-buttons";
case PropertyId::ScrollBarMode:
return getViewType() == Inclusive ? "inclusive" : "exclusive";
return getViewType() == ScrollViewType::Overlay ? "overlay" : "outside";
default:
return UIWidget::getPropertyString( propertyDef, propertyIndex );
}
@@ -313,10 +313,10 @@ bool UIScrollableWidget::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::ScrollBarMode: {
std::string val( attribute.asString() );
String::toLowerInPlace( val );
if ( "inclusive" == val || "inside" == val )
setScrollViewType( Inclusive );
else if ( "exclusive" == val || "outside" == val )
setScrollViewType( Exclusive );
if ( "overlay" == val || "inclusive" == val || "inside" == val )
setScrollViewType( ScrollViewType::Overlay );
else if ( "outside" == val || "exclusive" == val || "outside" == val )
setScrollViewType( ScrollViewType::Outside );
break;
}
case PropertyId::VScrollMode: {

View File

@@ -10,7 +10,7 @@ UIScrollView* UIScrollView::New() {
UIScrollView::UIScrollView() :
UITouchDraggableWidget( "scrollview" ),
mViewType( Exclusive ),
mViewType( ScrollViewType::Outside ),
mVScrollMode( ScrollBarMode::Auto ),
mHScrollMode( ScrollBarMode::Auto ),
mVScroll( UIScrollBar::NewVertical() ),
@@ -114,7 +114,7 @@ const ScrollBarMode& UIScrollView::getHorizontalScrollMode() const {
return mHScrollMode;
}
const UIScrollView::ScrollViewType& UIScrollView::getViewType() const {
const ScrollViewType& UIScrollView::getViewType() const {
return mViewType;
}
@@ -175,7 +175,7 @@ void UIScrollView::containerUpdate() {
Sizef size = getSize() - mPadding;
if ( Exclusive == mViewType ) {
if ( ScrollViewType::Outside == mViewType ) {
if ( mVScroll->isVisible() )
size.x -= mVScroll->getSize().getWidth();
@@ -280,7 +280,7 @@ void UIScrollView::onTouchDragValueChange( Vector2f diff ) {
}
bool UIScrollView::isTouchOverAllowedChildren() {
bool ret = mViewType == Exclusive
bool ret = mViewType == ScrollViewType::Outside
? !mVScroll->isMouseOverMeOrChildren() && !mHScroll->isMouseOverMeOrChildren()
: true;
return isMouseOverMeOrChildren() && mScrollView->isMouseOverMeOrChildren() && ret;
@@ -304,7 +304,7 @@ std::string UIScrollView::getPropertyString( const PropertyDefinition* propertyD
return mVScroll->getScrollBarType() == UIScrollBar::NoButtons ? "no-buttons"
: "two-buttons";
case PropertyId::ScrollBarMode:
return getViewType() == Inclusive ? "inclusive" : "exclusive";
return getViewType() == ScrollViewType::Overlay ? "overlay" : "outside";
default:
return UITouchDraggableWidget::getPropertyString( propertyDef, propertyIndex );
}
@@ -326,10 +326,10 @@ bool UIScrollView::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::ScrollBarMode: {
std::string val( attribute.asString() );
String::toLowerInPlace( val );
if ( "inclusive" == val || "inside" == val )
setViewType( Inclusive );
if ( "overlay" == val || "inclusive" == val || "inside" == val )
setViewType( ScrollViewType::Overlay );
else if ( "exclusive" == val || "outside" == val )
setViewType( Exclusive );
setViewType( ScrollViewType::Outside );
break;
}
case PropertyId::VScrollMode: {

View File

@@ -14,15 +14,12 @@ namespace eterm { namespace UI {
class UITerminal : public UIWidget {
public:
enum ScrollViewType { Inclusive, Exclusive };
static UITerminal* New( Font* font, const Float& fontSize, const Sizef& pixelsSize,
const std::string& program = "",
const std::vector<std::string>& args = {},
const std::unordered_map<std::string, std::string>& env = {},
const std::string& workingDir = "", const size_t& historySize = 10000,
IProcessFactory* processFactory = nullptr,
bool useFrameBuffer = false,
IProcessFactory* processFactory = nullptr, bool useFrameBuffer = false,
bool keepAlive = true );
typedef std::function<void()> TerminalCommand;
@@ -95,9 +92,9 @@ class UITerminal : public UIWidget {
UIScrollBar* getVerticalScrollBar() const;
const ScrollViewType& getViewType() const;
const ScrollViewType& getScrollViewType() const;
void setViewType( const ScrollViewType& viewType );
void setScrollViewType( const ScrollViewType& viewType );
virtual bool applyProperty( const StyleSheetProperty& attribute );
@@ -125,7 +122,7 @@ class UITerminal : public UIWidget {
std::map<std::string, TerminalCommand> mCommands;
UIPopUpMenu* mCurrentMenu{ nullptr };
size_t mMenuIconSize{ 16 };
ScrollViewType mViewType{ Inclusive };
ScrollViewType mViewType{ ScrollViewType::Overlay };
ScrollBarMode mVScrollMode{ ScrollBarMode::Auto };
UIScrollBar* mVScroll{ nullptr };
int mScrollOffset;

View File

@@ -147,14 +147,14 @@ const ScrollBarMode& UITerminal::getVerticalScrollMode() const {
return mVScrollMode;
}
const UITerminal::ScrollViewType& UITerminal::getViewType() const {
const ScrollViewType& UITerminal::getScrollViewType() const {
return mViewType;
}
void UITerminal::setViewType( const ScrollViewType& viewType ) {
void UITerminal::setScrollViewType( const ScrollViewType& viewType ) {
if ( viewType != mViewType ) {
mViewType = viewType;
onContentSizeChange();
onSizeChange();
}
}
@@ -171,7 +171,7 @@ void UITerminal::onPaddingChange() {
mTerm->setPadding(
{ mPaddingPx.Left, mPaddingPx.Top,
mPaddingPx.Right +
( mViewType == Exclusive ? mVScroll->getPixelsSize().getWidth() : 0.f ),
( mViewType == ScrollViewType::Outside ? mVScroll->getPixelsSize().getWidth() : 0.f ),
mPaddingPx.Bottom } );
onContentSizeChange();
UIWidget::onPaddingChange();
@@ -235,7 +235,7 @@ std::string UITerminal::getPropertyString( const PropertyDefinition* propertyDef
return mVScroll->getScrollBarType() == UIScrollBar::NoButtons ? "no-buttons"
: "two-buttons";
case PropertyId::ScrollBarMode:
return getViewType() == Inclusive ? "inclusive" : "exclusive";
return getScrollViewType() == ScrollViewType::Overlay ? "overlay" : "outside";
default:
return UIWidget::getPropertyString( propertyDef, propertyIndex );
}
@@ -274,10 +274,10 @@ bool UITerminal::applyProperty( const StyleSheetProperty& attribute ) {
case PropertyId::ScrollBarMode: {
std::string val( attribute.asString() );
String::toLowerInPlace( val );
if ( "inclusive" == val || "inside" == val )
setViewType( Inclusive );
else if ( "exclusive" == val || "outside" == val )
setViewType( Exclusive );
if ( "overlay" == val || "inclusive" == val || "inside" == val )
setScrollViewType( ScrollViewType::Overlay );
else if ( "outside" == val || "exclusive" == val || "outside" == val )
setScrollViewType( ScrollViewType::Outside );
break;
}
case PropertyId::VScrollMode: {
@@ -317,7 +317,11 @@ const std::shared_ptr<TerminalDisplay>& UITerminal::getTerm() const {
void UITerminal::scheduledUpdate( const Time& ) {
if ( !mTerm )
return;
mTerm->update( isMouseOverMeOrChildren() );
auto mousePos = getInput()->getRelativeMousePos();
bool mouseOutsideBounds =
mousePos.y < 0 || mousePos.y > getUISceneNode()->getWindow()->getSize().getHeight();
mTerm->update( isMouseOverMeOrChildren() && !mouseOutsideBounds );
if ( mTerm->isDirty() && isVisible() )
invalidateDraw();
@@ -326,7 +330,7 @@ void UITerminal::scheduledUpdate( const Time& ) {
mVScroll->setVisible( !mTerm->getTerminal()->tisaltscr() )
->setEnabled( !mTerm->getTerminal()->tisaltscr() );
} else if ( ScrollBarMode::Auto == mVScrollMode ) {
if ( mViewType == Inclusive && mMouseClock.getElapsedTime() > Seconds( 1 ) &&
if ( mViewType == ScrollViewType::Overlay && mMouseClock.getElapsedTime() > Seconds( 1 ) &&
!mVScroll->isDragging() )
mVScroll->setVisible( false )->setEnabled( false );
}
@@ -472,7 +476,7 @@ Uint32 UITerminal::onKeyUp( const KeyEvent& ) {
}
Uint32 UITerminal::onMouseMove( const Vector2i& position, const Uint32& flags ) {
if ( mViewType == Inclusive && ScrollBarMode::Auto == mVScrollMode ) {
if ( mViewType == ScrollViewType::Overlay && ScrollBarMode::Auto == mVScrollMode ) {
mMouseClock.restart();
bool visible = !mTerm->getTerminal()->tisaltscr() && getContentSize() > getVisibleArea() &&
!mTerm->getTerminal()->hasSelection();
@@ -518,7 +522,7 @@ void UITerminal::onSizeChange() {
mTerm->setPadding(
{ mPaddingPx.Left, mPaddingPx.Top,
mPaddingPx.Right +
( mViewType == Exclusive ? mVScroll->getPixelsSize().getWidth() : 0.f ),
( mViewType == ScrollViewType::Outside ? mVScroll->getPixelsSize().getWidth() : 0.f ),
mPaddingPx.Bottom } );
onContentSizeChange();
UIWidget::onSizeChange();

View File

@@ -232,6 +232,14 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
term.warnBeforeClosingTab = ini.getValueB( "terminal", "warn_before_closing_tab", true );
term.cursorStyle = TerminalCursorHelper::modeFromString(
ini.getValue( "terminal", "cursor_style", "steady_underline" ) );
term.scrollBarType = ini.getValue( "terminal", "scrollbar_type", "overlay" ) == "overlay"
? ScrollViewType::Overlay
: ScrollViewType::Outside;
auto scrollbarMode = ini.getValue( "terminal", "scrollbar_mode", "auto" );
term.scrollBarMode =
scrollbarMode == "auto"
? ScrollBarMode::Auto
: ( scrollbarMode == "on" ? ScrollBarMode::AlwaysOn : ScrollBarMode::AlwaysOff );
workspace.restoreLastSession = ini.getValueB( "workspace", "restore_last_session", false );
workspace.checkForUpdatesAtStartup =
@@ -263,7 +271,7 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
EE::Window::Window* win, const std::string& colorSchemeName,
const SearchBarConfig& searchBarConfig,
const GlobalSearchBarConfig& globalSearchBarConfig,
PluginManager* pluginManager ) {
PluginManager* pluginManager, bool terminalMode ) {
FileInfo configInfo( ini.path() );
if ( iniInfo.getModificationTime() != 0 &&
@@ -309,7 +317,8 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
ini.setValue( "editor", "font_size", editor.fontSize.toString() );
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 );
if ( !terminalMode )
ini.setValueB( "ui", "show_side_panel", ui.showSidePanel );
ini.setValueB( "ui", "show_status_bar", ui.showStatusBar );
ini.setValueB( "ui", "show_menu_bar", ui.showMenuBar );
ini.setValueB( "ui", "welcome_screen", ui.welcomeScreen );
@@ -396,6 +405,12 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
ini.setValueB( "terminal", "warn_before_closing_tab", term.warnBeforeClosingTab );
ini.setValue( "terminal", "cursor_style",
TerminalCursorHelper::modeToString( term.cursorStyle ) );
ini.setValue( "terminal", "scrollbar_type",
term.scrollBarType == ScrollViewType::Overlay ? "overlay"sv : "outside"sv );
ini.setValue( "terminal", "scrollbar_mode",
term.scrollBarMode == ScrollBarMode::Auto
? "auto"sv
: ( term.scrollBarMode == ScrollBarMode::AlwaysOn ? "on"sv : "off" ) );
ini.setValueB( "window", "vsync", context.VSync );
ini.setValue( "window", "glversion",

View File

@@ -10,6 +10,7 @@
#include <eepp/window/window.hpp>
#include <eterm/terminal/terminaltypes.hpp>
#include <eterm/ui/uiterminal.hpp>
#include <nlohmann/json_fwd.hpp>
@@ -21,6 +22,7 @@ using namespace EE::UI::Tools;
using namespace EE::System;
using namespace EE::Window;
using namespace eterm::Terminal;
using namespace eterm::UI;
namespace ecode {
class App;
@@ -184,6 +186,8 @@ struct TerminalConfig {
bool closeTerminalTabOnExit{ false };
bool warnBeforeClosingTab{ true };
TerminalCursorMode cursorStyle{ TerminalCursorMode::SteadyUnderline };
ScrollViewType scrollBarType{ ScrollViewType::Overlay };
ScrollBarMode scrollBarMode{ ScrollBarMode::Auto };
};
struct WorkspaceConfig {
@@ -243,7 +247,8 @@ class AppConfig {
const std::vector<std::string>& recentFolders, const std::string& panelPartition,
const std::string& statusBarPartition, EE::Window::Window* win,
const std::string& colorSchemeName, const SearchBarConfig& searchBarConfig,
const GlobalSearchBarConfig& globalSearchBarConfig, PluginManager* pluginManager );
const GlobalSearchBarConfig& globalSearchBarConfig, PluginManager* pluginManager,
bool terminalMode );
void saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
const std::string& configPath, const ProjectDocumentConfig& docConfig,

View File

@@ -790,7 +790,8 @@ void App::saveConfig() {
mMainSplitter ? mMainSplitter->getSplitPartition().toString() : "85%", mWindow,
mSplitter ? mSplitter->getCurrentColorSchemeName() : mConfig.editor.colorScheme,
mDocSearchController->getSearchBarConfig(),
mGlobalSearchController->getGlobalSearchBarConfig(), mPluginManager.get() );
mGlobalSearchController->getGlobalSearchBarConfig(), mPluginManager.get(),
mTerminalMode );
}
std::string App::getKeybind( const std::string& command ) {
@@ -2831,6 +2832,17 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
editor->showLinesRelativePosition( config.linesRelativePosition );
mPluginManager->onNewEditor( editor );
if ( mTerminalMode && mTerminalModeSidePanelWasVisible &&
mSplitter->getTabWidgets().size() == 1 &&
( mSplitter->getTabWidgets()[0]->getTabCount() == 0 ||
( mSplitter->getTabWidgets()[0]->getTabCount() == 1 && mSplitter->getCurEditor() &&
mSplitter->getCurEditor()->getDocument().isUntitledEmpty() ) ) ) {
showSidePanel( true );
mConfig.ui.showSidePanel = true;
if ( mSettings )
getSettingsMenu()->updateViewMenu();
}
}
void App::loadCurrentDirectory() {
@@ -3239,7 +3251,7 @@ void App::initProjectTreeViewUI() {
mProjectTreeView->setHeadersVisible( false );
mProjectTreeView->setExpandersAsIcons( true );
mProjectTreeView->setSingleClickNavigation( mConfig.editor.singleClickNavigation );
mProjectTreeView->setScrollViewType( UIScrollableWidget::Inclusive );
mProjectTreeView->setScrollViewType( ScrollViewType::Overlay );
mProjectTreeView->on( Event::OnModelEvent, [this]( const Event* event ) {
const ModelEvent* modelEvent = static_cast<const ModelEvent*>( event );
ModelEventType type = modelEvent->getModelEventType();
@@ -4423,8 +4435,13 @@ void App::init( InitParameters& params ) {
#endif
if ( params.terminal && params.file.empty() && params.fileToOpen.empty() ) {
mTerminalMode = true;
mTerminalModeSidePanelWasVisible = mConfig.ui.showSidePanel;
mConfig.ui.showSidePanel = false;
showSidePanel( false );
showStatusBar( false );
if ( mSettings )
getSettingsMenu()->updateViewMenu();
initProjectViewEmptyCont();
mTerminalManager->createNewTerminal();
} else {

View File

@@ -678,6 +678,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
std::condition_variable mAsyncResourcesLoadCond;
std::vector<SyntaxColorScheme> mColorSchemes;
bool mAsyncResourcesLoaded{ false };
bool mTerminalMode{ false };
bool mTerminalModeSidePanelWasVisible{ false };
std::string mProfilePath;
void sortSidePanel();

View File

@@ -1511,7 +1511,7 @@ void GitPlugin::buildSidePanelTab() {
mBranchesTree->setHeadersVisible( false );
mBranchesTree->setExpandersAsIcons( true );
mBranchesTree->setIndentWidth( PixelDensity::dpToPx( 16 ) );
mBranchesTree->setScrollViewType( UIScrollableWidget::Inclusive );
mBranchesTree->setScrollViewType( ScrollViewType::Overlay );
mBranchesTree->on( Event::OnModelEvent, [this]( const Event* event ) {
const ModelEvent* modelEvent = static_cast<const ModelEvent*>( event );
if ( !modelEvent->getModelIndex().hasParent() )
@@ -1577,7 +1577,7 @@ void GitPlugin::buildSidePanelTab() {
mStatusTree->setAutoColumnsWidth( true );
mStatusTree->setHeadersVisible( false );
mStatusTree->setExpandersAsIcons( true );
mStatusTree->setScrollViewType( UIScrollableWidget::Inclusive );
mStatusTree->setScrollViewType( ScrollViewType::Overlay );
mStatusTree->setIndentWidth( PixelDensity::dpToPx( 4 ) );
mStatusTree->on( Event::OnRowCreated, [this]( const Event* event ) {
UITableRow* row = event->asRowCreatedEvent()->getRow();

View File

@@ -1018,6 +1018,90 @@ UIMenu* SettingsMenu::createTerminalMenu() {
} );
} );
UIPopUpMenu* scrollBarTypeMenu = UIPopUpMenu::New();
const auto scrollBarTypeMenuRefresh = [this, scrollBarTypeMenu] {
const auto& cfg = mApp->getConfig();
auto el = scrollBarTypeMenu->find(
"tscrolltype_" +
( cfg.term.scrollBarType == ScrollViewType::Overlay ? "overlay"sv : "outside"sv ) );
if ( el && el->isType( UI_TYPE_MENURADIOBUTTON ) )
el->asType<UIMenuRadioButton>()->setActive( true );
};
scrollBarTypeMenu->on(
Event::OnMenuShow, [this, scrollBarTypeMenu, scrollBarTypeMenuRefresh]( auto ) {
if ( scrollBarTypeMenu->getCount() == 0 ) {
scrollBarTypeMenu->addRadioButton( i18n( "overlay", "Overlay" ) )
->setTooltipText(
i18n( "scroll_overlay_tooltip", "Scrollbar appears over content." ) )
->setId( "tscrolltype_overlay" );
scrollBarTypeMenu->addRadioButton( i18n( "outside", "Outside" ) )
->setTooltipText( i18n( "scroll_outside_tooltip",
"Scrollbar has its own space, never covers content." ) )
->setId( "tscrolltype_outside" );
}
scrollBarTypeMenuRefresh();
} );
scrollBarTypeMenu->on( Event::OnItemClicked, [this]( const Event* event ) {
const std::string& id( event->getNode()->getId() );
std::string cursor = id.substr( 12 );
mApp->getConfig().term.scrollBarType =
cursor == "overlay" ? ScrollViewType::Overlay : ScrollViewType::Outside;
mSplitter->forEachWidgetType( UI_TYPE_TERMINAL, [this]( UIWidget* widget ) {
widget->asType<UITerminal>()->setScrollViewType( mApp->getConfig().term.scrollBarType );
} );
} );
mTerminalMenu->addSubMenu( i18n( "scrollbar_type", "ScrollBar Type" ), nullptr,
scrollBarTypeMenu );
UIPopUpMenu* scrollBarModeMenu = UIPopUpMenu::New();
const auto scrollBarModeMenuRefresh = [this, scrollBarModeMenu] {
const auto& cfg = mApp->getConfig();
auto el = scrollBarModeMenu->find(
"tscrollmode_" +
( cfg.term.scrollBarMode == ScrollBarMode::Auto
? "auto"sv
: ( cfg.term.scrollBarMode == ScrollBarMode::AlwaysOn ? "on"sv : "off"sv ) ) );
if ( el && el->isType( UI_TYPE_MENURADIOBUTTON ) )
el->asType<UIMenuRadioButton>()->setActive( true );
};
scrollBarModeMenu->on(
Event::OnMenuShow, [this, scrollBarModeMenu, scrollBarModeMenuRefresh]( auto ) {
if ( scrollBarModeMenu->getCount() == 0 ) {
scrollBarModeMenu->addRadioButton( i18n( "auto", "Auto" ) )
->setTooltipText( i18n( "scrollbar_mode_auto_tooltip",
"In overlay type Scrollbar will be visible only when "
"mouse moves over the terminal.\nIn outside type it "
"will be visible if there's any scrollable area." ) )
->setId( "tscrollmode_auto" );
scrollBarModeMenu->addRadioButton( i18n( "always_visible", "Always Visible" ) )
->setId( "tscrollmode_on" );
scrollBarModeMenu->addRadioButton( i18n( "always_hidden", "Always Hidden" ) )
->setId( "tscrollmode_off" );
}
scrollBarModeMenuRefresh();
} );
scrollBarModeMenu->on( Event::OnItemClicked, [this]( const Event* event ) {
const std::string& id( event->getNode()->getId() );
std::string mode = id.substr( 12 );
mApp->getConfig().term.scrollBarMode =
mode == "auto" ? ScrollBarMode::Auto
: ( mode == "on" ? ScrollBarMode::AlwaysOn : ScrollBarMode::AlwaysOff );
mSplitter->forEachWidgetType( UI_TYPE_TERMINAL, [this]( UIWidget* widget ) {
widget->asType<UITerminal>()->setVerticalScrollMode(
mApp->getConfig().term.scrollBarMode );
} );
} );
mTerminalMenu->addSubMenu( i18n( "scrollbar_mode", "ScrollBar Mode" ), nullptr,
scrollBarModeMenu );
mTerminalMenu->addSeparator();
mTerminalMenu

View File

@@ -534,6 +534,8 @@ UITerminal* TerminalManager::createNewTerminal(
}
term->getTerm()->setCursorMode( mApp->termConfig().cursorStyle );
term->setScrollViewType( mApp->termConfig().scrollBarType );
term->setVerticalScrollMode( mApp->termConfig().scrollBarMode );
auto ret = mApp->getSplitter()->createWidgetInTabWidget(
tabWidget, term, title.empty() ? mApp->i18n( "shell", "Shell" ).toUtf8() : title, true );