#pragma once #include "modern-qt/utility/wrapper/common.hh" #include "modern-qt/utility/wrapper/property.hh" #include #include namespace creeper::widget::pro { using Token = common::Token; using MinimumWidth = SetterProp; using MaximumWidth = SetterProp; using FixedWidth = SetterProp; using MinimumHeight = SetterProp; using MaximumHeight = SetterProp; using FixedHeight = SetterProp; using LayoutDirection = SetterProp; using BackgroundRole = SetterProp; using ForegroundRole = SetterProp; using ClearMask = SetterProp; using GraphicsEffect = SetterProp; struct WindowFlag : Token { Qt::WindowType type; bool on; explicit WindowFlag(Qt::WindowType type, bool on = true) : type { type } , on { on } { } void apply(QWidget& widget) const { widget.setWindowFlag(type, on); } }; using WindowFlags = SetterProp; using WindowOpacity = SetterProp; using Parent = SetterProp; using Child = SetterPropsetParent(&self); }>; using MinimumSize = DerivedProp; using MaximumSize = DerivedProp; using SizeIncrement = DerivedProp; using BaseSize = DerivedProp; using FixedSize = DerivedProp; using Font = DerivedProp; using BitmapMask = DerivedProp; using RegionMask = DerivedProp; using WindowIcon = DerivedProp; using WindowIconText = DerivedProp; using WindowRole = DerivedProp; using WindowFilePath = DerivedProp; using ToolTip = DerivedProp; struct MoveCenter : Token { auto apply(QWidget& self) const noexcept -> void { const auto screen = self.screen(); const auto screen_geometry = screen->availableGeometry(); const auto screen_width = screen_geometry.width(); const auto screen_height = screen_geometry.height(); const auto widget_geometry = self.geometry(); const auto widget_width = widget_geometry.width(); const auto widget_height = widget_geometry.height(); const auto x = (screen_width - widget_width) / 2; const auto y = (screen_height - widget_height) / 2; self.move(x, y); } }; struct SizePolicy : Token { QSizePolicy::Policy v, h; explicit SizePolicy(QSizePolicy::Policy policy) : v { policy } , h { policy } { } explicit SizePolicy(QSizePolicy::Policy v, QSizePolicy::Policy h) : v { v } , h { h } { } void apply(QWidget& self) const { self.setSizePolicy(h, v); } }; /// @note 该属性本质是转发构造,有 new 的行为 template struct Layout : Token { T* layout_; explicit Layout(T* pointer) noexcept requires std::convertible_to : layout_ { pointer } { } explicit Layout(auto&&... args) requires std::constructible_from : layout_ { new T { std::forward(args)... } } { } void apply(QWidget& widget) const { widget.setLayout(layout_); } }; /// @brief 绑定裸指针,为了避免赋值语句 /// /// 一般情况下需要绑定指针: /// /// 假设下面是一个 layout 的内部 /// clang-format 会在下面的赋值符号后换行 /// @code /// auto widget = (Widget*)nullptr; /// ...... /// { widget = /// new Widget { /// ...... /// } }, /// ...... /// @endcode /// /// 利用赋值语句的返回特性将该组件返回给 layout,同时完成赋值, /// 但这样会多一层缩进,为保证构造配置的简洁和同一,可以使用该包装: /// /// @code /// ...... /// { new Widget { /// pro::Bind { widget }, /// } }, /// ...... /// @endcode /// /// @tparam Final 需要绑定的组件类型(自动推导,无需显式指定) /// /// @date 2025-06-19 template struct Bind : Token { Final*& widget; explicit Bind(Final*& widget) noexcept requires std::is_pointer::value : widget(widget) { } void apply(Final& self) const noexcept { widget = &self; } }; // 传入一个方法用来辅助构造,在没有想要的接口时用这个吧 template struct Apply : Token { Lambda lambda; explicit Apply(Lambda lambda) noexcept : lambda { lambda } { } auto apply(auto& self) const noexcept -> void { if constexpr (std::invocable) lambda(); if constexpr (std::invocable) lambda(self); } }; template concept trait = std::derived_from; CREEPER_DEFINE_CHECKER(trait); }