init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
156
Telegram/SourceFiles/layout/layout_mosaic.h
Normal file
156
Telegram/SourceFiles/layout/layout_mosaic.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "layout/abstract_layout_item.h"
|
||||
#include "layout/layout_position.h"
|
||||
|
||||
namespace Mosaic::Layout {
|
||||
|
||||
struct FoundItem {
|
||||
int index = -1;
|
||||
bool exact = false;
|
||||
QPoint relative;
|
||||
};
|
||||
|
||||
class AbstractMosaicLayout {
|
||||
public:
|
||||
AbstractMosaicLayout(int bigWidth);
|
||||
|
||||
[[nodiscard]] int rowHeightAt(int row) const;
|
||||
[[nodiscard]] int countDesiredHeight(int newWidth);
|
||||
|
||||
[[nodiscard]] FoundItem findByPoint(const QPoint &globalPoint) const;
|
||||
|
||||
[[nodiscard]] QRect findRect(int index) const;
|
||||
|
||||
void setRightSkip(int rightSkip);
|
||||
void setPadding(QMargins padding);
|
||||
void setFullWidth(int w);
|
||||
|
||||
[[nodiscard]] bool empty() const;
|
||||
[[nodiscard]] int rowsCount() const;
|
||||
|
||||
void clearRows(bool resultsDeleted);
|
||||
|
||||
protected:
|
||||
void addItems(gsl::span<const not_null<AbstractLayoutItem*>> items);
|
||||
|
||||
[[nodiscard]] not_null<AbstractLayoutItem*> itemAt(int row, int column) const;
|
||||
[[nodiscard]] not_null<AbstractLayoutItem*> itemAt(int index) const;
|
||||
|
||||
[[nodiscard]] AbstractLayoutItem *maybeItemAt(int row, int column) const;
|
||||
[[nodiscard]] AbstractLayoutItem *maybeItemAt(int index) const;
|
||||
|
||||
void forEach(Fn<void(not_null<const AbstractLayoutItem*>)> callback);
|
||||
|
||||
void paint(
|
||||
Fn<void(not_null<AbstractLayoutItem*>, QPoint)> paintItem,
|
||||
const QRect &clip) const;
|
||||
int validateExistingRows(
|
||||
Fn<bool(not_null<const AbstractLayoutItem*>, int)> checkItem,
|
||||
int count);
|
||||
|
||||
private:
|
||||
static constexpr auto kInlineItemsMaxPerRow = 5;
|
||||
struct Row {
|
||||
int maxWidth = 0;
|
||||
int height = 0;
|
||||
std::vector<AbstractLayoutItem*> items;
|
||||
};
|
||||
|
||||
void addItem(not_null<AbstractLayoutItem*> item, Row &row, int &sumWidth);
|
||||
bool rowFinalize(Row &row, int &sumWidth, bool force);
|
||||
void layoutRow(Row &row, int fullWidth);
|
||||
|
||||
int _bigWidth;
|
||||
int _width = 0;
|
||||
int _rightSkip = 0;
|
||||
QMargins _padding;
|
||||
std::vector<Row> _rows;
|
||||
|
||||
};
|
||||
|
||||
template <
|
||||
typename ItemBase,
|
||||
typename = std::enable_if_t<
|
||||
std::is_base_of_v<AbstractLayoutItem, ItemBase>>>
|
||||
class MosaicLayout final : public AbstractMosaicLayout {
|
||||
using Parent = AbstractMosaicLayout;
|
||||
|
||||
public:
|
||||
using Parent::Parent;
|
||||
|
||||
void addItems(const std::vector<not_null<ItemBase*>> &items) {
|
||||
Parent::addItems({
|
||||
reinterpret_cast<const not_null<AbstractLayoutItem*>*>(
|
||||
items.data()),
|
||||
items.size() });
|
||||
}
|
||||
|
||||
[[nodiscard]] not_null<ItemBase*> itemAt(int row, int column) const {
|
||||
return Downcast(Parent::itemAt(row, column));
|
||||
}
|
||||
[[nodiscard]] not_null<ItemBase*> itemAt(int index) const {
|
||||
return Downcast(Parent::itemAt(index));
|
||||
}
|
||||
[[nodiscard]] ItemBase *maybeItemAt(int row, int column) const {
|
||||
return Downcast(Parent::maybeItemAt(row, column));
|
||||
}
|
||||
[[nodiscard]] ItemBase *maybeItemAt(int index) const {
|
||||
return Downcast(Parent::maybeItemAt(index));
|
||||
}
|
||||
|
||||
void forEach(Fn<void(not_null<const ItemBase*>)> callback) {
|
||||
Parent::forEach([&](
|
||||
not_null<const AbstractLayoutItem*> item) {
|
||||
callback(Downcast(item));
|
||||
});
|
||||
}
|
||||
|
||||
void paint(
|
||||
Fn<void(not_null<ItemBase*>, QPoint)> paintItem,
|
||||
const QRect &clip) const {
|
||||
Parent::paint([&](
|
||||
not_null<AbstractLayoutItem*> item,
|
||||
QPoint point) {
|
||||
paintItem(Downcast(item), point);
|
||||
}, clip);
|
||||
}
|
||||
|
||||
int validateExistingRows(
|
||||
Fn<bool(not_null<const ItemBase*>, int)> checkItem,
|
||||
int count) {
|
||||
return Parent::validateExistingRows([&](
|
||||
not_null<const AbstractLayoutItem*> item,
|
||||
int until) {
|
||||
return checkItem(Downcast(item), until);
|
||||
}, count);
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] static not_null<ItemBase*> Downcast(
|
||||
not_null<AbstractLayoutItem*> item) {
|
||||
return static_cast<ItemBase*>(item.get());
|
||||
}
|
||||
[[nodiscard]] static ItemBase *Downcast(
|
||||
AbstractLayoutItem *item) {
|
||||
return static_cast<ItemBase*>(item);
|
||||
}
|
||||
[[nodiscard]] static not_null<const ItemBase*> Downcast(
|
||||
not_null<const AbstractLayoutItem*> item) {
|
||||
return static_cast<const ItemBase*>(item.get());
|
||||
}
|
||||
[[nodiscard]] static const ItemBase *Downcast(
|
||||
const AbstractLayoutItem *item) {
|
||||
return static_cast<const ItemBase*>(item);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace Mosaic::Layout
|
||||
Reference in New Issue
Block a user