Slightly simplified ChatHelpers::GifsListWidget.

This commit is contained in:
23rd 2021-07-22 01:14:16 +03:00 committed by John Preston
parent 85ce179f58
commit 9699aeb1cd
4 changed files with 106 additions and 91 deletions

View file

@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "layout/layout_utils.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -330,8 +331,10 @@ void GifsListWidget::paintInlineItems(Painter &p, QRect clip) {
p.drawText(QRect(0, 0, width(), (height() / 3) * 2 + st::normalFont->height), text, style::al_center); p.drawText(QRect(0, 0, width(), (height() / 3) * 2 + st::normalFont->height), text, style::al_center);
return; return;
} }
auto gifPaused = controller()->isGifPausedAtLeastFor(Window::GifPauseReason::SavedGifs); const auto gifPaused = controller()->isGifPausedAtLeastFor(
InlineBots::Layout::PaintContext context(crl::now(), false, gifPaused, false); Window::GifPauseReason::SavedGifs);
using namespace InlineBots::Layout;
PaintContext context(crl::now(), false, gifPaused, false);
_mosaic.paint( _mosaic.paint(
p, p,
@ -359,11 +362,9 @@ void GifsListWidget::fillContextMenu(
if (_selected < 0 || _pressed >= 0) { if (_selected < 0 || _pressed >= 0) {
return; return;
} }
const auto row = _selected / MatrixRowShift;
const auto column = _selected % MatrixRowShift;
const auto send = [=](Api::SendOptions options) { const auto send = [=, selected = _selected](Api::SendOptions options) {
selectInlineResult(row, column, options, true); selectInlineResult(selected, options, true);
}; };
SendMenu::FillSendMenu( SendMenu::FillSendMenu(
menu, menu,
@ -371,7 +372,7 @@ void GifsListWidget::fillContextMenu(
SendMenu::DefaultSilentCallback(send), SendMenu::DefaultSilentCallback(send),
SendMenu::DefaultScheduleCallback(this, type, send)); SendMenu::DefaultScheduleCallback(this, type, send));
if (const auto item = _mosaic.maybeItemAt(row, column)) { if (const auto item = _mosaic.maybeItemAt(_selected)) {
const auto document = item->getDocument() const auto document = item->getDocument()
? item->getDocument() // Saved GIF. ? item->getDocument() // Saved GIF.
: item->getPreviewDocument(); // Searched GIF. : item->getPreviewDocument(); // Searched GIF.
@ -403,23 +404,17 @@ void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) {
} }
if (dynamic_cast<InlineBots::Layout::SendClickHandler*>(activated.get())) { if (dynamic_cast<InlineBots::Layout::SendClickHandler*>(activated.get())) {
int row = _selected / MatrixRowShift, column = _selected % MatrixRowShift; selectInlineResult(_selected, {});
selectInlineResult(row, column);
} else { } else {
ActivateClickHandler(window(), activated, e->button()); ActivateClickHandler(window(), activated, e->button());
} }
} }
void GifsListWidget::selectInlineResult(int row, int column) {
selectInlineResult(row, column, Api::SendOptions());
}
void GifsListWidget::selectInlineResult( void GifsListWidget::selectInlineResult(
int row, int index,
int column,
Api::SendOptions options, Api::SendOptions options,
bool forceSend) { bool forceSend) {
const auto item = _mosaic.maybeItemAt(row, column); const auto item = _mosaic.maybeItemAt(index);
if (!item) { if (!item) {
return; return;
} }
@ -481,8 +476,7 @@ void GifsListWidget::enterFromChildEvent(QEvent *e, QWidget *child) {
void GifsListWidget::clearSelection() { void GifsListWidget::clearSelection() {
if (_selected >= 0) { if (_selected >= 0) {
int srow = _selected / MatrixRowShift, scol = _selected % MatrixRowShift; ClickHandler::clearActive(_mosaic.itemAt(_selected));
ClickHandler::clearActive(_mosaic.itemAt(srow, scol));
setCursor(style::cur_default); setCursor(style::cur_default);
} }
_selected = _pressed = -1; _selected = _pressed = -1;
@ -685,8 +679,7 @@ void GifsListWidget::inlineItemLayoutChanged(const InlineBots::Layout::ItemBase
return; return;
} }
int row = _selected / MatrixRowShift, col = _selected % MatrixRowShift; if (const auto item = _mosaic.maybeItemAt(_selected)) {
if (const auto item = _mosaic.maybeItemAt(row, col)) {
if (layout == item) { if (layout == item) {
updateSelected(); updateSelected();
} }
@ -708,16 +701,14 @@ bool GifsListWidget::inlineItemVisible(const InlineBots::Layout::ItemBase *layou
return false; return false;
} }
auto row = position / MatrixRowShift; const auto &[row, column] = Layout::IndexToPosition(position);
auto col = position % MatrixRowShift;
auto top = 0; auto top = 0;
for (auto i = 0; i != row; ++i) { for (auto i = 0; i != row; ++i) {
top += _mosaic.rowHeightAt(i); top += _mosaic.rowHeightAt(i);
} }
return (top < getVisibleBottom()) return (top < getVisibleBottom())
&& (top + _mosaic.itemAt(row, col)->height() > getVisibleTop()); && (top + _mosaic.itemAt(row, column)->height() > getVisibleTop());
} }
Data::FileOrigin GifsListWidget::inlineItemFileOrigin() { Data::FileOrigin GifsListWidget::inlineItemFileOrigin() {
@ -860,78 +851,37 @@ void GifsListWidget::updateSelected() {
return; return;
} }
auto p = mapFromGlobal(_lastMousePos); const auto p = mapFromGlobal(_lastMousePos);
int sx = (rtl() ? width() - p.x() : p.x()) - (st::inlineResultsLeft - st::roundRadiusSmall); const auto sx = (rtl() ? width() - p.x() : p.x())
int sy = p.y() - st::stickerPanPadding; - (st::inlineResultsLeft - st::roundRadiusSmall);
int row = -1, col = -1, sel = -1; const auto sy = p.y() - st::stickerPanPadding;
ClickHandlerPtr lnk; const auto &[link, item, selected] = _mosaic.findByPoint({ sx, sy });
ClickHandlerHost *lnkhost = nullptr;
if (sy >= 0) { if (_selected != selected) {
row = 0; if (const auto s = _mosaic.maybeItemAt(_selected)) {
for (int rows = _mosaic.rowsCount(); row < rows; ++row) { s->update();
const auto rowHeight = _mosaic.rowHeightAt(row);
if (sy < rowHeight) {
break;
}
sy -= rowHeight;
} }
} _selected = selected;
if (sx >= 0 && row >= 0 && row < _mosaic.rowsCount()) { if (item) {
const auto columnsCount = _mosaic.columnsCountAt(row); item->update();
col = 0;
for (int cols = columnsCount; col < cols; ++col) {
const auto item = _mosaic.itemAt(row, col);
int width = item->width();
if (sx < width) {
break;
}
sx -= width;
if (item->hasRightSkip()) {
sx -= st::inlineResultsSkip;
}
}
if (col < columnsCount) {
const auto item = _mosaic.itemAt(row, col);
sel = row * MatrixRowShift + col;
auto result = item->getState(
QPoint(sx, sy),
HistoryView::StateRequest());
lnk = result.link;
lnkhost = item;
} else {
row = col = -1;
}
} else {
row = col = -1;
}
int srow = (_selected >= 0) ? (_selected / MatrixRowShift) : -1;
int scol = (_selected >= 0) ? (_selected % MatrixRowShift) : -1;
if (_selected != sel) {
if (srow >= 0 && scol >= 0) {
_mosaic.itemAt(srow, scol)->update();
}
_selected = sel;
if (row >= 0 && col >= 0) {
_mosaic.itemAt(row, col)->update();
} }
if (_previewShown && _selected >= 0 && _pressed != _selected) { if (_previewShown && _selected >= 0 && _pressed != _selected) {
_pressed = _selected; _pressed = _selected;
if (row >= 0 && col >= 0) { if (item) {
const auto layout = _mosaic.itemAt(row, col); if (const auto preview = item->getPreviewDocument()) {
if (const auto previewDocument = layout->getPreviewDocument()) {
controller()->widget()->showMediaPreview( controller()->widget()->showMediaPreview(
Data::FileOriginSavedGifs(), Data::FileOriginSavedGifs(),
previewDocument); preview);
} else if (const auto previewPhoto = layout->getPreviewPhoto()) { } else if (const auto preview = item->getPreviewPhoto()) {
controller()->widget()->showMediaPreview( controller()->widget()->showMediaPreview(
Data::FileOrigin(), Data::FileOrigin(),
previewPhoto); preview);
} }
} }
} }
} }
if (ClickHandler::setActive(lnk, lnkhost)) { if (ClickHandler::setActive(link, item)) {
setCursor(lnk ? style::cur_pointer : style::cur_default); setCursor(link ? style::cur_pointer : style::cur_default);
} }
} }
@ -939,8 +889,7 @@ void GifsListWidget::showPreview() {
if (_pressed < 0) { if (_pressed < 0) {
return; return;
} }
int row = _pressed / MatrixRowShift, col = _pressed % MatrixRowShift; if (const auto layout = _mosaic.maybeItemAt(_pressed)) {
if (const auto layout = _mosaic.maybeItemAt(row, col)) {
if (const auto previewDocument = layout->getPreviewDocument()) { if (const auto previewDocument = layout->getPreviewDocument()) {
_previewShown = controller()->widget()->showMediaPreview( _previewShown = controller()->widget()->showMediaPreview(
Data::FileOriginSavedGifs(), Data::FileOriginSavedGifs(),

View file

@ -160,10 +160,8 @@ private:
void deleteUnusedInlineLayouts(); void deleteUnusedInlineLayouts();
int validateExistingInlineRows(const InlineResults &results); int validateExistingInlineRows(const InlineResults &results);
void selectInlineResult(int row, int column);
void selectInlineResult( void selectInlineResult(
int row, int index,
int column,
Api::SendOptions options, Api::SendOptions options,
bool forceSend = false); bool forceSend = false);

View file

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "inline_bots/inline_results_mosaic_layout.h" #include "inline_bots/inline_results_mosaic_layout.h"
#include "history/view/history_view_cursor_state.h"
#include "layout/layout_utils.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
namespace InlineBots::Layout { namespace InlineBots::Layout {
@ -45,6 +47,11 @@ not_null<ItemBase*> MosaicLayout::itemAt(int row, int column) const {
return _rows[row].items[column]; return _rows[row].items[column];
} }
not_null<ItemBase*> MosaicLayout::itemAt(int index) const {
const auto &[row, column] = ::Layout::IndexToPosition(index);
return itemAt(row, column);
}
ItemBase *MosaicLayout::maybeItemAt(int row, int column) const { ItemBase *MosaicLayout::maybeItemAt(int row, int column) const {
if ((row >= 0) if ((row >= 0)
&& (row < _rows.size()) && (row < _rows.size())
@ -55,6 +62,11 @@ ItemBase *MosaicLayout::maybeItemAt(int row, int column) const {
return nullptr; return nullptr;
} }
ItemBase *MosaicLayout::maybeItemAt(int index) const {
const auto &[row, column] = ::Layout::IndexToPosition(index);
return maybeItemAt(row, column);
}
void MosaicLayout::addItems(const std::vector<ItemBase*> &items) { void MosaicLayout::addItems(const std::vector<ItemBase*> &items) {
_rows.reserve(items.size()); _rows.reserve(items.size());
auto row = Row(); auto row = Row();
@ -72,9 +84,10 @@ void MosaicLayout::addItem(
int &sumWidth) { int &sumWidth) {
item->preload(); item->preload();
item->setPosition(_rows.size() * MatrixRowShift + row.items.size()); using namespace ::Layout;
item->setPosition(PositionToIndex(_rows.size(), row.items.size()));
if (rowFinalize(row, sumWidth, item->isFullLine())) { if (rowFinalize(row, sumWidth, item->isFullLine())) {
item->setPosition(_rows.size() * MatrixRowShift); item->setPosition(PositionToIndex(_rows.size(), 0));
} }
sumWidth += item->maxWidth(); sumWidth += item->maxWidth();
@ -275,4 +288,50 @@ int MosaicLayout::rowHeightAt(int row) {
return _rows[row].height; return _rows[row].height;
} }
MosaicLayout::FoundItem MosaicLayout::findByPoint(const QPoint &globalPoint) {
auto sx = globalPoint.x();
auto sy = globalPoint.y();
auto row = -1;
auto col = -1;
auto sel = -1;
ClickHandlerPtr link;
ItemBase *item = nullptr;
if (sy >= 0) {
row = 0;
for (auto rows = rowsCount(); row < rows; ++row) {
const auto rowHeight = _rows[row].height;
if (sy < rowHeight) {
break;
}
sy -= rowHeight;
}
}
if (sx >= 0 && row >= 0 && row < rowsCount()) {
const auto columnsCount = _rows[row].items.size();
col = 0;
for (int cols = columnsCount; col < cols; ++col) {
const auto item = itemAt(row, col);
const auto width = item->width();
if (sx < width) {
break;
}
sx -= width;
if (item->hasRightSkip()) {
sx -= st::inlineResultsSkip;
}
}
if (col < columnsCount) {
item = itemAt(row, col);
sel = ::Layout::PositionToIndex(row, + col);
const auto result = item->getState(QPoint(sx, sy), {});
link = result.link;
} else {
row = col = -1;
}
} else {
row = col = -1;
}
return { link, item, sel };
}
} // namespace InlineBots::Layout } // namespace InlineBots::Layout

View file

@ -19,11 +19,18 @@ using Results = std::vector<std::unique_ptr<Result>>;
class MosaicLayout final { class MosaicLayout final {
public: public:
struct FoundItem {
ClickHandlerPtr link;
ItemBase *item = nullptr;
int index = -1;
};
MosaicLayout() = default; MosaicLayout() = default;
[[nodiscard]] int rowHeightAt(int row); [[nodiscard]] int rowHeightAt(int row);
[[nodiscard]] int countDesiredHeight(int newWidth); [[nodiscard]] int countDesiredHeight(int newWidth);
[[nodiscard]] FoundItem findByPoint(const QPoint &globalPoint);
void addItems(const std::vector<ItemBase*> &items); void addItems(const std::vector<ItemBase*> &items);
void setFullWidth(int w); void setFullWidth(int w);
@ -33,7 +40,9 @@ public:
[[nodiscard]] int columnsCountAt(int row) const; [[nodiscard]] int columnsCountAt(int row) const;
[[nodiscard]] not_null<ItemBase*> itemAt(int row, int column) const; [[nodiscard]] not_null<ItemBase*> itemAt(int row, int column) const;
[[nodiscard]] not_null<ItemBase*> itemAt(int index) const;
[[nodiscard]] ItemBase *maybeItemAt(int row, int column) const; [[nodiscard]] ItemBase *maybeItemAt(int row, int column) const;
[[nodiscard]] ItemBase *maybeItemAt(int index) const;
void clearRows(bool resultsDeleted); void clearRows(bool resultsDeleted);
[[nodiscard]]int validateExistingRows(const Results &results); [[nodiscard]]int validateExistingRows(const Results &results);