121 lines
3.5 KiB
C++
121 lines
3.5 KiB
C++
#pragma once
|
||
/**
|
||
* @file mpanel_widget.h
|
||
* @brief 定义可容纳多个子组件的面板组件基类
|
||
*
|
||
* 本文件定义了mpanel_widget模板类,这是一种可以容纳多个子组件的面板组件。
|
||
* 通过模板参数SlotType可以自定义子组件插槽的具体行为。
|
||
*/
|
||
|
||
#include "widget/mwidget.h"
|
||
#include "widget/slot_util.h"
|
||
#include "widget_tree/widget_manager.h"
|
||
|
||
/**
|
||
* @struct mpanel_widget_slot
|
||
* @brief 面板组件的插槽结构,管理子组件
|
||
*
|
||
* @tparam T 插槽的具体类型,通常是派生自此模板的类
|
||
*
|
||
* 提供了对子组件的内容管理功能。
|
||
* 使用SLOT宏来定义插槽的标准功能。
|
||
*/
|
||
template<typename T>
|
||
struct mpanel_widget_slot {
|
||
/**
|
||
* @brief 获取当前实例的引用,转换为具体类型T
|
||
* @return 当前实例的引用,类型为T&
|
||
*/
|
||
auto& me() {
|
||
return static_cast<T&>(*this);
|
||
}
|
||
widget_key slot_owner;
|
||
|
||
// 插槽功能宏 - 定义内容管理
|
||
SLOT_CONTENT()
|
||
};
|
||
|
||
/**
|
||
* @class mpanel_widget
|
||
* @brief 可布局多个子组件的面板组件基类
|
||
*
|
||
* @tparam SlotType 插槽类型,控制如何管理子组件
|
||
*
|
||
* 这个类是所有需要容纳多个子组件的面板组件的基类。
|
||
* 它提供了子组件的管理和查询功能。
|
||
*/
|
||
template<typename SlotType>
|
||
class mpanel_widget : public mwidget {
|
||
public:
|
||
//-------------- 绘制 --------------
|
||
|
||
/**
|
||
* @brief 绘制组件
|
||
* @param in_context 绘制上下文
|
||
*
|
||
* 基类实现为空,因为面板组件通常不需要自己绘制,而是依赖子组件的绘制。
|
||
*/
|
||
void on_paint(mirage_paint_context& in_context) override {}
|
||
|
||
void cache_all_children_desired_size(float in_layout_scale_multiplier, bool in_force = false) const;
|
||
|
||
//-------------- 子项管理 --------------
|
||
|
||
// 1. 创建一个新的entity
|
||
// 2. 给entity添加一个slot component
|
||
// 3. 更新父子关系
|
||
// 4. 通知父组件需要重新计算布局
|
||
// 5. 返回slot component的引用,便于链式调用设置属性
|
||
|
||
/**
|
||
* @brief 添加新的子组件插槽
|
||
* @return 新添加的插槽引用,允许链式调用设置插槽属性
|
||
*
|
||
* 创建并添加一个新的子组件插槽到面板中。
|
||
*/
|
||
auto add_slot() -> SlotType& {
|
||
auto& manager = widget_manager::get();
|
||
auto widget_entity = manager.new_widget<SlotType>(get_window());
|
||
auto w = widget_entity.lock();
|
||
auto& slot = w->template add_component<SlotType>();
|
||
slot.slot_owner = key_;
|
||
return slot;
|
||
}
|
||
|
||
auto get_slots_ref() {
|
||
std::vector<SlotType&> children;
|
||
if (auto hierarchy = get_component<widget_hierarchy>()) {
|
||
auto& manager = widget_manager::get();
|
||
for (const auto& child : hierarchy->children) {
|
||
if (auto slot = manager.get_component<SlotType>(child)) {
|
||
children.push_back(*slot);
|
||
}
|
||
}
|
||
}
|
||
return children;
|
||
}
|
||
auto get_slots() const {
|
||
std::vector<SlotType*> children;
|
||
if (auto hierarchy = get_component<widget_hierarchy>()) {
|
||
auto& manager = widget_manager::get();
|
||
for (const auto& child : hierarchy->children) {
|
||
if (auto slot = manager.get_component<SlotType>(child)) {
|
||
children.push_back(slot);
|
||
}
|
||
}
|
||
}
|
||
return children;
|
||
}
|
||
};
|
||
|
||
template<typename SlotType>
|
||
void mpanel_widget<SlotType>::cache_all_children_desired_size(float in_layout_scale_multiplier, bool in_force) const {
|
||
auto& manager = widget_manager::get();
|
||
const auto& hierarchy = get_component_ref<widget_hierarchy>();
|
||
|
||
for (const auto& child: hierarchy.children) {
|
||
const auto& ptr = manager.get_component_ref<widget_ptr>(child);
|
||
ptr->cache_desired_size(in_layout_scale_multiplier, in_force);
|
||
}
|
||
}
|