GUI: Implement drag to scroll in ScrollContainer

This commit is contained in:
Mohit Bankar
2026-04-19 18:47:17 +05:30
committed by Eugene Sandulenko
parent 5ef242d112
commit 441f97f4e4
2 changed files with 74 additions and 5 deletions
+66 -5
View File
@@ -38,7 +38,7 @@ ScrollContainerWidget::ScrollContainerWidget(GuiObject *boss, const Common::Stri
}
void ScrollContainerWidget::init() {
setFlags(WIDGET_ENABLED);
setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE);
_type = kScrollContainerWidget;
_backgroundType = ThemeEngine::kWidgetBackgroundPlain;
_verticalScroll = new ScrollBarWidget(this, _w, 0, 16, _h);
@@ -53,6 +53,63 @@ void ScrollContainerWidget::handleMouseWheel(int x, int y, int direction) {
_verticalScroll->handleMouseWheel(x, y, direction);
}
void ScrollContainerWidget::handleMouseDown(int x, int y, int button, int clickCount) {
_mouseDownY = _mouseDownStartY = y;
Widget *child = _childUnderMouse;
if (child) {
int childX = (x + _scrolledX) - child->getRelX();
int childY = (y + _scrolledY) - child->getRelY();
child->handleMouseDown(childX, childY, button, clickCount);
}
}
void ScrollContainerWidget::handleMouseMoved(int x, int y, int button) {
if (_mouseDownY == y)
return;
if (!_isDragging && ABS(y - _mouseDownStartY) > 5)
_isDragging = true;
if (_isDragging) {
int deltaY = _mouseDownY - y;
_mouseDownY = y;
_childUnderMouse = nullptr;
if (deltaY != 0) {
int oldPos = _scrolledY;
_scrolledY += deltaY;
int h = _verticalScroll->_numEntries;
if (_scrolledY < 0)
_scrolledY = 0;
else if (_scrolledY > h - _limitH)
_scrolledY = MAX(0, h - _limitH);
if (_scrolledY != oldPos) {
_verticalScroll->_currentPos = _scrolledY;
recalc();
markAsDirty();
g_gui.scheduleTopDialogRedraw();
}
}
}
}
void ScrollContainerWidget::handleMouseUp(int x, int y, int button, int clickCount) {
Widget *child = _childUnderMouse;
bool isDragging = _isDragging;
_mouseDownY = _mouseDownStartY = 0;
_isDragging = false;
_childUnderMouse = nullptr;
if (!isDragging && child) {
int childX = (x + _scrolledX) - child->getRelX();
int childY = (y + _scrolledY) - child->getRelY();
child->handleMouseUp(childX, childY, button, clickCount);
}
}
void ScrollContainerWidget::recalc() {
_scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
_limitH = _h;
@@ -80,6 +137,7 @@ void ScrollContainerWidget::recalc() {
_verticalScroll->_singleStep = kLineHeight;
_verticalScroll->setPos(_w, _scrolledY);
_verticalScroll->setSize(_scrollbarWidth, _limitH-1);
_verticalScroll->recalc();
}
@@ -119,6 +177,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
}
void ScrollContainerWidget::reflowLayout() {
_childUnderMouse = nullptr;
Widget::reflowLayout();
if (!_dialogName.empty()) {
@@ -169,11 +228,13 @@ bool ScrollContainerWidget::containsWidget(Widget *w) const {
}
Widget *ScrollContainerWidget::findWidget(int x, int y) {
if (_verticalScroll->isVisible() && x >= _w)
if (_verticalScroll->isVisible() && x >= _w) {
_childUnderMouse = nullptr;
return _verticalScroll;
Widget *w = Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
if (w)
return w;
}
_childUnderMouse = Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
if (_childUnderMouse == _verticalScroll)
_childUnderMouse = nullptr;
return this;
}
+8
View File
@@ -36,6 +36,10 @@ class ScrollContainerWidget: public Widget, public CommandSender {
uint32 _reflowCmd;
ThemeEngine::WidgetBackground _backgroundType;
Common::String _dialogName;
int _mouseDownY = 0;
int _mouseDownStartY = 0;
bool _isDragging = false;
Widget *_childUnderMouse = nullptr;
void recalc();
@@ -53,6 +57,9 @@ public:
void setBackgroundType(ThemeEngine::WidgetBackground backgroundType);
void handleMouseWheel(int x, int y, int direction) override;
void handleMouseDown(int x, int y, int button, int clickCount) override;
void handleMouseUp(int x, int y, int button, int clickCount) override;
void handleMouseMoved(int x, int y, int button) override;
// We overload getChildY to make sure child widgets are positioned correctly.
// Essentially this compensates for the space taken up by the tab title header.
@@ -60,6 +67,7 @@ public:
int16 getChildY() const override;
uint16 getWidth() const override;
uint16 getHeight() const override;
bool wantsFocus() override { return true; }
void draw() override;
void markAsDirty() override;