Fix status debugger panel serialization.

Fix UIWindow invalid min-size auto sizing.
Fix UIListView displaying horizontal scrollbar when wasn't necessary.
This commit is contained in:
Martín Lucas Golini
2026-08-20 17:12:25 -03:00
parent f193047f1e
commit c13710dddc
7 changed files with 61 additions and 20 deletions
@@ -244,6 +244,7 @@ class EE_API UIAbstractTableView : public UIAbstractView {
ColumnWidthMode mColumnWidthMode{ ColumnWidthMode::Pixels }; ColumnWidthMode mColumnWidthMode{ ColumnWidthMode::Pixels };
bool mColumnWidthModeMenuEnabled{ false }; bool mColumnWidthModeMenuEnabled{ false };
bool mUpdatingColumnsForScrollbars{ false }; bool mUpdatingColumnsForScrollbars{ false };
bool mAutoExpandedColumnUsesVerticalScroll{ false };
std::string mPendingSerializedColumnWidths; std::string mPendingSerializedColumnWidths;
virtual ~UIAbstractTableView(); virtual ~UIAbstractTableView();
+1 -2
View File
@@ -61,8 +61,7 @@ class EE_API UIDropDown : public UITextInput {
protected: protected:
StyleConfig mStyleConfig; StyleConfig mStyleConfig;
UINode* mFriendNode{ nullptr }; UINode* mFriendNode{ nullptr };
Uint64 mLastFocusLoss{ 0 }; SmallVector<UIWidget*, 1> mRelatedWidgets;
std::vector<UIWidget*> mRelatedWidgets;
UIDropDown( const std::string& tag ); UIDropDown( const std::string& tag );
+18 -5
View File
@@ -629,7 +629,11 @@ void UIAbstractTableView::updateColumnsWidth() {
if ( visibleColumnCount() == 1 && ( col = visibleColumn() ) != -1 ) { if ( visibleColumnCount() == 1 && ( col = visibleColumn() ) != -1 ) {
Float width = eemax( getContentSpaceWidth(), getMaxColumnContentWidth( col, true ) ); Float width = eemax( getContentSpaceWidth(), getMaxColumnContentWidth( col, true ) );
bool shouldVScrollBeVisible = shouldVerticalScrollBeVisible(); 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 ) if ( !mVScroll->isVisible() && shouldVScrollBeVisible )
width -= getVerticalScrollBar()->getPixelsSize().getWidth(); width -= getVerticalScrollBar()->getPixelsSize().getWidth();
else if ( mVScroll->isVisible() && !shouldVScrollBeVisible ) else if ( mVScroll->isVisible() && !shouldVScrollBeVisible )
@@ -843,10 +847,19 @@ void UIAbstractTableView::onContentSizeChange() {
bool verticalScrollWasVisible = mVScroll->isVisible(); bool verticalScrollWasVisible = mVScroll->isVisible();
UIScrollableWidget::onContentSizeChange(); UIScrollableWidget::onContentSizeChange();
const bool columnsDependOnContentWidth = const bool autoExpandedSingleColumn = mAutoExpandOnSingleColumn && visibleColumnCount() == 1;
mColumnWidthMode == ColumnWidthMode::Percentage || mAutoColumnsWidth || const bool columnsDependOnContentWidth = mColumnWidthMode == ColumnWidthMode::Percentage ||
( mAutoExpandOnSingleColumn && visibleColumnCount() == 1 ); mAutoColumnsWidth || autoExpandedSingleColumn;
if ( !columnsDependOnContentWidth || verticalScrollWasVisible == mVScroll->isVisible() ) 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; return;
mUpdatingColumnsForScrollbars = true; mUpdatingColumnsForScrollbars = true;
-2
View File
@@ -227,8 +227,6 @@ void UIDropDown::onPopUpFocusLoss() {
if ( getEventDispatcher()->getFocusNode() != this && !isChildFocus && !friendIsFocus && if ( getEventDispatcher()->getFocusNode() != this && !isChildFocus && !friendIsFocus &&
!isRelatedWidget ) { !isRelatedWidget ) {
hide(); hide();
mLastFocusLoss = Sys::getTicks();
} }
} }
+4 -5
View File
@@ -563,13 +563,12 @@ void UIWindow::onSizeChange() {
Sizef size( getMinWindowSizeWithDecoration() ); Sizef size( getMinWindowSizeWithDecoration() );
if ( getSize().getWidth() < size.getWidth() || getSize().getHeight() < size.getHeight() ) { if ( getSize().getWidth() < size.getWidth() || getSize().getHeight() < size.getHeight() ) {
if ( getSize().getWidth() < size.getWidth() && if ( getSize().getWidth() < size.getWidth() && getSize().getHeight() < size.getHeight() ) {
getSize().getHeight() < mStyleConfig.MinWindowSize.getHeight() ) { internalSize( size );
setSize( mStyleConfig.MinWindowSize );
} else if ( getSize().getWidth() < size.getWidth() ) { } 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() ) { } else if ( getSize().getHeight() < size.getHeight() ) {
setSize( Sizef( getSize().getWidth(), mStyleConfig.MinWindowSize.getHeight() ) ); internalSize( Sizef( getSize().getWidth(), size.getHeight() ) );
} }
} else { } else {
fixChildrenSize(); fixChildrenSize();
@@ -35,6 +35,7 @@ class TransferTestTabWidget : public UITabWidget {
class ThreeColumnModel : public Model { class ThreeColumnModel : public Model {
public: public:
explicit ThreeColumnModel( size_t rows = 1 ) : mRows( rows ) {} 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 rowCount( const ModelIndex& = ModelIndex() ) const override { return mRows; }
size_t columnCount( const ModelIndex& = ModelIndex() ) const override { return 3; } size_t columnCount( const ModelIndex& = ModelIndex() ) const override { return 3; }
@@ -74,6 +75,8 @@ class PercentageTestTable : public UITableView {
onColumnResizeToContent( column ); onColumnResizeToContent( column );
} }
void updateScrollbars() { onContentSizeChange(); }
Float getMaxColumnContentWidth( const size_t&, bool ) override { return mContentWidth; } Float getMaxColumnContentWidth( const size_t&, bool ) override { return mContentWidth; }
protected: protected:
@@ -330,6 +333,32 @@ UTEST( UIAbstractTableView, AutoPixelColumnsRecomputeWhenVerticalScrollbarAppear
EXPECT_FALSE( table->getHorizontalScrollBar()->isVisible() ); 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<ThreeColumnModel>( 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<ThreeColumnModel>();
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 ) { UTEST( UIAbstractTableView, ColumnWidthsSerializationRoundTripsBothModes ) {
UIApplication app( UIApplication app(
WindowSettings( 800, 600, "eepp - unit tests" ), WindowSettings( 800, 600, "eepp - unit tests" ),
@@ -141,7 +141,9 @@ StatusDebuggerController::getLocalDefaultKeybindings() {
StatusDebuggerController::StatusDebuggerController( UISplitter* mainSplitter, StatusDebuggerController::StatusDebuggerController( UISplitter* mainSplitter,
UISceneNode* uiSceneNode, UISceneNode* uiSceneNode,
PluginContextProvider* pluginContext ) : PluginContextProvider* pluginContext ) :
StatusBarElement( mainSplitter, uiSceneNode, pluginContext ) {} StatusBarElement( mainSplitter, uiSceneNode, pluginContext ) {
mSerializedLayout = mContext->getConfig().iniState.getValue( "debugger", "panel_layout" );
}
StatusDebuggerController::~StatusDebuggerController() { StatusDebuggerController::~StatusDebuggerController() {
mEventConnections.clear(); mEventConnections.clear();
@@ -346,9 +348,7 @@ void StatusDebuggerController::restoreTabLayout() {
"debugger-breakpoints", "debugger-console" }; "debugger-breakpoints", "debugger-console" };
mRestoringLayout = true; mRestoringLayout = true;
bool restored = false; bool restored = false;
mSerializedLayout = mContext->getConfig().iniState.getValue( mSerializedLayout = mContext->getConfig().iniState.getValue( "debugger", "panel_layout" );
"debugger", "panel_layout",
mContext->getConfig().iniState.getValue( "ui", "debugger_panel_layout", "" ) );
const std::string& saved = mSerializedLayout; const std::string& saved = mSerializedLayout;
if ( !saved.empty() ) { if ( !saved.empty() ) {
auto layout = nlohmann::json::parse( saved, nullptr, false, true ); auto layout = nlohmann::json::parse( saved, nullptr, false, true );
@@ -392,11 +392,13 @@ void StatusDebuggerController::restoreTabLayout() {
mUITabWidget->setTabSelected( Uint32{ 0 } ); mUITabWidget->setTabSelected( Uint32{ 0 } );
mUIRightTabWidget->setTabSelected( Uint32{ 0 } ); mUIRightTabWidget->setTabSelected( Uint32{ 0 } );
} }
if ( mUITabWidget->getTabCount() )
if ( mUITabWidget->getTabCount() ) {
mTabWidgetSplitter->setCurrentWidget( mTabWidgetSplitter->setCurrentWidget(
mUITabWidget->getTabSelected()->getOwnedWidget()->asType<UIWidget>() ); mUITabWidget->getTabSelected()->getOwnedWidget()->asType<UIWidget>() );
}
mRestoringLayout = false; mRestoringLayout = false;
saveTabLayout();
updateRightPanel(); updateRightPanel();
} }