From 276875bf52d8d50ad66be3fa169c79a3f2135876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Sat, 16 Apr 2016 10:27:09 +0300 Subject: [PATCH] libappfw|ScrollAreaWidget: Scrolling to show a specific widget --- .../include/de/widgets/scrollareawidget.h | 26 ++++++++++++++--- .../sdk/libappfw/src/widgets/menuwidget.cpp | 1 + .../libappfw/src/widgets/scrollareawidget.cpp | 28 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h b/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h index 046b3373f3..a7c502f942 100644 --- a/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h +++ b/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h @@ -114,6 +114,8 @@ class LIBAPPFW_PUBLIC ScrollAreaWidget : public GuiWidget void scrollX(int to, TimeDelta span = 0); void scrollY(int to, TimeDelta span = 0); + bool isScrollable() const; + /** * Determines if the history view is at the bottom, showing the latest entry. */ @@ -150,15 +152,31 @@ class LIBAPPFW_PUBLIC ScrollAreaWidget : public GuiWidget bool handleEvent(Event const &event) override; public slots: - void scrollToTop(TimeDelta span = .3f); + void scrollToTop(TimeDelta span = 0.3); /** * Moves the scroll offset of the widget to the bottom of the content. */ - void scrollToBottom(TimeDelta span = .3f); + void scrollToBottom(TimeDelta span = 0.3); + + void scrollToLeft(TimeDelta span = 0.3); + void scrollToRight(TimeDelta span = 0.3); - void scrollToLeft(TimeDelta span = .3f); - void scrollToRight(TimeDelta span = .3f); + /** + * Moves the scroll offset to center on the given widget. + * + * @param widget Widget to center on. + * @param span Animation duration. + */ + void scrollToWidget(GuiWidget const &widget, TimeDelta span = 0.3); + + /** + * Finds the topmost scroll area that can be scrolled. May return this widget + * if there are no scrollable ancestors. + * + * @return + */ + ScrollAreaWidget &findTopmostScrollable(); protected: void glInit() override; diff --git a/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp b/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp index c4f01f2687..b5844bed9e 100644 --- a/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp +++ b/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp @@ -546,6 +546,7 @@ bool MenuWidget::handleEvent(Event const &event) if(child->isVisible() && child->behavior().testFlag(Focusable)) { root().setFocus(child); + findTopmostScrollable().scrollToWidget(child->as()); return true; } } diff --git a/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp b/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp index 1af031b2b1..0de0556df6 100644 --- a/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp +++ b/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp @@ -354,6 +354,11 @@ void ScrollAreaWidget::scrollY(int to, TimeDelta span) d->restartScrollOpacityFade(); } +bool ScrollAreaWidget::isScrollable() const +{ + return d->scrollingEnabled && maximumScrollY().valuei() > 0; +} + bool ScrollAreaWidget::isAtBottom() const { return d->origin == Bottom && d->y->animation().target() == 0; @@ -485,6 +490,29 @@ void ScrollAreaWidget::scrollToRight(TimeDelta span) scrollX(maximumScrollX().valuei(), span); } +void ScrollAreaWidget::scrollToWidget(GuiWidget const &widget, TimeDelta span) +{ + int off = widget.rule().midY().valuei() - contentRule().top().valuei() - + rule().height().valuei()/2; + qDebug() << "scroll off:" << off; + scrollY(off, span); +} + +ScrollAreaWidget &ScrollAreaWidget::findTopmostScrollable() +{ + for(Widget *parent = parentWidget(); parent; parent = parent->parent()) + { + if(ScrollAreaWidget *scroll = parent->maybeAs()) + { + if(scroll->isScrollable()) + { + return *scroll; + } + } + } + return *this; +} + void ScrollAreaWidget::glInit() { d->glInit();