From b4aededbdb16ca0072e2c4b5e3dda8328651a86b Mon Sep 17 00:00:00 2001 From: JJ <69144954+jonjenssen@users.noreply.github.com> Date: Mon, 14 Sep 2026 20:30:46 +0200 Subject: [PATCH] Support tiling windows in a single direction (horz or vert) (#14754) * Support tiling windows in a single direction (horz or vert) --- ApplicationExeCode/Resources/ResInsight.qrc | 4 +- .../Resources/TileHorizontally.svg | 33 ++++ .../Resources/TileVertically.svg | 37 +++++ .../UserInterface/RiuMainWindowBase.cpp | 151 ++++++++++++++---- .../UserInterface/RiuMainWindowBase.h | 9 ++ 5 files changed, 200 insertions(+), 34 deletions(-) create mode 100644 ApplicationExeCode/Resources/TileHorizontally.svg create mode 100644 ApplicationExeCode/Resources/TileVertically.svg diff --git a/ApplicationExeCode/Resources/ResInsight.qrc b/ApplicationExeCode/Resources/ResInsight.qrc index 1bd95eed8c..8d214434cc 100644 --- a/ApplicationExeCode/Resources/ResInsight.qrc +++ b/ApplicationExeCode/Resources/ResInsight.qrc @@ -245,7 +245,9 @@ ObjectiveFunctionWeight.svg CellFilter_UserDefined.png CellFilter_Polygon.png - undo.png + TileVertically.svg + TileHorizontally.svg + undo.png redo.png ComboBoxDown.svg ComboBoxUp.svg diff --git a/ApplicationExeCode/Resources/TileHorizontally.svg b/ApplicationExeCode/Resources/TileHorizontally.svg new file mode 100644 index 0000000000..36ff68cdc8 --- /dev/null +++ b/ApplicationExeCode/Resources/TileHorizontally.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ApplicationExeCode/Resources/TileVertically.svg b/ApplicationExeCode/Resources/TileVertically.svg new file mode 100644 index 0000000000..16a7f9916a --- /dev/null +++ b/ApplicationExeCode/Resources/TileVertically.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp b/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp index 6aca4d6e61..e7235afaf7 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp +++ b/ApplicationLibCode/UserInterface/RiuMainWindowBase.cpp @@ -65,6 +65,25 @@ #include #include +namespace internal +{ +void rebalanceDockSplitters( RiuMainWindowBase* widget, std::set splitters ) +{ + // rebalance splitters after a short delay to allow the layout to be updated before setting sizes + QTimer::singleShot( 10, + widget, + [splitters]() + { + for ( QSplitter* splitter : splitters ) + { + QList sizes( splitter->count(), 1000 ); // size not important, just needs all to be equal + splitter->setSizes( sizes ); + } + } ); +} + +} // namespace internal + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -106,6 +125,14 @@ RiuMainWindowBase::RiuMainWindowBase() m_tileWindowsAction->setToolTip( "Tile All View Windows" ); connect( m_tileWindowsAction, SIGNAL( triggered() ), SLOT( tileViewWindows() ) ); + m_tileHorizontallyAction = new QAction( QIcon( ":/TileHorizontally.svg" ), "Tile Windows Horizontally", this ); + m_tileHorizontallyAction->setToolTip( "Tile All View Windows Horizontally" ); + connect( m_tileHorizontallyAction, SIGNAL( triggered() ), SLOT( tileWindowsHorizontally() ) ); + + m_tileVerticallyAction = new QAction( QIcon( ":/TileVertically.svg" ), "Tile Windows Vertically", this ); + m_tileVerticallyAction->setToolTip( "Tile All View Windows Vertically" ); + connect( m_tileVerticallyAction, SIGNAL( triggered() ), SLOT( tileWindowsVertically() ) ); + m_maximizeWindowsAction = new QAction( QIcon( ":/MaximizeWindows.svg" ), "Maximize Windows", this ); m_maximizeWindowsAction->setToolTip( "Maximize All View Windows" ); connect( m_maximizeWindowsAction, SIGNAL( triggered() ), SLOT( maximizeViewWindows() ) ); @@ -793,6 +820,8 @@ void RiuMainWindowBase::addDefaultEntriesToWindowsMenu() m_windowMenu->addSeparator(); m_windowMenu->addAction( m_tileWindowsAction ); + m_windowMenu->addAction( m_tileVerticallyAction ); + m_windowMenu->addAction( m_tileHorizontallyAction ); m_windowMenu->addAction( m_maximizeWindowsAction ); } @@ -885,6 +914,25 @@ void RiuMainWindowBase::slotHideTabs( bool hideTabs ) } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector RiuMainWindowBase::removeActiveViewWindows() +{ + std::vector activeWindows; + + // remove all visible views from central dock area + for ( auto view : viewWindows() ) + { + if ( !view->dockWidget() ) continue; + if ( !view->showWindow() ) continue; + activeWindows.push_back( view ); + m_dockManager->removeDockWidget( view->dockWidget() ); + } + + return activeWindows; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -900,19 +948,10 @@ void RiuMainWindowBase::tileViewWindows() { 25, { 5, 5 } } }; // stores the views to tile - std::vector tiledWindows; - - // remove all visible views from central dock area - for ( auto view : viewWindows() ) - { - if ( !view->dockWidget() ) continue; - if ( !view->showWindow() ) continue; - tiledWindows.push_back( view ); - m_dockManager->removeDockWidget( view->dockWidget() ); - } + std::vector windowsToTile = removeActiveViewWindows(); // redock views in a grid layout - const int nViews = (int)tiledWindows.size(); + const int nViews = (int)windowsToTile.size(); const int nCols = gridSizeMap[nViews].first; const int nRows = gridSizeMap[nViews].second; @@ -927,11 +966,11 @@ void RiuMainWindowBase::tileViewWindows() if ( viewIndex >= nViews ) break; if ( viewIndex >= 25 ) // limit to 25 views, see map above { - tiledWindows[viewIndex++]->removeWindowFromDock(); + windowsToTile[viewIndex++]->removeWindowFromDock(); continue; } - auto view = tiledWindows[viewIndex++]; + auto view = windowsToTile[viewIndex++]; auto dock = view->dockWidget(); if ( row == 0 && col == 0 ) @@ -969,17 +1008,7 @@ void RiuMainWindowBase::tileViewWindows() splitters.insert( m_dockManager->centralWidget()->dockAreaWidget()->parentSplitter() ); } - // rebalance splitters after a short delay to allow the layout to be updated before setting sizes - QTimer::singleShot( 10, - this, - [splitters]() - { - for ( QSplitter* splitter : splitters ) - { - QList sizes( splitter->count(), 1000 ); // size not important, just needs all to be equal - splitter->setSizes( sizes ); - } - } ); + internal::rebalanceDockSplitters( this, splitters ); } //-------------------------------------------------------------------------------------------------- @@ -988,15 +1017,7 @@ void RiuMainWindowBase::tileViewWindows() void RiuMainWindowBase::maximizeViewWindows() { // remove all active views from dock manager - std::vector activeViews; - for ( auto view : viewWindows() ) - { - if ( !view->dockWidget() ) continue; - if ( !view->showWindow() ) continue; - activeViews.push_back( view ); - - m_dockManager->removeDockWidget( view->dockWidget() ); - } + std::vector activeViews = removeActiveViewWindows(); // add all views to the center area for ( auto view : activeViews ) @@ -1006,3 +1027,67 @@ void RiuMainWindowBase::maximizeViewWindows() m_dockManager->centralWidget()->dockAreaWidget() ); } } + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::tileWindowsHorizontally() +{ + tileWindows( ads::RightDockWidgetArea ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::tileWindowsVertically() +{ + tileWindows( ads::BottomDockWidgetArea ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuMainWindowBase::tileWindows( ads::DockWidgetArea whereToDock ) +{ + // stores the views to tile + std::vector windowsToTile = removeActiveViewWindows(); + + const int nViews = (int)windowsToTile.size(); + + std::vector areas( nViews ); + + int viewIndex = 0; + + for ( int i = 0; i < nViews; i++ ) + { + auto view = windowsToTile[viewIndex++]; + auto dock = view->dockWidget(); + + if ( i == 0 ) + { + areas[i] = m_dockManager->addDockWidget( ads::CenterDockWidgetArea, dock, m_dockManager->centralWidget()->dockAreaWidget() ); + } + else + { + areas[i] = m_dockManager->addDockWidget( whereToDock, dock, areas[i - 1] ); + } + } + + // build unique list of splitters used in the areas created + std::set splitters; + + for ( auto area : areas ) + { + if ( area && area->parentSplitter() ) + { + splitters.insert( area->parentSplitter() ); + } + } + + if ( m_dockManager->centralWidget() && m_dockManager->centralWidget()->dockAreaWidget() ) + { + splitters.insert( m_dockManager->centralWidget()->dockAreaWidget()->parentSplitter() ); + } + + internal::rebalanceDockSplitters( this, splitters ); +} diff --git a/ApplicationLibCode/UserInterface/RiuMainWindowBase.h b/ApplicationLibCode/UserInterface/RiuMainWindowBase.h index 10f34f0785..c5666dff3a 100644 --- a/ApplicationLibCode/UserInterface/RiuMainWindowBase.h +++ b/ApplicationLibCode/UserInterface/RiuMainWindowBase.h @@ -123,6 +123,8 @@ protected: virtual void onCentralWidgetContextMenu( QMenu& menu ) {}; + std::vector removeActiveViewWindows(); + protected slots: void slotDockWidgetToggleViewActionTriggered(); void slotDockViewerVisibilityChanged( bool visible ); @@ -142,6 +144,11 @@ protected slots: void exportDockLayout(); void maximizeViewWindows(); + void tileWindowsVertically(); + void tileWindowsHorizontally(); + +private: + void tileWindows( ads::DockWidgetArea whereToDock ); protected: bool m_allowActiveViewChangeFromSelection; // To be used in selectedObjectsChanged() to control @@ -150,6 +157,8 @@ protected: QAction* m_hideTabsAction; QAction* m_tileWindowsAction; QAction* m_maximizeWindowsAction; + QAction* m_tileHorizontallyAction; + QAction* m_tileVerticallyAction; QAction* m_undoAction; QAction* m_redoAction;