diff --git a/include/eepp/ui/abstract/uiabstracttableview.hpp b/include/eepp/ui/abstract/uiabstracttableview.hpp index 2cba6ff6e..24a166739 100644 --- a/include/eepp/ui/abstract/uiabstracttableview.hpp +++ b/include/eepp/ui/abstract/uiabstracttableview.hpp @@ -244,6 +244,7 @@ class EE_API UIAbstractTableView : public UIAbstractView { ColumnWidthMode mColumnWidthMode{ ColumnWidthMode::Pixels }; bool mColumnWidthModeMenuEnabled{ false }; bool mUpdatingColumnsForScrollbars{ false }; + bool mAutoExpandedColumnUsesVerticalScroll{ false }; std::string mPendingSerializedColumnWidths; virtual ~UIAbstractTableView(); diff --git a/include/eepp/ui/uidropdown.hpp b/include/eepp/ui/uidropdown.hpp index faa91803b..27d57cc2c 100644 --- a/include/eepp/ui/uidropdown.hpp +++ b/include/eepp/ui/uidropdown.hpp @@ -61,8 +61,7 @@ class EE_API UIDropDown : public UITextInput { protected: StyleConfig mStyleConfig; UINode* mFriendNode{ nullptr }; - Uint64 mLastFocusLoss{ 0 }; - std::vector mRelatedWidgets; + SmallVector mRelatedWidgets; UIDropDown( const std::string& tag ); diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 1ba32dfbf..af1d137d1 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -629,7 +629,11 @@ void UIAbstractTableView::updateColumnsWidth() { if ( visibleColumnCount() == 1 && ( col = visibleColumn() ) != -1 ) { Float width = eemax( getContentSpaceWidth(), getMaxColumnContentWidth( col, true ) ); bool shouldVScrollBeVisible = shouldVerticalScrollBeVisible(); - if ( mScrollViewType == ScrollViewType::Outside || mVScroll->getAlpha() != 0.f ) { + const bool verticalScrollConsumesWidth = + mScrollViewType == ScrollViewType::Outside || mVScroll->getAlpha() != 0.f; + mAutoExpandedColumnUsesVerticalScroll = + shouldVScrollBeVisible && verticalScrollConsumesWidth; + if ( verticalScrollConsumesWidth ) { if ( !mVScroll->isVisible() && shouldVScrollBeVisible ) width -= getVerticalScrollBar()->getPixelsSize().getWidth(); else if ( mVScroll->isVisible() && !shouldVScrollBeVisible ) @@ -843,10 +847,19 @@ void UIAbstractTableView::onContentSizeChange() { bool verticalScrollWasVisible = mVScroll->isVisible(); UIScrollableWidget::onContentSizeChange(); - const bool columnsDependOnContentWidth = - mColumnWidthMode == ColumnWidthMode::Percentage || mAutoColumnsWidth || - ( mAutoExpandOnSingleColumn && visibleColumnCount() == 1 ); - if ( !columnsDependOnContentWidth || verticalScrollWasVisible == mVScroll->isVisible() ) + const bool autoExpandedSingleColumn = mAutoExpandOnSingleColumn && visibleColumnCount() == 1; + const bool columnsDependOnContentWidth = mColumnWidthMode == ColumnWidthMode::Percentage || + mAutoColumnsWidth || autoExpandedSingleColumn; + const bool verticalScrollConsumesWidth = + mVScroll->isVisible() && + ( mScrollViewType == ScrollViewType::Outside || mVScroll->getAlpha() != 0.f ); + // Visibility can be updated before this callback begins, so comparing only the state before and + // after the base implementation can miss a stale auto-expanded width. + const bool autoExpandedColumnIsStale = + autoExpandedSingleColumn && + mAutoExpandedColumnUsesVerticalScroll != verticalScrollConsumesWidth; + if ( !columnsDependOnContentWidth || + ( verticalScrollWasVisible == mVScroll->isVisible() && !autoExpandedColumnIsStale ) ) return; mUpdatingColumnsForScrollbars = true; diff --git a/src/eepp/ui/uidropdown.cpp b/src/eepp/ui/uidropdown.cpp index 3ba5229d4..fa3e3af16 100644 --- a/src/eepp/ui/uidropdown.cpp +++ b/src/eepp/ui/uidropdown.cpp @@ -227,8 +227,6 @@ void UIDropDown::onPopUpFocusLoss() { if ( getEventDispatcher()->getFocusNode() != this && !isChildFocus && !friendIsFocus && !isRelatedWidget ) { hide(); - - mLastFocusLoss = Sys::getTicks(); } } diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index 451f66391..694d6fd7e 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -563,13 +563,12 @@ void UIWindow::onSizeChange() { Sizef size( getMinWindowSizeWithDecoration() ); if ( getSize().getWidth() < size.getWidth() || getSize().getHeight() < size.getHeight() ) { - if ( getSize().getWidth() < size.getWidth() && - getSize().getHeight() < mStyleConfig.MinWindowSize.getHeight() ) { - setSize( mStyleConfig.MinWindowSize ); + if ( getSize().getWidth() < size.getWidth() && getSize().getHeight() < size.getHeight() ) { + internalSize( size ); } else if ( getSize().getWidth() < size.getWidth() ) { - setSize( Sizef( mStyleConfig.MinWindowSize.getWidth(), getSize().getHeight() ) ); + internalSize( Sizef( size.getWidth(), getSize().getHeight() ) ); } else if ( getSize().getHeight() < size.getHeight() ) { - setSize( Sizef( getSize().getWidth(), mStyleConfig.MinWindowSize.getHeight() ) ); + internalSize( Sizef( getSize().getWidth(), size.getHeight() ) ); } } else { fixChildrenSize(); diff --git a/src/tests/unit_tests/uitabwidgetsplitter_tests.cpp b/src/tests/unit_tests/uitabwidgetsplitter_tests.cpp index 38ce45150..05919001f 100644 --- a/src/tests/unit_tests/uitabwidgetsplitter_tests.cpp +++ b/src/tests/unit_tests/uitabwidgetsplitter_tests.cpp @@ -35,6 +35,7 @@ class TransferTestTabWidget : public UITabWidget { class ThreeColumnModel : public Model { public: explicit ThreeColumnModel( size_t rows = 1 ) : mRows( rows ) {} + void setRows( size_t rows ) { mRows = rows; } size_t rowCount( const ModelIndex& = ModelIndex() ) const override { return mRows; } size_t columnCount( const ModelIndex& = ModelIndex() ) const override { return 3; } @@ -74,6 +75,8 @@ class PercentageTestTable : public UITableView { onColumnResizeToContent( column ); } + void updateScrollbars() { onContentSizeChange(); } + Float getMaxColumnContentWidth( const size_t&, bool ) override { return mContentWidth; } protected: @@ -330,6 +333,32 @@ UTEST( UIAbstractTableView, AutoPixelColumnsRecomputeWhenVerticalScrollbarAppear EXPECT_FALSE( table->getHorizontalScrollBar()->isVisible() ); } +UTEST( UIAbstractTableView, AutoExpandedSingleColumnAccountsForVerticalScrollbar ) { + UIApplication app( + WindowSettings( 800, 600, "eepp - unit tests" ), + UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) ); + auto* table = PercentageTestTable::New(); + table->setParent( app.getUI() ); + table->setPixelsSize( 400, 100 ); + table->setAutoExpandOnSingleColumn( true ); + table->setModel( std::make_shared( 100 ) ); + table->setColumnsVisible( { 0 } ); + app.getUI()->update( Milliseconds( 16 ) ); + + EXPECT_TRUE( table->getVerticalScrollBar()->isVisible() ); + EXPECT_EQ( table->getColumnWidth( 0 ), table->getContentSpaceWidth() ); + EXPECT_FALSE( table->getHorizontalScrollBar()->isVisible() ); + + auto model = std::make_shared(); + table->setModel( model ); + model->setRows( 100 ); + table->getVerticalScrollBar()->setVisible( true ); + table->updateScrollbars(); + EXPECT_TRUE( table->getVerticalScrollBar()->isVisible() ); + EXPECT_EQ( table->getColumnWidth( 0 ), table->getContentSpaceWidth() ); + EXPECT_FALSE( table->getHorizontalScrollBar()->isVisible() ); +} + UTEST( UIAbstractTableView, ColumnWidthsSerializationRoundTripsBothModes ) { UIApplication app( WindowSettings( 800, 600, "eepp - unit tests" ), diff --git a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp index bf2f3d40e..f0f2142a7 100644 --- a/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp +++ b/src/tools/ecode/plugins/debugger/statusdebuggercontroller.cpp @@ -141,7 +141,9 @@ StatusDebuggerController::getLocalDefaultKeybindings() { StatusDebuggerController::StatusDebuggerController( UISplitter* mainSplitter, UISceneNode* uiSceneNode, PluginContextProvider* pluginContext ) : - StatusBarElement( mainSplitter, uiSceneNode, pluginContext ) {} + StatusBarElement( mainSplitter, uiSceneNode, pluginContext ) { + mSerializedLayout = mContext->getConfig().iniState.getValue( "debugger", "panel_layout" ); +} StatusDebuggerController::~StatusDebuggerController() { mEventConnections.clear(); @@ -346,9 +348,7 @@ void StatusDebuggerController::restoreTabLayout() { "debugger-breakpoints", "debugger-console" }; mRestoringLayout = true; bool restored = false; - mSerializedLayout = mContext->getConfig().iniState.getValue( - "debugger", "panel_layout", - mContext->getConfig().iniState.getValue( "ui", "debugger_panel_layout", "" ) ); + mSerializedLayout = mContext->getConfig().iniState.getValue( "debugger", "panel_layout" ); const std::string& saved = mSerializedLayout; if ( !saved.empty() ) { auto layout = nlohmann::json::parse( saved, nullptr, false, true ); @@ -392,11 +392,13 @@ void StatusDebuggerController::restoreTabLayout() { mUITabWidget->setTabSelected( Uint32{ 0 } ); mUIRightTabWidget->setTabSelected( Uint32{ 0 } ); } - if ( mUITabWidget->getTabCount() ) + + if ( mUITabWidget->getTabCount() ) { mTabWidgetSplitter->setCurrentWidget( mUITabWidget->getTabSelected()->getOwnedWidget()->asType() ); + } + mRestoringLayout = false; - saveTabLayout(); updateRightPanel(); }