1#ifndef NEFORCE_TUI_COMPONENT_COMPONENT_HPP__
2#define NEFORCE_TUI_COMPONENT_COMPONENT_HPP__
18NEFORCE_BEGIN_NAMESPACE__
157 NEFORCE_NODISCARD
int index() const noexcept {
161 for (
size_t i = 0; i <
parent_->children_.size(); ++i) {
162 if (
parent_->children_[i].get() ==
this) {
163 return static_cast<int>(i);
176 child->parent_ =
this;
179 child->schedule_render_cb_ = schedule_render_cb_;
180 auto* raw = child.
get();
194 if (it->get() == child) {
195 auto owned =
move(*it);
209 return parent_->remove_child(
this);
227 NEFORCE_NODISCARD
virtual bool focusable()
const {
return false; }
251 NEFORCE_NODISCARD
bool active() const noexcept {
return parent_ ==
nullptr ||
parent_->active_child() ==
this; }
257 NEFORCE_NODISCARD
bool focused() const noexcept {
272 for (
auto* p =
parent_; p !=
nullptr; p = p->parent_) {
273 p->set_active_child(focus);
284 if (schedule_render_cb_) {
285 schedule_render_cb_(
this);
294 template <
typename Ctx>
304 template <
typename Ctx>
305 NEFORCE_NODISCARD
const Ctx&
context()
const {
306 for (
const auto* p =
this; p !=
nullptr; p = p->parent_) {
307 auto it = p->contexts_.find(
typeid(Ctx).hash_code());
308 if (it != p->contexts_.end()) {
309 return *
static_cast<const Ctx*
>(it->second.get());
312 NEFORCE_THROW_EXCEPTION(
value_exception(
"Context not found in component tree"));
333 child->collect_focusable(out);
348template <
typename P = empty_props>
351 using props_type = P;
353 component() =
default;
354 ~component()
override =
default;
355 component(
const component&) =
delete;
356 component& operator=(
const component&) =
delete;
357 component(component&&) =
delete;
358 component& operator=(component&&) =
delete;
365 NEFORCE_NODISCARD
const props_type&
props() const noexcept {
return props_; }
377 template <
typename T>
380 states_.push_back(s);
402void state<T>::schedule_render() {
403 if (owner_ !=
nullptr) {
404 owner_->schedule_render();
412NEFORCE_END_NAMESPACE__
void add_child(unique_ptr< component_base > child)
注册子组件
virtual bool on_key(const key_event &e)
键盘事件处理
component_base * active_child() noexcept
获取当前激活的子组件
void set_active_child(component_base *child) noexcept
设置激活的子组件
virtual element render()=0
声明式渲染
virtual void take_focus()
请求焦点
bool pass_through() const noexcept
是否启用事件穿透
component_base * parent_
父组件指针
bool active() const noexcept
是否处于激活状态
const component_base * active_child() const noexcept
获取当前激活的子组件
void set_pass_through(bool v) noexcept
设置事件穿透
int index() const noexcept
获取自身在父组件中的索引
bool has_focus() const noexcept
是否持有 Reconciler 键盘焦点
void provide_context(Ctx value)
设置上下文值
component_base * active_child_
当前激活的子组件
virtual bool focusable() const
是否可获取焦点
virtual void on_animation(int64_t delta)
动画帧回调
virtual void on_mouse_leave()
鼠标离开回调
bool has_focus_
reconciler 焦点状态
void schedule_render()
调度重渲染
bool focused() const noexcept
是否拥有焦点
unique_ptr< component_base > remove_child(component_base *child)
移除子组件
const Ctx & context() const
获取上下文值
size_t child_count() const noexcept
获取子组件数量
component_base * child_at(size_t i) const noexcept
获取指定索引的子组件
component_base * parent() const noexcept
获取父组件
void detach_all_children()
移除所有子组件
unique_ptr< component_base > detach()
从父组件中脱离自身
void set_has_focus(bool v) noexcept
设置 Reconciler 焦点状态(由 Reconciler 调用)
virtual void cleanup() noexcept
卸载回调
vector< unique_ptr< component_base > > children_
子组件列表
virtual bool on_mouse(const mouse_event &e)
鼠标事件处理
virtual bool should_update()
是否需要更新
state< T > & create_state(T initial)
创建响应式状态变量
void set_props(props_type p)
注入属性
const props_type & props() const noexcept
获取父组件传入的属性
constexpr pointer get() const noexcept
获取原始指针
constexpr void push_back(const T &value)
在末尾拷贝插入元素
enable_if_t<!is_unbounded_array_v< T > &&is_constructible_v< T, Args... >, shared_ptr< T > > make_shared(Args &&... args)
融合分配创建共享指针
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素