Added icon for reorder to media list section with one column mode.

This commit is contained in:
23rd
2025-11-17 11:02:00 +03:00
parent 18422c4193
commit 035087987c
4 changed files with 97 additions and 13 deletions
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_shared_media.h"
#include "layout/layout_selection.h"
#include "ui/rect.h"
#include "ui/painter.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_info.h"
@@ -45,6 +46,10 @@ int ListSection::top() const {
return _top;
}
void ListSection::setCanReorder(bool value) {
_canReorder = value;
}
int ListSection::height() const {
return _height;
}
@@ -276,6 +281,15 @@ void ListSection::paint(
itemSelection(item, context),
&localContext);
p.translate(-rect.topLeft());
if (_canReorder && isOneColumn()) {
st::stickersReorderIcon.paint(
p,
rect::right(rect) - oneColumnRightPadding(),
(rect.height() - st::stickersReorderIcon.height()) / 2
+ rect.y(),
outerWidth);
}
}
}
}
@@ -334,6 +348,14 @@ int ListSection::headerHeight() const {
return _header.isEmpty() ? 0 : st::infoMediaHeaderHeight;
}
int ListSection::oneColumnRightPadding() const {
return !isOneColumn()
? 0
: _canReorder
? st::stickersReorderIcon.width() + st::infoMediaLeft
: 0;
}
void ListSection::resizeToWidth(int newWidth) {
auto minWidth = st::infoMediaMinGridSize + st::infoMediaSkip * 2;
if (newWidth < minWidth) {
@@ -341,12 +363,13 @@ void ListSection::resizeToWidth(int newWidth) {
}
auto resizeOneColumn = [&](int itemsLeft, int itemWidth) {
const auto rightPadding = oneColumnRightPadding();
_itemsLeft = itemsLeft;
_itemsTop = 0;
_itemsInRow = 1;
_itemWidth = itemWidth;
_itemWidth = itemWidth - rightPadding;
for (auto &item : _items) {
item->resizeGetHeight(_itemWidth);
item->resizeGetHeight(_itemWidth - rightPadding);
}
};
switch (_type) {
@@ -26,11 +26,13 @@ public:
void setTop(int top);
[[nodiscard]] int top() const;
void setCanReorder(bool);
void resizeToWidth(int newWidth);
[[nodiscard]] int height() const;
[[nodiscard]] int bottom() const;
[[nodiscard]] bool isOneColumn() const;
[[nodiscard]] int oneColumnRightPadding() const;
bool removeItem(not_null<const HistoryItem*> item);
void reorderItems(int oldPosition, int newPosition);
@@ -89,6 +91,7 @@ private:
mutable int _rowsCount = 0;
int _top = 0;
int _height = 0;
bool _canReorder = false;
Mosaic::Layout::MosaicLayout<BaseLayout> _mosaic;
@@ -73,6 +73,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_menu_icons.h"
#include "styles/style_chat.h"
#include "styles/style_credits.h" // giftBoxHiddenMark
#include "styles/style_chat_helpers.h"
#include <QtWidgets/QApplication>
#include <QtGui/QClipboard>
@@ -395,6 +396,8 @@ void ListWidget::restart() {
_heavyLayouts.clear();
_provider->restart();
_reorderState = {};
}
void ListWidget::itemRemoved(not_null<const HistoryItem*> item) {
@@ -406,6 +409,10 @@ void ListWidget::itemRemoved(not_null<const HistoryItem*> item) {
_contextItem = nullptr;
}
if (_reorderState.item && _reorderState.item->getItem() == item) {
_reorderState = {};
}
auto needHeightRefresh = false;
auto sectionIt = findSectionByItem(item);
if (sectionIt != _sections.end()) {
@@ -673,6 +680,7 @@ void ListWidget::markStoryMsgsSelected() {
void ListWidget::refreshRows() {
saveScrollState();
_reorderState = {};
_sections.clear();
_sections = _provider->fillSections(this);
@@ -714,6 +722,7 @@ void ListWidget::restoreState(not_null<Memento*> memento) {
int ListWidget::resizeGetHeight(int newWidth) {
if (newWidth > 0) {
for (auto &section : _sections) {
section.setCanReorder(canReorder());
section.resizeToWidth(newWidth);
}
}
@@ -985,6 +994,8 @@ void ListWidget::paintEvent(QPaintEvent *e) {
if (_mouseAction == MouseAction::Reordering && _reorderState.item) {
auto o = ScopedPainterOpacity(p, 0.8);
p.translate(_reorderState.currentPos);
const auto isOneColumn = _reorderState.section
&& _reorderState.section->isOneColumn();
_reorderState.item->paint(
p,
QRect(
@@ -992,8 +1003,18 @@ void ListWidget::paintEvent(QPaintEvent *e) {
0,
_reorderState.item->maxWidth(),
_reorderState.item->minHeight()),
FullSelection,
isOneColumn ? TextSelection{} : FullSelection,
&context.layoutContext);
if (isOneColumn) {
st::stickersReorderIcon.paint(
p,
width()
- _reorderState.section->oneColumnRightPadding() * 2,
(_reorderState.item->minHeight()
- st::stickersReorderIcon.height()) / 2,
outerWidth);
}
p.translate(-_reorderState.currentPos);
}
@@ -1769,7 +1790,11 @@ void ListWidget::mouseActionUpdate(const QPoint &globalPosition) {
auto local = mapFromGlobal(_mousePosition);
auto point = clampMousePosition(local);
auto [layout, geometry, inside] = findItemByPoint(point);
auto [foundItem, section] = findItemByPointWithSection(point);
auto [layout, geometry, inside] = std::tie(
foundItem.layout,
foundItem.geometry,
foundItem.exact);
auto state = MouseState{
layout->getItem(),
geometry.size(),
@@ -1783,6 +1808,19 @@ void ListWidget::mouseActionUpdate(const QPoint &globalPosition) {
}
_overState = state;
const auto inDragArea = canReorder()
&& section
&& section->isOneColumn()
&& point.y() >= geometry.y()
&& point.y() < geometry.bottom()
&& ((point.x() - geometry.x())
>= (geometry.width()
- section->oneColumnRightPadding()
- st::stickersReorderSkip));
if (_inDragArea != inDragArea) {
_inDragArea = inDragArea;
}
TextState dragState;
ClickHandlerHost *lnkhost = nullptr;
auto inTextSelection = _overState.inside
@@ -1870,7 +1908,9 @@ void ListWidget::mouseActionUpdate(const QPoint &globalPosition) {
}
style::cursor ListWidget::computeMouseCursor() const {
if (ClickHandler::getPressed() || ClickHandler::getActive()) {
if (_inDragArea && canReorder()) {
return style::cur_sizeall;
} else if (ClickHandler::getPressed() || ClickHandler::getActive()) {
return style::cur_pointer;
} else if (!hasSelectedItems()
&& (_mouseCursorState == CursorState::Text)) {
@@ -1955,6 +1995,13 @@ void ListWidget::mouseActionStart(
false);
}
if (_inDragArea && canReorder() && !hasSelected()) {
startReorder(globalPosition);
if (_mouseAction == MouseAction::PrepareReorder) {
return;
}
}
if (ClickHandler::getPressed() && !hasSelected()) {
_mouseAction = MouseAction::PrepareDrag;
if (canReorder()) {
@@ -2297,16 +2344,23 @@ void ListWidget::startReorder(const QPoint &globalPos) {
return;
}
const auto mapped = mapFromGlobal(globalPos);
const auto index = itemIndexFromPoint(mapped);
const auto foundWithSection = findItemByPointWithSection(mapped);
if (!foundWithSection.section) {
return;
}
if (foundWithSection.section->isOneColumn()
? !_inDragArea
: !foundWithSection.item.exact) {
return;
}
const auto index = itemIndexFromPoint(mapped
- QPoint(foundWithSection.section->oneColumnRightPadding(), 0));
if (index < 0) {
return;
}
const auto found = findItemByPoint(mapped);
if (!found.exact) {
return;
}
if (_reorderDescriptor.filter) {
const auto item = found.layout->getItem();
const auto item = foundWithSection.item.layout->getItem();
if (!_reorderDescriptor.filter(item)) {
return;
}
@@ -2315,8 +2369,10 @@ void ListWidget::startReorder(const QPoint &globalPos) {
_reorderState.index = index;
_reorderState.targetIndex = index;
_reorderState.startPos = globalPos;
_reorderState.dragPoint = mapped - found.geometry.topLeft();
_reorderState.item = found.layout;
_reorderState.dragPoint = mapped
- foundWithSection.item.geometry.topLeft();
_reorderState.item = foundWithSection.item.layout;
_reorderState.section = foundWithSection.section;
_mouseAction = MouseAction::PrepareReorder;
}
@@ -132,6 +132,7 @@ private:
QPoint dragPoint;
QPoint currentPos;
BaseLayout *item = nullptr;
const Section *section = nullptr;
};
struct ShiftAnimation {
Ui::Animations::Simple xAnimation;
@@ -373,6 +374,7 @@ private:
int _activeShiftAnimations = 0;
Ui::Animations::Simple _returnAnimation;
ReorderDescriptor _reorderDescriptor;
bool _inDragArea = false;
};