235 lines
7.6 KiB
C++
235 lines
7.6 KiB
C++
#pragma once
|
||
|
||
#include "property.hh"
|
||
|
||
#include <qbitmap.h>
|
||
#include <qvector.h>
|
||
#include <qdebug.h>
|
||
#include <qicon.h>
|
||
#include <qwidget.h>
|
||
|
||
namespace creeper::common {
|
||
template <typename Instance>
|
||
struct Token {
|
||
void apply(auto& self) const {
|
||
const auto self_name = typeid(self).name();
|
||
const auto prop_name = typeid(this).name();
|
||
qDebug() << "Unimplemented" << prop_name << "is called by" << self_name;
|
||
}
|
||
};
|
||
|
||
namespace pro {
|
||
|
||
// 设置组建透明度
|
||
template <class Token>
|
||
using Opacity = SetterProp<Token, double, [](auto& self, double v) { self.set_opacity(v); }>;
|
||
|
||
// 设置圆角(NXNY)
|
||
template <class Token>
|
||
using RadiusNxNy =
|
||
SetterProp<Token, double, [](auto& self, double v) { self.set_radius_nx_ny(v); }>;
|
||
|
||
// 设置圆角(PXPY)
|
||
template <class Token>
|
||
using RadiusPxPy =
|
||
SetterProp<Token, double, [](auto& self, double v) { self.set_radius_px_py(v); }>;
|
||
|
||
// 设置圆角(NXPY)
|
||
template <class Token>
|
||
using RadiusNxPy =
|
||
SetterProp<Token, double, [](auto& self, double v) { self.set_radius_nx_py(v); }>;
|
||
|
||
// 设置圆角(PXNY)
|
||
template <class Token>
|
||
using RadiusPxNy =
|
||
SetterProp<Token, double, [](auto& self, double v) { self.set_radius_px_ny(v); }>;
|
||
|
||
// 设置圆角(X方向)
|
||
template <class Token>
|
||
using RadiusX = SetterProp<Token, double, [](auto& self, double v) { self.set_radius_x(v); }>;
|
||
|
||
// 设置圆角(Y方向)
|
||
template <class Token>
|
||
using RadiusY = SetterProp<Token, double, [](auto& self, double v) { self.set_radius_y(v); }>;
|
||
|
||
// 设置通用圆角
|
||
template <class Token>
|
||
using Radius = SetterProp<Token, double, [](auto& self, double v) { self.set_radius(v); }>;
|
||
|
||
// 通用边界宽度
|
||
template <class Token>
|
||
using BorderWidth =
|
||
SetterProp<Token, double, [](auto& self, double v) { self.set_border_width(v); }>;
|
||
|
||
// 通用边界颜色
|
||
template <class Token>
|
||
using BorderColor =
|
||
SetterProp<Token, QColor, [](auto& self, const QColor& v) { self.set_border_color(v); }>;
|
||
|
||
// 通用文字颜色
|
||
template <class Token>
|
||
using TextColor =
|
||
SetterProp<Token, QColor, [](auto& self, const QColor& v) { self.set_text_color(v); }>;
|
||
|
||
// 通用背景颜色
|
||
template <class Token>
|
||
using Background =
|
||
SetterProp<Token, QColor, [](auto& self, const QColor& v) { self.set_background(v); }>;
|
||
|
||
// 通用水波纹颜色
|
||
template <class Token>
|
||
using WaterColor =
|
||
SetterProp<Token, QColor, [](auto& self, const QColor& v) { self.set_water_color(v); }>;
|
||
|
||
// 通用禁止属性
|
||
template <class Token>
|
||
using Disabled = SetterProp<Token, bool, [](auto& self, bool v) { self.set_disabled(v); }>;
|
||
|
||
// 通用 Checked 属性
|
||
template <class Token>
|
||
using Checked = SetterProp<Token, bool, [](auto& self, bool v) { self.set_checked(v); }>;
|
||
|
||
// 通用文本属性
|
||
template <class Token, auto setter>
|
||
struct String : public QString, Token {
|
||
using QString::QString;
|
||
|
||
explicit String(const QString& text) noexcept
|
||
: QString { text } { }
|
||
explicit String(const std::string& text) noexcept
|
||
: QString { QString::fromStdString(text) } { }
|
||
|
||
auto operator=(const QString& text) noexcept {
|
||
QString::operator=(text);
|
||
return *this;
|
||
}
|
||
auto operator=(QString&& text) noexcept {
|
||
QString::operator=(std::move(text));
|
||
return *this;
|
||
}
|
||
|
||
void apply(auto& self) const
|
||
requires requires { setter(self, *this); }
|
||
{
|
||
setter(self, *this);
|
||
}
|
||
};
|
||
|
||
template <class Token, typename T, auto setter>
|
||
struct Vector : public QVector<T>, Token {
|
||
using QVector<T>::QVector;
|
||
|
||
explicit Vector(const QVector<T>& vec) noexcept
|
||
: QVector<T> { vec } { }
|
||
explicit Vector(const std::vector<T>& vec) noexcept
|
||
: QVector<T> { vec } { }
|
||
|
||
void apply(auto& self) const
|
||
requires requires {setter(self, *this); }
|
||
{
|
||
setter(self, *this);
|
||
}
|
||
};
|
||
|
||
template <class Token, typename T, std::size_t N, auto setter>
|
||
struct Array : public std::array<T, N>, Token {
|
||
using std::array<T, N>::array;
|
||
explicit Array(const std::array<T, N>& arr) noexcept
|
||
: std::array<T, N> { arr } { }
|
||
|
||
template <typename... Args>
|
||
requires (sizeof...(Args) == N)
|
||
explicit Array(Args&&... args) noexcept
|
||
: std::array<T, N> {
|
||
std::forward<Args>(args)...} {}
|
||
|
||
void apply(auto& self) const
|
||
requires requires {setter(self, *this);}
|
||
{
|
||
setter(self, *this);
|
||
}
|
||
};
|
||
|
||
// template<class Token, typename T, auto setter>
|
||
// Vector<Token, T, setter>::Vector(const QVector<T> &vec) noexcept:QVector { vec } { }
|
||
|
||
template <class Token>
|
||
using Text = String<Token, [](auto& self, const auto& string) { self.setText(string); }>;
|
||
|
||
// 通用指针绑定
|
||
template <class Token, class Final>
|
||
struct Bind : Token {
|
||
Final*& widget;
|
||
explicit Bind(Final*& p)
|
||
: widget(p) { };
|
||
void apply(Final& self) const { widget = &self; }
|
||
};
|
||
|
||
// 通用点击事件
|
||
template <typename Callback, class Token>
|
||
struct Clickable : Token {
|
||
Callback callback;
|
||
explicit Clickable(Callback callback) noexcept
|
||
: callback { std::move(callback) } { }
|
||
auto apply(auto& self) const noexcept -> void
|
||
requires std::invocable<Callback, decltype(self)> || std::invocable<Callback>
|
||
{
|
||
using widget_t = std::remove_cvref_t<decltype(self)>;
|
||
QObject::connect(&self, &widget_t::clicked, [function = callback, &self] {
|
||
if constexpr (std::invocable<Callback, decltype(self)>) function(self);
|
||
if constexpr (std::invocable<Callback>) function();
|
||
});
|
||
}
|
||
};
|
||
|
||
template <typename Callback, class Token>
|
||
struct IndexChanged : Token {
|
||
Callback callback;
|
||
explicit IndexChanged(Callback callback) noexcept
|
||
: callback {std::move(callback)} {}
|
||
auto apply(auto& self) const noexcept -> void
|
||
requires std::invocable<Callback, decltype(self)> || std::invocable<Callback> {
|
||
using widget_t = std::remove_cvref_t<decltype(self)>;
|
||
QObject::connect(&self, &widget_t::currentIndexChanged, [function = callback, &self] {
|
||
if constexpr (std::invocable<Callback, decltype(self)>) function(self);
|
||
});
|
||
}
|
||
};
|
||
|
||
// 自定义信号回调注册
|
||
|
||
namespace internal {
|
||
template <typename T>
|
||
struct FunctionArgs;
|
||
|
||
template <class C, class R, class... Args>
|
||
struct FunctionArgs<auto (C::*)(Args...)->R> {
|
||
using type = std::tuple<Args...>;
|
||
};
|
||
template <class C, class R, class... Args>
|
||
struct FunctionArgs<auto (C::*)(Args...) const->R> {
|
||
using type = std::tuple<Args...>;
|
||
};
|
||
|
||
template <typename F, typename Tuple>
|
||
concept tuple_invocable_trait = requires(F&& f, Tuple&& t) {
|
||
std::apply(std::forward<F>(f), std::forward<Tuple>(t)); //
|
||
};
|
||
}
|
||
|
||
template <typename F, class Token, auto signal>
|
||
struct SignalInjection : Token {
|
||
F f;
|
||
|
||
using SignalArgs = typename internal::FunctionArgs<decltype(signal)>::type;
|
||
|
||
explicit SignalInjection(F f) noexcept
|
||
requires internal::tuple_invocable_trait<F, SignalArgs>
|
||
: f { std::forward<decltype(f)>(f) } { }
|
||
|
||
auto apply(auto& self) const noexcept { QObject::connect(&self, signal, f); }
|
||
};
|
||
|
||
}
|
||
}
|