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;