LCOV - code coverage report
Current view: top level - xenolith/renderer/basic2d - XL2dScrollView.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 232 367 63.2 %
Date: 2024-05-12 00:16:13 Functions: 42 56 75.0 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "XL2dScrollView.h"
      24             : #include "XL2dLayerRounded.h"
      25             : #include "XLActionEase.h"
      26             : 
      27             : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
      28             : 
      29          92 : bool ScrollView::Overscroll::init() {
      30          92 :         if (!VectorSprite::init(Size2(8.0f, 8.0f))) {
      31           0 :                 return false;
      32             :         }
      33             : 
      34          92 :         return true;
      35             : }
      36             : 
      37           0 : bool ScrollView::Overscroll::init(Direction dir) {
      38           0 :         if (!VectorSprite::init(Size2(8.0f, 8.0f))) {
      39           0 :                 return false;
      40             :         }
      41             : 
      42           0 :         _direction = dir;
      43           0 :         return true;
      44             : }
      45             : 
      46          68 : void ScrollView::Overscroll::onContentSizeDirty() {
      47          68 :         VectorSprite::onContentSizeDirty();
      48             : 
      49          68 :         if (_contentSize == Size2::ZERO) {
      50           0 :                 _image->clear();
      51          68 :         } else if (_image->getImageSize() != _contentSize) {
      52          68 :                 auto image = Rc<VectorImage>::create(_contentSize);
      53          68 :                 updateProgress(image);
      54          68 :                 setImage(move(image));
      55          68 :         } else if (_progressDirty) {
      56           0 :                 updateProgress(_image);
      57             :         }
      58          68 : }
      59             : 
      60       26330 : void ScrollView::Overscroll::update(const UpdateTime &time) {
      61       26330 :         VectorSprite::update(time);
      62       26330 :         if (TimeInterval(time.global - _delayStart) > TimeInterval::microseconds(250000)) {
      63       26330 :                 decrementProgress(time.dt);
      64             :         }
      65       26330 : }
      66             : 
      67          92 : void ScrollView::Overscroll::onEnter(Scene *scene) {
      68          92 :         VectorSprite::onEnter(scene);
      69          92 :         scheduleUpdate();
      70          92 : }
      71             : 
      72          92 : void ScrollView::Overscroll::onExit() {
      73          92 :         unscheduleUpdate();
      74          92 :         VectorSprite::onExit();
      75          92 : }
      76             : 
      77         116 : void ScrollView::Overscroll::setDirection(Direction dir) {
      78         116 :         if (_direction != dir) {
      79          38 :                 _direction = dir;
      80          38 :                 _progressDirty = _contentSizeDirty = true;
      81             :         }
      82         116 : }
      83             : 
      84           0 : ScrollView::Overscroll::Direction ScrollView::Overscroll::getDirection() const {
      85           0 :         return _direction;
      86             : }
      87             : 
      88       26330 : void ScrollView::Overscroll::setProgress(float p) {
      89       26330 :         p = math::clamp(p, 0.0f, 1.0f);
      90       26330 :         if (p != _progress) {
      91           0 :                 _progress = p;
      92           0 :                 _progressDirty = _contentSizeDirty = true;
      93             :         }
      94       26330 : }
      95             : 
      96           0 : void ScrollView::Overscroll::incrementProgress(float dt) {
      97           0 :         setProgress(_progress + (dt * ((1.0 - _progress) * (1.0 - _progress))));
      98           0 :         _delayStart = Time::now().toMicros();
      99           0 : }
     100             : 
     101       26330 : void ScrollView::Overscroll::decrementProgress(float dt) {
     102       26330 :         setProgress(_progress - (dt * 2.5f));
     103       26330 : }
     104             : 
     105          68 : void ScrollView::Overscroll::updateProgress(VectorImage *) {
     106             : 
     107          68 : }
     108             : 
     109          46 : bool ScrollView::init(Layout l) {
     110          46 :         if (!ScrollViewBase::init(l)) {
     111           0 :                 return false;
     112             :         }
     113             : 
     114          46 :         _indicator = addChild(Rc<LayerRounded>::create(Color4F(1.0f, 1.0f, 1.0f, 0.0f), 2.0f), ZOrder(1));
     115          46 :         _indicator->setAnchorPoint(Vec2(1, 0));
     116             : 
     117          46 :         _overflowFront = addChild(Rc<Overscroll>::create());
     118          46 :         _overflowBack = addChild(Rc<Overscroll>::create());
     119             : 
     120          46 :         setOverscrollColor(Color4F(0.5f, 0.5f, 0.5f, 1.0f));
     121          46 :         setOverscrollVisible(!_bounce);
     122             : 
     123          46 :         return true;
     124             : }
     125             : 
     126          58 : void ScrollView::onContentSizeDirty() {
     127          58 :         ScrollViewBase::onContentSizeDirty();
     128          58 :         if (isVertical()) {
     129          54 :                 _overflowFront->setAnchorPoint(Vec2(0, 1)); // top
     130          54 :                 _overflowFront->setDirection(Overscroll::Direction::Top);
     131          54 :                 _overflowFront->setPosition(Vec2(0, _contentSize.height - _overscrollFrontOffset));
     132          54 :                 _overflowFront->setContentSize(Size2(_contentSize.width,
     133          54 :                                 std::min(_contentSize.width * Overscroll::OverscrollScale, Overscroll::OverscrollMaxHeight)));
     134             : 
     135          54 :                 _overflowBack->setAnchorPoint(Vec2(0, 0)); // bottom
     136          54 :                 _overflowBack->setDirection(Overscroll::Direction::Bottom);
     137          54 :                 _overflowBack->setPosition(Vec2(0, _overscrollBackOffset));
     138          54 :                 _overflowBack->setContentSize(Size2(_contentSize.width,
     139         108 :                                 std::min(_contentSize.width * Overscroll::OverscrollScale, Overscroll::OverscrollMaxHeight)));
     140             : 
     141             :         } else {
     142           4 :                 _overflowFront->setAnchorPoint(Vec2(0, 0)); // left
     143           4 :                 _overflowFront->setDirection(Overscroll::Direction::Left);
     144           4 :                 _overflowFront->setPosition(Vec2(_overscrollFrontOffset, 0));
     145           4 :                 _overflowFront->setContentSize(Size2(
     146           4 :                                 std::min(_contentSize.height * Overscroll::OverscrollScale, Overscroll::OverscrollMaxHeight),
     147             :                                 _contentSize.height));
     148             : 
     149           4 :                 _overflowBack->setAnchorPoint(Vec2(1, 0)); // right
     150           4 :                 _overflowBack->setDirection(Overscroll::Direction::Right);
     151           4 :                 _overflowBack->setPosition(Vec2(_contentSize.width - _overscrollBackOffset, 0));
     152           4 :                 _overflowBack->setContentSize(Size2(
     153           8 :                                 std::min(_contentSize.height * Overscroll::OverscrollScale, Overscroll::OverscrollMaxHeight),
     154             :                                 _contentSize.height));
     155             :         }
     156          58 :         updateIndicatorPosition();
     157          58 : }
     158             : 
     159          46 : void ScrollView::setOverscrollColor(const Color4F &val, bool withOpacity) {
     160          46 :         _overflowFront->setColor(val, withOpacity);
     161          46 :         _overflowBack->setColor(val, withOpacity);
     162          46 : }
     163             : 
     164           3 : Color4F ScrollView::getOverscrollColor() const {
     165           3 :         return _overflowFront->getColor();
     166             : }
     167             : 
     168          48 : void ScrollView::setOverscrollVisible(bool value) {
     169          48 :         _overflowFront->setVisible(value);
     170          48 :         _overflowBack->setVisible(value);
     171          48 : }
     172             : 
     173           3 : bool ScrollView::isOverscrollVisible() const {
     174           3 :         return _overflowFront->isVisible();
     175             : }
     176             : 
     177          10 : void ScrollView::setIndicatorColor(const Color4B &val, bool withOpacity) {
     178          10 :         _indicator->setPathColor(val, withOpacity);
     179          10 : }
     180             : 
     181           3 : Color4F ScrollView::getIndicatorColor() const {
     182           3 :         return _indicator->getColor();
     183             : }
     184             : 
     185           5 : void ScrollView::setIndicatorVisible(bool value) {
     186           5 :         _indicatorVisible = value;
     187           5 :         if (!isnan(getScrollLength())) {
     188           5 :                 _indicator->setVisible(value);
     189             :         } else {
     190           0 :                 _indicator->setVisible(false);
     191             :         }
     192           5 : }
     193             : 
     194           3 : bool ScrollView::isIndicatorVisible() const {
     195           3 :         return _indicatorVisible;
     196             : }
     197             : 
     198         299 : void ScrollView::doSetScrollPosition(float pos) {
     199         299 :         ScrollViewBase::doSetScrollPosition(pos);
     200         299 :         updateIndicatorPosition();
     201         299 : }
     202             : 
     203           0 : void ScrollView::onOverscroll(float delta) {
     204           0 :         ScrollViewBase::onOverscroll(delta);
     205           0 :         if (isOverscrollVisible()) {
     206           0 :                 if (delta > 0.0f) {
     207           0 :                         _overflowBack->incrementProgress(delta / 50.0f);
     208             :                 } else {
     209           0 :                         _overflowFront->incrementProgress(-delta / 50.0f);
     210             :                 }
     211             :         }
     212           0 : }
     213             : 
     214         333 : void ScrollView::onScroll(float delta, bool finished) {
     215         333 :         ScrollViewBase::onScroll(delta, finished);
     216         333 :         if (!finished) {
     217         333 :                 updateIndicatorPosition();
     218             :         }
     219         333 : }
     220             : 
     221           0 : void ScrollView::onTap(int count, const Vec2 &loc) {
     222           0 :         if (_tapCallback) {
     223           0 :                 _tapCallback(count, loc);
     224             :         }
     225           0 : }
     226             : 
     227          38 : void ScrollView::onAnimationFinished() {
     228          38 :         ScrollViewBase::onAnimationFinished();
     229          38 :         if (_animationCallback) {
     230           6 :                 _animationCallback();
     231             :         }
     232          38 :         updateIndicatorPosition();
     233          38 : }
     234             : 
     235         328 : void ScrollView::updateIndicatorPosition() {
     236         328 :         if (!_indicatorVisible) {
     237           4 :                 return;
     238             :         }
     239             : 
     240         324 :         const float scrollWidth = _contentSize.width;
     241         324 :         const float scrollHeight = _contentSize.height;
     242         324 :         const float scrollLength = getScrollLength();
     243             : 
     244         324 :         updateIndicatorPosition(_indicator, (isVertical()?scrollHeight:scrollWidth) / scrollLength,
     245         324 :                         (_scrollPosition - getScrollMinPosition()) / (getScrollMaxPosition() - getScrollMinPosition()), true, 20.0f);
     246             : }
     247             : 
     248         724 : void ScrollView::updateIndicatorPosition(Node *indicator, float size, float value, bool actions, float min) {
     249         724 :         if (!_indicatorVisible) {
     250           0 :                 return;
     251             :         }
     252             : 
     253         724 :         float scrollWidth = _contentSize.width;
     254         724 :         float scrollHeight = _contentSize.height;
     255             : 
     256         724 :         float scrollLength = getScrollLength();
     257         724 :         if (isnan(scrollLength)) {
     258          78 :                 indicator->setVisible(false);
     259             :         } else {
     260         646 :                 indicator->setVisible(_indicatorVisible);
     261             :         }
     262             : 
     263         724 :         auto paddingLocal = _paddingGlobal;
     264         724 :         if (_indicatorIgnorePadding) {
     265         127 :                 if (isVertical()) {
     266         127 :                         paddingLocal.top = 0;
     267         127 :                         paddingLocal.bottom = 0;
     268             :                 } else {
     269           0 :                         paddingLocal.left = 0;
     270           0 :                         paddingLocal.right = 0;
     271             :                 }
     272             :         }
     273             : 
     274         724 :         if (scrollLength > _scrollSize) {
     275         602 :                 if (isVertical()) {
     276         602 :                         float h = (scrollHeight - 4 - paddingLocal.top - paddingLocal.bottom) * size;
     277         602 :                         if (h < min) {
     278           0 :                                 h = min;
     279             :                         }
     280         602 :                         float r = scrollHeight - h - 4 - paddingLocal.top - paddingLocal.bottom;
     281             : 
     282         602 :                         indicator->setContentSize(Size2(3, h));
     283         602 :                         indicator->setPosition(Vec2(scrollWidth - 2, paddingLocal.bottom + 2 + r * (1.0f - value)));
     284         602 :                         indicator->setAnchorPoint(Vec2(1, 0));
     285             :                 } else {
     286           0 :                         float h = (scrollWidth - 4 - paddingLocal.left - paddingLocal.right) * size;
     287           0 :                         if (h < min) {
     288           0 :                                 h = min;
     289             :                         }
     290           0 :                         float r = scrollWidth - h - 4 - paddingLocal.left - paddingLocal.right;
     291             : 
     292           0 :                         indicator->setContentSize(Size2(h, 3));
     293           0 :                         indicator->setPosition(Vec2(paddingLocal.left + 2 + r * (value), 2));
     294           0 :                         indicator->setAnchorPoint(Vec2(0, 0));
     295             :                 }
     296         602 :                 if (actions) {
     297         602 :                         if (indicator->getOpacity() != 1.0f) {
     298         123 :                                 Action* a = indicator->getActionByTag(19);
     299         123 :                                 if (!a) {
     300          24 :                                         indicator->runAction(Rc<FadeTo>::create(progress(0.1f, 0.0f, indicator->getOpacity()), 1.0f), 19);
     301             :                                 }
     302             :                         }
     303             : 
     304         602 :                         indicator->stopActionByTag(18);
     305         602 :                         auto fade = Rc<Sequence>::create(2.0f, Rc<FadeTo>::create(0.25f, 0.0f));
     306         602 :                         indicator->runAction(fade, 18);
     307         602 :                 }
     308             :         } else {
     309         122 :                 indicator->setVisible(false);
     310             :         }
     311             : }
     312             : 
     313          30 : void ScrollView::setPadding(const Padding &p) {
     314          30 :         if (p != _paddingGlobal) {
     315          10 :                 float offset = (isVertical()?_paddingGlobal.top:_paddingGlobal.left);
     316          10 :                 float newOffset = (isVertical()?p.top:p.left);
     317          10 :                 ScrollViewBase::setPadding(p);
     318             : 
     319          10 :                 if (offset != newOffset) {
     320          10 :                         setScrollPosition(getScrollPosition() + (offset - newOffset));
     321             :                 }
     322             :         }
     323          30 : }
     324             : 
     325          43 : void ScrollView::setOverscrollFrontOffset(float value) {
     326          43 :         if (_overscrollFrontOffset != value) {
     327          33 :                 _overscrollFrontOffset = value;
     328          33 :                 _contentSizeDirty = true;
     329             :         }
     330          43 : }
     331           3 : float ScrollView::getOverscrollFrontOffset() const {
     332           3 :         return _overscrollFrontOffset;
     333             : }
     334             : 
     335           3 : void ScrollView::setOverscrollBackOffset(float value) {
     336           3 :         if (_overscrollBackOffset != value) {
     337           3 :                 _overscrollBackOffset = value;
     338           3 :                 _contentSizeDirty = true;
     339             :         }
     340           3 : }
     341           3 : float ScrollView::getOverscrollBackOffset() const {
     342           3 :         return _overscrollBackOffset;
     343             : }
     344             : 
     345           3 : void ScrollView::setIndicatorIgnorePadding(bool value) {
     346           3 :         if (_indicatorIgnorePadding != value) {
     347           3 :                 _indicatorIgnorePadding = value;
     348             :         }
     349           3 : }
     350           3 : bool ScrollView::isIndicatorIgnorePadding() const {
     351           3 :         return _indicatorIgnorePadding;
     352             : }
     353             : 
     354           3 : void ScrollView::setTapCallback(const TapCallback &cb) {
     355           3 :         _tapCallback = cb;
     356           3 : }
     357             : 
     358           3 : const ScrollView::TapCallback &ScrollView::getTapCallback() const {
     359           3 :         return _tapCallback;
     360             : }
     361             : 
     362           3 : void ScrollView::setAnimationCallback(const AnimationCallback &cb) {
     363           3 :         _animationCallback = cb;
     364           3 : }
     365             : 
     366           3 : const ScrollView::AnimationCallback &ScrollView::getAnimationCallback() const {
     367           3 :         return _animationCallback;
     368             : }
     369             : 
     370           0 : void ScrollView::update(const UpdateTime &time) {
     371           0 :         auto newpos = getScrollPosition();
     372           0 :         auto factor = std::min(64.0f, _adjustValue);
     373             : 
     374           0 :         switch (_adjust) {
     375           0 :         case Adjust::Front:
     376           0 :                 newpos += (45.0f + progress(0.0f, 200.0f, factor / 32.0f)) * time.dt;
     377           0 :                 break;
     378           0 :         case Adjust::Back:
     379           0 :                 newpos -= (45.0f + progress(0.0f, 200.0f, factor / 32.0f)) * time.dt;
     380           0 :                 break;
     381           0 :         default:
     382           0 :                 break;
     383             :         }
     384             : 
     385           0 :         if (newpos != getScrollPosition()) {
     386           0 :                 if (newpos < getScrollMinPosition()) {
     387           0 :                         newpos = getScrollMinPosition();
     388           0 :                 } else if (newpos > getScrollMaxPosition()) {
     389           0 :                         newpos = getScrollMaxPosition();
     390             :                 }
     391           0 :                 _root->stopAllActionsByTag("ScrollViewAdjust"_tag);
     392           0 :                 setScrollPosition(newpos);
     393             :         }
     394           0 : }
     395             : 
     396           0 : void ScrollView::runAdjustPosition(float newPos, float factor) {
     397           0 :         if (!isnan(newPos)) {
     398           0 :                 if (newPos < getScrollMinPosition()) {
     399           0 :                         newPos = getScrollMinPosition();
     400           0 :                 } else if (newPos > getScrollMaxPosition()) {
     401           0 :                         newPos = getScrollMaxPosition();
     402             :                 }
     403           0 :                 if (_adjustValue != newPos) {
     404           0 :                         _adjustValue = newPos;
     405           0 :                         auto dist = fabsf(newPos - getScrollPosition());
     406             : 
     407           0 :                         auto t = 0.15f;
     408           0 :                         if (dist < 20.0f) {
     409           0 :                                 t = 0.15f;
     410           0 :                         } else if (dist > 220.0f) {
     411           0 :                                 t = 0.45f;
     412             :                         } else {
     413           0 :                                 t = progress(0.15f, 0.45f, (dist - 20.0f) / 200.0f);
     414             :                         }
     415           0 :                         _root->stopAllActionsByTag("ScrollViewAdjust"_tag);
     416           0 :                         auto a = Rc<Sequence>::create(Rc<EaseQuadraticActionInOut>::create(Rc<MoveTo>::create(t,
     417           0 :                                         isVertical()?Vec2(_root->getPosition().x, newPos + _scrollSize):Vec2(-newPos, _root->getPosition().y))),
     418           0 :                                         [this] { _adjustValue = nan(); });
     419           0 :                         _root->runAction(a, "ScrollViewAdjust"_tag);
     420           0 :                 }
     421             :         }
     422           0 : }
     423           0 : void ScrollView::runAdjust(float pos, float factor) {
     424           0 :         auto scrollPos = getScrollPosition();
     425           0 :         auto scrollSize = getScrollSize();
     426             : 
     427           0 :         float newPos = nan();
     428           0 :         if (scrollSize < 64.0f +  48.0f) {
     429           0 :                 newPos = ((pos - 64.0f) + (pos - scrollSize + 48.0f)) / 2.0f;
     430           0 :         } else if (pos < scrollPos + 64.0f) {
     431           0 :                 newPos = pos - 64.0f;
     432           0 :         } else if (pos > scrollPos + scrollSize - 48.0f) {
     433           0 :                 newPos = pos - scrollSize + 48.0f;
     434             :         }
     435             : 
     436           0 :         runAdjustPosition(newPos, factor);
     437           0 : }
     438             : 
     439           0 : void ScrollView::scheduleAdjust(Adjust a, float val) {
     440           0 :         _adjustValue = val;
     441           0 :         if (a != _adjust) {
     442           0 :                 _adjust = a;
     443           0 :                 switch (_adjust) {
     444           0 :                 case Adjust::None:
     445           0 :                         unscheduleUpdate();
     446           0 :                         _adjustValue = nan();
     447           0 :                         break;
     448           0 :                 default:
     449           0 :                         scheduleUpdate();
     450           0 :                         break;
     451             :                 }
     452             :         }
     453           0 : }
     454             : 
     455           3 : Value ScrollView::save() const {
     456           3 :         Value ret;
     457           3 :         ret.setDouble(getScrollRelativePosition(), "value");
     458           3 :         return ret;
     459           0 : }
     460             : 
     461           3 : void ScrollView::load(const Value &d) {
     462           3 :         if (d.isDictionary()) {
     463           0 :                 _savedRelativePosition = d.getDouble("value");
     464           0 :                 if (_controller) {
     465           0 :                         _controller->onScrollPosition(true);
     466             :                 }
     467             :         }
     468           3 : }
     469             : 
     470           6 : ScrollController::Item * ScrollView::getItemForNode(Node *node) const {
     471           6 :         auto &items = _controller->getItems();
     472          84 :         for (auto &it : items) {
     473          84 :                 if (it.node && it.node == node) {
     474           6 :                         return &it;
     475             :                 }
     476             :         }
     477           0 :         return nullptr;
     478             : }
     479             : 
     480           3 : Rc<ActionProgress> ScrollView::resizeNode(Node *node, float newSize, float duration, Function<void()> &&cb) {
     481           3 :         return resizeNode(getItemForNode(node), newSize, duration, move(cb));
     482             : }
     483             : 
     484           6 : Rc<ActionProgress> ScrollView::resizeNode(ScrollController::Item *item, float newSize, float duration, Function<void()> &&cb) {
     485           6 :         if (!item) {
     486           0 :                 return nullptr;
     487             :         }
     488             : 
     489           6 :         auto &items = _controller->getItems();
     490             : 
     491           6 :         float sourceSize = isVertical()?item->size.height:item->size.width;
     492           6 :         float tergetSize = newSize;
     493             : 
     494             :         struct ItemRects {
     495             :                 float startPos;
     496             :                 float startSize;
     497             :                 float targetPos;
     498             :                 float targetSize;
     499             :                 ScrollController::Item *item;
     500             :         };
     501             : 
     502           6 :         Vector<ItemRects> vec;
     503             : 
     504           6 :         float offset = 0.0f;
     505         462 :         for (auto &it : items) {
     506         456 :                 if (it.node && &it == item) {
     507           6 :                         offset += sourceSize - tergetSize;
     508           6 :                         vec.emplace_back(ItemRects{
     509           6 :                                 getNodeScrollPosition(it.pos),
     510           6 :                                 getNodeScrollSize(it.size),
     511           6 :                                 getNodeScrollPosition(it.pos),
     512             :                                 tergetSize,
     513             :                                 &it});
     514         450 :                 } else if (offset != 0.0f) {
     515         372 :                         vec.emplace_back(ItemRects{
     516         372 :                                 getNodeScrollPosition(it.pos),
     517         372 :                                 getNodeScrollSize(it.size),
     518         372 :                                 getNodeScrollPosition(it.pos) - offset,
     519         372 :                                 getNodeScrollSize(it.size),
     520             :                                 &it});
     521             :                 }
     522             :         }
     523             : 
     524           0 :         auto ret = Rc<ActionProgress>::create(duration, [this, vec] (float p) {
     525           0 :                 for (auto &it : vec) {
     526           0 :                         if (isVertical()) {
     527           0 :                                 it.item->pos.y = progress(it.startPos, it.targetPos, p);
     528           0 :                                 it.item->size.height = progress(it.startSize, it.targetSize, p);
     529             :                         } else {
     530           0 :                                 it.item->pos.x = progress(it.startPos, it.targetPos, p);
     531           0 :                                 it.item->size.width = progress(it.startSize, it.targetSize, p);
     532             :                         }
     533           0 :                         if (it.item->node) {
     534           0 :                                 updateScrollNode(it.item->node, it.item->pos, it.item->size, it.item->zIndex, it.item->name);
     535             :                         }
     536             :                 }
     537           0 :                 _controller->onScrollPosition(true);
     538           0 :         }, [] () {
     539             : 
     540           6 :         }, [cb = move(cb)] () {
     541           0 :                 if (cb) {
     542           0 :                         cb();
     543             :                 }
     544          12 :         });
     545           6 :         return ret;
     546           6 : }
     547             : 
     548           3 : Rc<ActionProgress> ScrollView::removeNode(Node *node, float duration, Function<void()> &&cb, bool disable) {
     549           3 :         return removeNode(getItemForNode(node), duration, move(cb), disable);
     550             : }
     551             : 
     552           3 : Rc<ActionProgress> ScrollView::removeNode(ScrollController::Item *item, float duration, Function<void()> &&cb, bool disable) {
     553           3 :         return resizeNode(item, 0.0f, duration, [item, cb = move(cb), disable] {
     554           0 :                 if (item->node) {
     555           0 :                         if (item->node->isRunning()) {
     556           0 :                                 item->node->removeFromParent();
     557             :                         }
     558           0 :                         item->node = nullptr;
     559           0 :                         item->handle = nullptr;
     560           0 :                         if (disable) {
     561           0 :                                 item->nodeFunction = nullptr;
     562             :                         }
     563             :                 }
     564           0 :                 if (cb) {
     565           0 :                         cb();
     566             :                 }
     567           3 :         });
     568             : }
     569             : 
     570             : }

Generated by: LCOV version 1.14