#pragma once
#include <optional>

#define SLOT_ME() auto& me() { return static_cast<T&>(*this) }

#define SLOT_ATTRIBUTE(type, name) \
	public: \
	auto& name(type in_##name) { \
		name##_ = in_##name; \
		return me(); \
	} \
	const auto& name() const { return name##_; } \
	protected: \
	type name##_{};

#define SLOT_OPTIONAL(type, name) \
	public: \
	auto& name(type in_##name) { \
		name##_ = in_##name; \
		return me(); \
	} \
	const auto& name() const { return name##_.value(); } \
	auto has_##name() const { return name##_.has_value(); } \
	protected: \
	std::optional<type> name##_;

#define SLOT_CONTENT() \
	public: \
	auto& set(const std::shared_ptr<mwidget_interface>& in_widget) { \
		widget_ = in_widget; \
		return me(); \
	} \
	const auto& get() const { return widget_; } \
	auto& operator[](const std::shared_ptr<mwidget_interface>& in_widget) { \
		set(in_widget); \
		return me(); \
	} \
	auto& operator+(const std::shared_ptr<mwidget_interface>& in_widget) { \
		set(in_widget); \
		return me(); \
	} \
	protected: \
	std::shared_ptr<mwidget_interface> widget_{};

#define SLOT_SIZE() \
	public: \
	auto& stretch(float in_stretch = 1.f) { \
		size_.set_stretch(in_stretch); \
		return me(); \
	} \
	auto& auto_size() { \
		size_.set_auto_size(); \
		return me(); \
	} \
	const auto& size() const { \
		return size_; \
	} \
	protected: \
		widget_size size_ = widget_size::auto_size();
