From e2304a3c7661228c3b016fa9a47b0f772bb2aeeb Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 30 May 2022 14:03:39 +0300 Subject: [PATCH] Added ability to set pinned items for vertical layout reorder. --- ui/wrap/vertical_layout_reorder.cpp | 27 +++++++++++++++++++++++++++ ui/wrap/vertical_layout_reorder.h | 14 +++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ui/wrap/vertical_layout_reorder.cpp b/ui/wrap/vertical_layout_reorder.cpp index a750dfa..a4cc15f 100644 --- a/ui/wrap/vertical_layout_reorder.cpp +++ b/ui/wrap/vertical_layout_reorder.cpp @@ -75,6 +75,24 @@ void VerticalLayoutReorder::start() { } } +void VerticalLayoutReorder::addPinnedInterval(int from, int length) { + _pinnedIntervals.push_back({ from, length }); +} + +void VerticalLayoutReorder::clearPinnedIntervals() { + _pinnedIntervals.clear(); +} + +bool VerticalLayoutReorder::Interval::isIn(int index) const { + return (index >= from) && (index < (from + length)); +} + +bool VerticalLayoutReorder::isIndexPinned(int index) const { + return ranges::any_of(_pinnedIntervals, [&](const Interval &i) { + return i.isIn(index); + }); +} + void VerticalLayoutReorder::mouseMove( not_null widget, QPoint position) { @@ -105,6 +123,9 @@ void VerticalLayoutReorder::checkForStart(QPoint position) { } void VerticalLayoutReorder::updateOrder(int index, QPoint position) { + if (isIndexPinned(index)) { + return; + } const auto shift = position.y() - _currentStart; auto ¤t = _entries[index]; current.shiftAnimation.stop(); @@ -120,6 +141,9 @@ void VerticalLayoutReorder::updateOrder(int index, QPoint position) { if (shift > 0) { auto top = current.widget->y() - shift; for (auto next = index + 1; next != count; ++next) { + if (isIndexPinned(next)) { + return; + } const auto &entry = _entries[next]; top += entry.widget->height(); if (currentMiddle < top) { @@ -137,6 +161,9 @@ void VerticalLayoutReorder::updateOrder(int index, QPoint position) { moveToShift(next, 0); } for (auto prev = index - 1; prev >= 0; --prev) { + if (isIndexPinned(prev)) { + return; + } const auto &entry = _entries[prev]; if (currentMiddle >= entry.widget->y() - entry.shift + currentHeight) { moveToShift(prev, 0); diff --git a/ui/wrap/vertical_layout_reorder.h b/ui/wrap/vertical_layout_reorder.h index 1b28e76..87875b6 100644 --- a/ui/wrap/vertical_layout_reorder.h +++ b/ui/wrap/vertical_layout_reorder.h @@ -36,6 +36,8 @@ public: void start(); void cancel(); void finishReordering(); + void addPinnedInterval(int from, int length); + void clearPinnedIntervals(); [[nodiscard]] rpl::producer updates() const; private: @@ -46,6 +48,12 @@ private: int finalShift = 0; int deltaShift = 0; }; + struct Interval { + [[nodiscard]] bool isIn(int index) const; + + int from = 0; + int length = 0; + }; void mouseMove(not_null widget, QPoint position); void mousePress( @@ -66,13 +74,17 @@ private: void updateScrollCallback(); void checkForScrollAnimation(); - int deltaFromEdge(); + [[nodiscard]] int deltaFromEdge(); + + [[nodiscard]] bool isIndexPinned(int index) const; const not_null _layout; Ui::ScrollArea *_scroll = nullptr; Ui::Animations::Basic _scrollAnimation; + std::vector _pinnedIntervals; + RpWidget *_currentWidget = nullptr; int _currentStart = 0; int _currentDesiredIndex = 0;