From eaab3f9a8a5a1bc429449a9a40c0798f2203947b Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 20 Mar 2020 16:33:29 +0400 Subject: [PATCH] Implement animated VerticalLayout reordering. --- ui/wrap/vertical_layout.cpp | 1 + ui/wrap/vertical_layout_reorder.cpp | 64 ++++++++++++++++++++++++++--- ui/wrap/vertical_layout_reorder.h | 6 +++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/ui/wrap/vertical_layout.cpp b/ui/wrap/vertical_layout.cpp index d588384..c43aa0a 100644 --- a/ui/wrap/vertical_layout.cpp +++ b/ui/wrap/vertical_layout.cpp @@ -55,6 +55,7 @@ void VerticalLayout::setVerticalShift(int index, int shift) { if (const auto delta = shift - row.verticalShift) { row.verticalShift = shift; row.widget->move(row.widget->x(), row.widget->y() + delta); + row.widget->update(); } } diff --git a/ui/wrap/vertical_layout_reorder.cpp b/ui/wrap/vertical_layout_reorder.cpp index bac99e0..f880602 100644 --- a/ui/wrap/vertical_layout_reorder.cpp +++ b/ui/wrap/vertical_layout_reorder.cpp @@ -7,6 +7,7 @@ #include "ui/wrap/vertical_layout_reorder.h" #include "ui/wrap/vertical_layout.h" +#include "styles/style_basic.h" #include #include @@ -95,7 +96,8 @@ void VerticalLayoutReorder::checkForStart(QPoint position) { void VerticalLayoutReorder::updateOrder(int index, QPoint position) { const auto shift = position.y() - _currentStart; auto ¤t = _entries[index]; - current.shift = shift; + current.shiftAnimation.stop(); + current.shift = current.finalShift = shift; _layout->setVerticalShift(index, shift); const auto count = _entries.size(); @@ -186,19 +188,69 @@ void VerticalLayoutReorder::finishCurrent() { const auto widget = _currentWidget; _currentState = State::Cancelled; _currentWidget = nullptr; + + auto ¤t = _entries[index]; + const auto height = current.widget->height(); + if (index < result) { + auto sum = 0; + for (auto i = index; i != result; ++i) { + auto &entry = _entries[i + 1]; + const auto widget = entry.widget; + entry.deltaShift += height; + updateShift(widget, i + 1); + sum += widget->height(); + } + current.finalShift -= sum; + } else if (index > result) { + auto sum = 0; + for (auto i = result; i != index; ++i) { + auto &entry = _entries[i]; + const auto widget = entry.widget; + entry.deltaShift -= height; + updateShift(widget, i); + sum += widget->height(); + } + current.finalShift += sum; + } + base::reorder(_entries, index, result); + _layout->reorderRows(index, _currentDesiredIndex); for (auto i = 0, count = int(_entries.size()); i != count; ++i) { moveToShift(i, 0); } - _layout->reorderRows(index, _currentDesiredIndex); - base::reorder(_entries, index, result); - _updates.fire({ widget, index, result, State::Applied }); } void VerticalLayoutReorder::moveToShift(int index, int shift) { - _layout->setVerticalShift(index, shift); - _entries[index].shift = shift; + auto &entry = _entries[index]; + if (entry.finalShift + entry.deltaShift == shift) { + return; + } + const auto widget = entry.widget; + entry.shiftAnimation.start( + [=] { updateShift(widget, index); }, + entry.finalShift, + shift - entry.deltaShift, + st::slideWrapDuration); + entry.finalShift = shift - entry.deltaShift; +} + +void VerticalLayoutReorder::updateShift( + not_null widget, + int indexHint) { + Expects(indexHint >= 0 && indexHint < _entries.size()); + + const auto index = (_entries[indexHint].widget == widget) + ? indexHint + : indexOf(widget); + auto &entry = _entries[index]; + entry.shift = std::round(entry.shiftAnimation.value(entry.finalShift)) + + entry.deltaShift; + if (entry.deltaShift && !entry.shiftAnimation.animating()) { + entry.finalShift += entry.deltaShift; + entry.deltaShift = 0; + } + _layout->setVerticalShift(index, entry.shift); } int VerticalLayoutReorder::indexOf(not_null widget) const { diff --git a/ui/wrap/vertical_layout_reorder.h b/ui/wrap/vertical_layout_reorder.h index 11578b7..d5e6769 100644 --- a/ui/wrap/vertical_layout_reorder.h +++ b/ui/wrap/vertical_layout_reorder.h @@ -6,6 +6,8 @@ // #pragma once +#include "ui/effects/animations.h" + namespace Ui { class RpWidget; @@ -34,7 +36,10 @@ public: private: struct Entry { not_null widget; + Ui::Animations::Simple shiftAnimation; int shift = 0; + int finalShift = 0; + int deltaShift = 0; }; void mouseMove(not_null widget, QPoint position); @@ -52,6 +57,7 @@ private: [[nodiscard]] int indexOf(not_null widget) const; void moveToShift(int index, int shift); + void updateShift(not_null widget, int indexHint); const not_null _layout;