Added ability to set pinned items for vertical layout reorder.

This commit is contained in:
23rd 2022-05-30 14:03:39 +03:00
parent 060eb63ce8
commit e2304a3c76
2 changed files with 40 additions and 1 deletions

View file

@ -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( void VerticalLayoutReorder::mouseMove(
not_null<RpWidget*> widget, not_null<RpWidget*> widget,
QPoint position) { QPoint position) {
@ -105,6 +123,9 @@ void VerticalLayoutReorder::checkForStart(QPoint position) {
} }
void VerticalLayoutReorder::updateOrder(int index, QPoint position) { void VerticalLayoutReorder::updateOrder(int index, QPoint position) {
if (isIndexPinned(index)) {
return;
}
const auto shift = position.y() - _currentStart; const auto shift = position.y() - _currentStart;
auto &current = _entries[index]; auto &current = _entries[index];
current.shiftAnimation.stop(); current.shiftAnimation.stop();
@ -120,6 +141,9 @@ void VerticalLayoutReorder::updateOrder(int index, QPoint position) {
if (shift > 0) { if (shift > 0) {
auto top = current.widget->y() - shift; auto top = current.widget->y() - shift;
for (auto next = index + 1; next != count; ++next) { for (auto next = index + 1; next != count; ++next) {
if (isIndexPinned(next)) {
return;
}
const auto &entry = _entries[next]; const auto &entry = _entries[next];
top += entry.widget->height(); top += entry.widget->height();
if (currentMiddle < top) { if (currentMiddle < top) {
@ -137,6 +161,9 @@ void VerticalLayoutReorder::updateOrder(int index, QPoint position) {
moveToShift(next, 0); moveToShift(next, 0);
} }
for (auto prev = index - 1; prev >= 0; --prev) { for (auto prev = index - 1; prev >= 0; --prev) {
if (isIndexPinned(prev)) {
return;
}
const auto &entry = _entries[prev]; const auto &entry = _entries[prev];
if (currentMiddle >= entry.widget->y() - entry.shift + currentHeight) { if (currentMiddle >= entry.widget->y() - entry.shift + currentHeight) {
moveToShift(prev, 0); moveToShift(prev, 0);

View file

@ -36,6 +36,8 @@ public:
void start(); void start();
void cancel(); void cancel();
void finishReordering(); void finishReordering();
void addPinnedInterval(int from, int length);
void clearPinnedIntervals();
[[nodiscard]] rpl::producer<Single> updates() const; [[nodiscard]] rpl::producer<Single> updates() const;
private: private:
@ -46,6 +48,12 @@ private:
int finalShift = 0; int finalShift = 0;
int deltaShift = 0; int deltaShift = 0;
}; };
struct Interval {
[[nodiscard]] bool isIn(int index) const;
int from = 0;
int length = 0;
};
void mouseMove(not_null<RpWidget*> widget, QPoint position); void mouseMove(not_null<RpWidget*> widget, QPoint position);
void mousePress( void mousePress(
@ -66,13 +74,17 @@ private:
void updateScrollCallback(); void updateScrollCallback();
void checkForScrollAnimation(); void checkForScrollAnimation();
int deltaFromEdge(); [[nodiscard]] int deltaFromEdge();
[[nodiscard]] bool isIndexPinned(int index) const;
const not_null<Ui::VerticalLayout*> _layout; const not_null<Ui::VerticalLayout*> _layout;
Ui::ScrollArea *_scroll = nullptr; Ui::ScrollArea *_scroll = nullptr;
Ui::Animations::Basic _scrollAnimation; Ui::Animations::Basic _scrollAnimation;
std::vector<Interval> _pinnedIntervals;
RpWidget *_currentWidget = nullptr; RpWidget *_currentWidget = nullptr;
int _currentStart = 0; int _currentStart = 0;
int _currentDesiredIndex = 0; int _currentDesiredIndex = 0;