[Scummvm-git-logs] scummvm master -> 84e4dd0cdfd288e29ca1b8df1fdc4e0b0eb45217

sev- noreply at scummvm.org
Tue Apr 7 11:52:07 UTC 2026


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
84e4dd0cdf GUI: Preserve multi-selection when changing grouping


Commit: 84e4dd0cdfd288e29ca1b8df1fdc4e0b0eb45217
    https://github.com/scummvm/scummvm/commit/84e4dd0cdfd288e29ca1b8df1fdc4e0b0eb45217
Author: Antonio (1642229 at uab.cat)
Date: 2026-04-07T13:52:03+02:00

Commit Message:
GUI: Preserve multi-selection when changing grouping

Changed paths:
    gui/launcher.cpp
    gui/widgets/groupedlist.cpp
    gui/widgets/groupedlist.h


diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 27332bb5fe4..2f8df9e7150 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -1107,6 +1107,8 @@ int LauncherChooser::runModal() {
 
 #pragma mark -
 
+static const int kSelPosGroupingChange = -2;
+
 LauncherSimple::LauncherSimple(const Common::String &title)
 	: LauncherDialog(title),
 	_list(nullptr) {
@@ -1246,6 +1248,13 @@ void LauncherSimple::updateListing(int selPos) {
 
 	const int oldSel = _list->getSelected();
 
+	Common::Array<bool> savedSelection;
+	const bool restoringGroupedSelection = (selPos == kSelPosGroupingChange);
+
+	if (restoringGroupedSelection) {
+		savedSelection = _list->saveSelection();
+	}
+
 	// Preserve the current collapsed groups before rebuilding the grouped list
 	if (_groupBy != kGroupByNone) {
 		_list->saveClosedGroups(Common::U32String(groupingModes[_groupBy].name));
@@ -1262,13 +1271,16 @@ void LauncherSimple::updateListing(int selPos) {
 	// is called.
 	_list->setFilter(_searchWidget->getEditString());
 
-	if (_groupBy != kGroupByNone && selPos != -1) {
+	if (restoringGroupedSelection) {
+		_list->loadSelection(savedSelection);
+	} else if (_groupBy != kGroupByNone && selPos != -1) {
 		_list->setSelected(_list->getNewSel(selPos));
-	} else if (oldSel < (int)l.size() && oldSel >= 0)
+	} else if (oldSel < (int)l.size() && oldSel >= 0) {
 		_list->setSelected(oldSel);	// Restore the old selection
-	else if (oldSel != -1)
+	} else if (oldSel != -1) {
 		// Select the last entry if the list has been reduced
 		_list->setSelected(_list->getList().size() - 1);
+	}
 	updateButtons();
 }
 
@@ -1446,7 +1458,7 @@ void LauncherSimple::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
 				}
 				++mode;
 			}
-			updateListing();
+			updateListing(kSelPosGroupingChange);
 		}
 		break;
 	}
diff --git a/gui/widgets/groupedlist.cpp b/gui/widgets/groupedlist.cpp
index 88e5a499dd0..00535bb2492 100644
--- a/gui/widgets/groupedlist.cpp
+++ b/gui/widgets/groupedlist.cpp
@@ -140,8 +140,13 @@ void GroupedListWidget::sortGroups() {
 			}
 		}
 	}
+
+	_selectedItem = -1;
 	checkBounds();
 	scrollBarRecalc();
+
+	_scrollBar->_currentPos = _currentPos;
+	_scrollBar->recalc();
 	// FIXME: Temporary solution to clear/display the background ofthe scrollbar when list
 	// grows too small or large during group toggle. We shouldn't have to redraw the top dialog,
 	// but not doing so the background of scrollbar isn't cleared.
@@ -189,6 +194,66 @@ void GroupedListWidget::saveClosedGroups(const Common::U32String &groupName) {
 	ConfMan.flushToDisk();
 }
 
+Common::Array<bool> GroupedListWidget::saveSelection() const {
+	return _selectedItems;
+}
+
+void GroupedListWidget::loadSelection(const Common::Array<bool> &savedSelection) {
+	_selectedItems.clear();
+	_selectedItems.resize(_dataList.size(), false);
+
+	int count = MIN((int)savedSelection.size(), (int)_selectedItems.size());
+	for (int i = 0; i < count; ++i) {
+		_selectedItems[i] = savedSelection[i];
+	}
+
+	_selectedItem = -1;
+	_lastSelectionStartItem = -1;
+
+	int topMostSel = -1;
+	int bottomMostSel = -1;
+
+	for (int visualRow = 0; visualRow < (int)_listIndex.size(); ++visualRow) {
+		int dataIndex = _listIndex[visualRow];
+
+		if (dataIndex >= 0 &&
+			dataIndex < (int)_selectedItems.size() &&
+			_selectedItems[dataIndex]) {
+
+			if (topMostSel == -1) {
+				topMostSel = visualRow;
+				_selectedItem = visualRow;
+				_lastSelectionStartItem = visualRow;
+			}
+
+			bottomMostSel = visualRow;
+		}
+	}
+
+	if (topMostSel != -1 && _entriesPerPage > 0) {
+		int span = bottomMostSel - topMostSel + 1;
+
+		if (topMostSel == bottomMostSel) {
+			_currentPos = topMostSel - _entriesPerPage / 2;
+		} else if (span <= _entriesPerPage) {
+			int spanCenter = (topMostSel + bottomMostSel) / 2;
+			_currentPos = spanCenter - _entriesPerPage / 2;
+		} else {
+			_currentPos = topMostSel;
+		}
+	} else {
+		_currentPos = 0;
+	}
+
+	checkBounds();
+	scrollBarRecalc();
+
+	_scrollBar->_currentPos = _currentPos;
+	_scrollBar->recalc();
+
+	markAsDirty();
+}
+
 void GroupedListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 	if (!isEnabled())
 		return;
diff --git a/gui/widgets/groupedlist.h b/gui/widgets/groupedlist.h
index 10171f6aa09..fc1166611e5 100644
--- a/gui/widgets/groupedlist.h
+++ b/gui/widgets/groupedlist.h
@@ -55,6 +55,8 @@ public:
 	void loadClosedGroups(const Common::U32String &groupName);
 	void saveClosedGroups(const Common::U32String &groupName);
 
+	Common::Array<bool> saveSelection() const;
+	void loadSelection(const Common::Array<bool> &savedSelection);
 	int getSelected() const { return (_selectedItem == -1) ? _selectedItem : _listIndex[_selectedItem]; }
 	void setFilter(const Common::U32String &filter, bool redraw = true);
 




More information about the Scummvm-git-logs mailing list