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

View file

@ -160,10 +160,8 @@ private:
void deleteUnusedInlineLayouts();
int validateExistingInlineRows(const InlineResults &results);
void selectInlineResult(int row, int column);
void selectInlineResult(
int row,
int column,
int index,
Api::SendOptions options,
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 "history/view/history_view_cursor_state.h"
#include "layout/layout_utils.h"
#include "styles/style_chat_helpers.h"
namespace InlineBots::Layout {
@ -45,6 +47,11 @@ not_null<ItemBase*> MosaicLayout::itemAt(int row, int column) const {
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 {
if ((row >= 0)
&& (row < _rows.size())
@ -55,6 +62,11 @@ ItemBase *MosaicLayout::maybeItemAt(int row, int column) const {
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) {
_rows.reserve(items.size());
auto row = Row();
@ -72,9 +84,10 @@ void MosaicLayout::addItem(
int &sumWidth) {
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())) {
item->setPosition(_rows.size() * MatrixRowShift);
item->setPosition(PositionToIndex(_rows.size(), 0));
}
sumWidth += item->maxWidth();
@ -275,4 +288,50 @@ int MosaicLayout::rowHeightAt(int row) {
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

View file

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