GUI: Account for the scroll bar size in ScrollContainerWidget objects

This commit is contained in:
Cameron Cawley 2022-12-26 00:01:10 +00:00 committed by Eugene Sandulenko
parent 30bdbb6f76
commit 7ef8da53d7
9 changed files with 148 additions and 38 deletions

View file

@ -103,6 +103,12 @@ ThemeEval &ThemeEval::addWidget(const Common::String &name, const Common::String
typeH == -1 ? h : typeH,
typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign,
getVar("Globals.TabWidget.Tab.Height", 0));
else if (type == "ScrollContainerWidget")
widget = new ThemeLayoutScrollContainerWidget(_curLayout.top(), name,
typeW == -1 ? w : typeW,
typeH == -1 ? h : typeH,
typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign,
getVar("Globals.Scrollbar.Width", 0));
else
widget = new ThemeLayoutWidget(_curLayout.top(), name,
typeW == -1 ? w : typeW,

View file

@ -50,6 +50,7 @@ public:
kLayoutHorizontal,
kLayoutWidget,
kLayoutTabWidget,
kLayoutScrollContainerWidget,
kLayoutSpace
};
@ -285,6 +286,40 @@ protected:
}
};
class ThemeLayoutScrollContainerWidget : public ThemeLayoutWidget {
int _scrollWidth;
public:
ThemeLayoutScrollContainerWidget(ThemeLayout *p, const Common::String &name, int16 w, int16 h, Graphics::TextAlign align, int scrollWidth):
ThemeLayoutWidget(p, name, w, h, align, p->getUseRTL()) {
_scrollWidth = scrollWidth;
}
void reflowLayout(Widget *widgetChain) override {
for (uint i = 0; i < _children.size(); ++i) {
_children[i]->reflowLayout(widgetChain);
}
}
bool getWidgetData(const Common::String &name, int16 &x, int16 &y, int16 &w, int16 &h, bool &useRTL) override {
if (ThemeLayoutWidget::getWidgetData(name, x, y, w, h, useRTL)) {
w -= _scrollWidth;
return true;
}
return false;
}
protected:
LayoutType getLayoutType() const override { return kLayoutScrollContainerWidget; }
ThemeLayout *makeClone(ThemeLayout *newParent) override {
ThemeLayoutScrollContainerWidget *n = new ThemeLayoutScrollContainerWidget(*this);
n->_parent = newParent;
return n;
}
};
class ThemeLayoutSpacing : public ThemeLayout {
public:
ThemeLayoutSpacing(ThemeLayout *p, int size) : ThemeLayout(p) {

View file

@ -585,7 +585,9 @@
<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GlobalOptions_Graphics_Container' overlays = 'GlobalOptions_Graphics.Container'>
@ -913,7 +915,9 @@
<dialog name = 'GlobalOptions_GUI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -1035,7 +1039,9 @@
<dialog name = 'GlobalOptions_Cloud' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -1494,13 +1500,17 @@
<dialog name = 'GameOptions_Achievements' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics_Container' overlays = 'GameOptions_Graphics.Container'>
@ -1788,7 +1798,9 @@
<dialog name = 'GlobalConfig_Achievements' overlays = 'Dialog.GlobalConfig.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -2337,6 +2349,7 @@
<dialog name = 'UnknownGameDialog' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 0'>
<widget name = 'TextContainer'
type = 'ScrollContainerWidget'
/>
<layout type = 'horizontal' padding = '0, 0, 16, 16'>
<space/>

View file

@ -439,7 +439,9 @@
<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GlobalOptions_Graphics_Container' overlays = 'GlobalOptions_Graphics.Container'>
@ -766,7 +768,9 @@
<dialog name = 'GlobalOptions_GUI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -900,7 +904,9 @@
<dialog name = 'GlobalOptions_Cloud' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -1341,13 +1347,17 @@
<dialog name = 'GameOptions_Achievements' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics_Container' overlays = 'GameOptions_Graphics.Container'>
@ -1644,7 +1654,9 @@
<dialog name = 'GlobalConfig_Achievements' overlays = 'Dialog.GlobalConfig.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -2172,6 +2184,7 @@
<dialog name = 'UnknownGameDialog' overlays = 'screen' inset = '8' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 0'>
<widget name = 'TextContainer'
type = 'ScrollContainerWidget'
/>
<layout type = 'horizontal' padding = '0, 0, 8, 8'>
<space/>

View file

@ -353,7 +353,9 @@
<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GlobalOptions_Graphics_Container' overlays = 'GlobalOptions_Graphics.Container'>
@ -681,7 +683,9 @@
<dialog name = 'GlobalOptions_GUI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -803,7 +807,9 @@
<dialog name = 'GlobalOptions_Cloud' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -1247,13 +1253,17 @@
<dialog name = 'GameOptions_Achievements' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics_Container' overlays = 'GameOptions_Graphics.Container'>
@ -1541,7 +1551,9 @@
<dialog name = 'GlobalConfig_Achievements' overlays = 'Dialog.GlobalConfig.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -2088,6 +2100,7 @@
<dialog name = 'UnknownGameDialog' overlays = 'Dialog.Launcher.GameList' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 0'>
<widget name = 'TextContainer'
type = 'ScrollContainerWidget'
/>
<layout type = 'horizontal' padding = '0, 0, 16, 16'>
<space/>

View file

@ -361,7 +361,9 @@
<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GlobalOptions_Graphics_Container' overlays = 'GlobalOptions_Graphics.Container'>
@ -688,7 +690,9 @@
<dialog name = 'GlobalOptions_GUI' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -822,7 +826,9 @@
<dialog name = 'GlobalOptions_Cloud' overlays = 'Dialog.GlobalOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -1263,13 +1269,17 @@
<dialog name = 'GameOptions_Achievements' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
<dialog name = 'GameOptions_Graphics_Container' overlays = 'GameOptions_Graphics.Container'>
@ -1565,7 +1575,9 @@
<dialog name = 'GlobalConfig_Achievements' overlays = 'Dialog.GlobalConfig.TabWidget'>
<layout type = 'vertical' padding = '0, 0, 0, 0'>
<widget name = 'Container'/>
<widget name = 'Container'
type = 'ScrollContainerWidget'
/>
</layout>
</dialog>
@ -2072,6 +2084,7 @@
<dialog name = 'UnknownGameDialog' overlays = 'screen' inset = '8' shading = 'dim'>
<layout type = 'vertical' padding = '8, 8, 8, 0'>
<widget name = 'TextContainer'
type = 'ScrollContainerWidget'
/>
<layout type = 'horizontal' padding = '0, 0, 8, 8'>
<space/>

View file

@ -166,7 +166,7 @@ void Widget::draw() {
Widget *Widget::findWidgetInChain(Widget *w, int x, int y) {
while (w) {
// Stop as soon as we find a widget that contains the point (x,y)
if (x >= w->_x && x < w->_x + w->_w && y >= w->_y && y < w->_y + w->getHeight())
if (x >= w->_x && x < w->_x + w->getWidth() && y >= w->_y && y < w->_y + w->getHeight())
break;
w = w->_next;
}

View file

@ -41,7 +41,7 @@ void ScrollContainerWidget::init() {
setFlags(WIDGET_ENABLED);
_type = kScrollContainerWidget;
_backgroundType = ThemeEngine::kWidgetBackgroundPlain;
_verticalScroll = new ScrollBarWidget(this, _w-16, 0, 16, _h);
_verticalScroll = new ScrollBarWidget(this, _w, 0, 16, _h);
_verticalScroll->setTarget(this);
_scrolledX = 0;
_scrolledY = 0;
@ -54,7 +54,7 @@ void ScrollContainerWidget::handleMouseWheel(int x, int y, int direction) {
}
void ScrollContainerWidget::recalc() {
int scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
_scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
_limitH = _h;
//calculate virtual height
@ -78,8 +78,8 @@ void ScrollContainerWidget::recalc() {
_verticalScroll->_currentPos = _scrolledY;
_verticalScroll->_entriesPerPage = _limitH;
_verticalScroll->_singleStep = kLineHeight;
_verticalScroll->setPos(_w - scrollbarWidth, _scrolledY);
_verticalScroll->setSize(scrollbarWidth, _limitH-1);
_verticalScroll->setPos(_w, _scrolledY);
_verticalScroll->setSize(_scrollbarWidth, _limitH-1);
}
@ -94,7 +94,11 @@ int16 ScrollContainerWidget::getChildY() const {
}
uint16 ScrollContainerWidget::getWidth() const {
return _w - (_verticalScroll->isVisible() ? _verticalScroll->getWidth() : 0);
// NOTE: if you change that, make sure to do the same
// changes in the ThemeLayoutScrollContainerWidget (gui/ThemeLayout.cpp)
// NOTE: this width is used for clipping, so it *includes*
// scrollbars, because it starts from getAbsX(), not getChildX()
return _w + _scrollbarWidth;
}
uint16 ScrollContainerWidget::getHeight() const {
@ -142,6 +146,22 @@ void ScrollContainerWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight()), _backgroundType);
}
void ScrollContainerWidget::draw() {
Widget::draw();
if (_verticalScroll->isVisible()) {
_verticalScroll->draw();
}
}
void ScrollContainerWidget::markAsDirty() {
Widget::markAsDirty();
if (_verticalScroll->isVisible()) {
_verticalScroll->markAsDirty();
}
}
bool ScrollContainerWidget::containsWidget(Widget *w) const {
if (w == _verticalScroll || _verticalScroll->containsWidget(w))
return true;
@ -149,7 +169,7 @@ bool ScrollContainerWidget::containsWidget(Widget *w) const {
}
Widget *ScrollContainerWidget::findWidget(int x, int y) {
if (_verticalScroll->isVisible() && x >= _w - _verticalScroll->getWidth())
if (_verticalScroll->isVisible() && x >= _w)
return _verticalScroll;
Widget *w = Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
if (w)
@ -157,11 +177,6 @@ Widget *ScrollContainerWidget::findWidget(int x, int y) {
return this;
}
Common::Rect ScrollContainerWidget::getClipRect() const {
// Make sure the clipping rect contains the scrollbar so it is properly redrawn
return Common::Rect(getAbsX(), getAbsY(), getAbsX() + _w, getAbsY() + getHeight() - 1); // this -1 is because of container border, which might not be present actually
}
void ScrollContainerWidget::setBackgroundType(ThemeEngine::WidgetBackground backgroundType) {
_backgroundType = backgroundType;
}

View file

@ -31,6 +31,7 @@ namespace GUI {
class ScrollContainerWidget: public Widget, public CommandSender {
ScrollBarWidget *_verticalScroll;
int16 _scrolledX, _scrolledY;
int _scrollbarWidth;
uint16 _limitH;
uint32 _reflowCmd;
ThemeEngine::WidgetBackground _backgroundType;
@ -49,8 +50,6 @@ public:
bool containsWidget(Widget *) const override;
Common::Rect getClipRect() const override;
void setBackgroundType(ThemeEngine::WidgetBackground backgroundType);
void handleMouseWheel(int x, int y, int direction) override;
@ -62,6 +61,9 @@ public:
uint16 getWidth() const override;
uint16 getHeight() const override;
void draw() override;
void markAsDirty() override;
protected:
void drawWidget() override;