Files
ts-qt/modern-qt/layout/linear.hh
2025-10-20 00:32:01 +08:00

109 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "modern-qt/utility/trait/widget.hh"
#include "modern-qt/utility/wrapper/common.hh"
#include "modern-qt/utility/wrapper/layout.hh"
#include "modern-qt/utility/wrapper/property.hh"
#include <qboxlayout.h>
namespace creeper::linear::pro {
using Token = common::Token<QBoxLayout>;
struct SpacingItem : Token {
int size;
explicit SpacingItem(int p) { size = p; }
void apply(QBoxLayout& self) const { self.addSpacing(size); }
};
struct Stretch : Token {
int stretch;
explicit Stretch(int p) { stretch = p; }
void apply(QBoxLayout& self) const { self.addStretch(stretch); }
};
struct SpacerItem : Token {
QSpacerItem* spacer_item;
explicit SpacerItem(QSpacerItem* p) { spacer_item = p; }
void apply(QBoxLayout& self) const { self.addSpacerItem(spacer_item); }
};
/// @brief
/// 布局项包装器,用于声明式地将 Widget 或 Layout 添加到布局中
///
/// @tparam T
/// 被包装的组件类型,需满足可转换为 QWidget* 或 QLayout*,不需
/// 要显式指定,由构造参数推倒
///
/// @note
/// Item 提供统一的接口用于在布局中插入控件或子布局,
/// 支持多种构造方式,包括直接传入指针或通过参数构造新对象。
/// 通过 LayoutMethod 可指定拉伸因子和对齐方式,
/// 在布局应用时自动选择 addWidget 或 addLayout
/// 实现非侵入式的布局声明式封装。
///
/// 示例用途:
/// linear::pro::Item<Widget> {
/// { 0, Qt::AlignHCenter } // stretch, and alignment, optional
/// ...
/// };
///
template <item_trait T>
struct Item : Token {
struct LayoutMethod {
int stretch = 0;
Qt::Alignment align = {};
} method;
T* item_pointer = nullptr;
explicit Item(const LayoutMethod& method, T* pointer) noexcept
: item_pointer { pointer }
, method { method } { }
explicit Item(T* pointer) noexcept
: item_pointer { pointer } { }
explicit Item(const LayoutMethod& method, auto&&... args) noexcept
requires std::constructible_from<T, decltype(args)...>
: item_pointer { new T { std::forward<decltype(args)>(args)... } }
, method(method) { }
explicit Item(auto&&... args) noexcept
requires std::constructible_from<T, decltype(args)...>
: item_pointer { new T { std::forward<decltype(args)>(args)... } } { }
void apply(linear_trait auto& layout) const {
if constexpr (widget_trait<T>) layout.addWidget(item_pointer, method.stretch, method.align);
if constexpr (layout_trait<T>) layout.addLayout(item_pointer, method.stretch);
}
};
template <typename T>
concept trait = std::derived_from<T, Token>;
CREEPER_DEFINE_CHECKER(trait);
using namespace layout::pro;
}
namespace creeper {
template <class T>
using BoxLayout = Declarative<T, CheckerOr<linear::pro::checker, layout::pro::checker>>;
using Row = BoxLayout<QHBoxLayout>;
using Col = BoxLayout<QVBoxLayout>;
namespace row = linear;
namespace col = linear;
namespace internal {
inline auto use_the_namespace_alias_to_eliminate_warnings() {
std::ignore = row::pro::Token {};
std::ignore = col::pro::Token {};
}
}
}