| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /*
- 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
|