Loading...
Searching...
No Matches
Core.h
Go to the documentation of this file.
1// Copyright (c) 2025 Dave R. Smith.
2// Malena Framework — Licensed under PolyForm Noncommercial 1.0.0; commercial use requires a paid license. See LICENSE.
3
4//
5// Created by Dave Smith on 10/4/25.
6//
7
8#ifndef MALENA_UICOMPONENTBASE_H
9#define MALENA_UICOMPONENTBASE_H
10
12#include <SFML/Graphics.hpp>
13#include <functional>
14#include <type_traits>
15#include <vector>
16
21
28
30
31namespace ml
32{
51 enum class Layer : int
52 {
54 Content = 100,
55 Overlay = 200,
56 };
57
85 class MALENA_API Core : public virtual Subscribable,
86 public virtual Flaggable,
87 public virtual Positionable,
88 public virtual Clickable,
89 public virtual Hoverable,
90 public virtual Focusable,
91 public virtual Keyable,
92 public virtual Scrollable,
93 // public virtual Draggable,
94 public virtual Updatable,
95 public Unsubscribable
96
97 {
98 public:
100 virtual ~Core();
101
103
104 // ── Enabled state ──────────────────────────────────────────────────
105 // Two-flag model: effective enabled = _selfEnabled && _parentEnabled,
106 // mirrored into Flag::ENABLED (what hit-testing filters on). This keeps
107 // "a component I explicitly disabled stays disabled when its parent is
108 // re-enabled" working.
109 //
110 // To REACT to an enable/disable change (sync visuals/colors, reset a
111 // hover state, close a popup, …), override onEnabledChanged(bool
112 // effective) — it fires on BOTH the direct (setEnabled) and cascade
113 // (setParentEnabled) paths. Do NOT override setEnabled/setParentEnabled
114 // to do that work, or the cascade path silently skips it. Controls do
115 // NOT keep a separate "disabled" flag; disabled is read live from
116 // Flag::ENABLED, so the flag and the visuals can never disagree.
117
121 void setEnabled(bool enabled);
122
127 void setParentEnabled(bool enabled);
128
129 virtual void setVisible(bool visible);
130 virtual void setActive(bool active);
131
136 void setVisibilityIndependent(bool independent) { setFlag(Flag::VISIBILITY_INDEPENDENT, independent); }
138
142 virtual void onWindowResize(unsigned int /*width*/, unsigned int /*height*/) {}
143 bool isEnabled() const;
144 bool isVisible() const;
145
158
162 static constexpr int DefaultLayer = 100;
163
170 struct Child
171 {
173 int layer;
174 };
175
176 void addComponent(Core& child);
177 void addComponent(Core& child, int layer);
178
210 template<typename E,
211 typename = std::enable_if_t<std::is_enum_v<E>>>
212 void addComponent(Core& child, E layer)
213 {
214 addComponent(child, static_cast<int>(layer));
215 }
216
217 void removeComponent(Core& child);
218
236 Core* topmostMatching(const std::function<bool(Core&)>& accept);
237
249 template<typename... Children>
250 void addComponents(Children&... children)
251 {
252 static_assert((std::is_base_of_v<Core, Children> && ...),
253 "addComponents() requires Core-derived arguments");
254 (addComponent(children), ...);
255 }
256
266 template<typename... Children>
267 void addComponents(int layer, Children&... children)
268 {
269 static_assert((std::is_base_of_v<Core, Children> && ...),
270 "addComponents() requires Core-derived arguments");
271 (addComponent(children, layer), ...);
272 }
273
281 template<typename E, typename... Children,
282 typename = std::enable_if_t<std::is_enum_v<E>>>
283 void addComponents(E layer, Children&... children)
284 {
285 static_assert((std::is_base_of_v<Core, Children> && ...),
286 "addComponents() requires Core-derived arguments");
287 (addComponent(children, static_cast<int>(layer)), ...);
288 }
289
290 static void linkChild(Core* parent, Core* child);
291 static void unlinkAll(Core* core);
292
293 protected:
300 virtual void onEnabledChanged(bool enabled) {}
301
306 const std::vector<Child>& getChildren() const { return _children; }
307
320 void drawChildren(sf::RenderTarget& target, sf::RenderStates states) const;
321
322 private:
323 bool _selfEnabled = true;
324 bool _parentEnabled = true;
325
326 void applyEnabled(bool selfEnabled, bool parentEnabled);
327
328 // ── Per-instance parent/child topology ──────────────────────────────
329 // Replaces the static _childMap. Single-parent: a Core may appear in
330 // at most one parent's _children vector at a time. linkChild silently
331 // moves a child if its previous parent differs.
332 Core* _parent = nullptr;
333 std::vector<Child> _children;
334
335 // Reentrancy guard for cascades that may indirectly trigger
336 // removeComponent / linkChild. Mutations while iterating defer until
337 // the depth returns to zero.
338 int _iterDepth = 0;
339 std::vector<std::function<void()>> _pendingOps;
340
341 void doRemoveChild(Core* child);
342 void runPendingIfDepthZero();
343
344 // Insert a child keeping _children sorted by layer ascending, with
345 // registration order preserved within a layer. O(n) positional insert,
346 // not a full re-sort. Sets the child's _parent. Caller guarantees the
347 // child is not already present.
348 void insertChildSorted(Core& child, int layer);
349
350 static bool isDescendantOf(Core* ancestor, Core* component);
351 friend class AppManager;
352 };
353
354} // namespace ml
355
356#endif // MALENA_UICOMPONENTBASE_H
void addComponents(int layer, Children &... children)
Register multiple child components at a shared layer.
Definition Core.h:267
bool isEffectivelyVisible() const
True only if this component and every ancestor are visible.
virtual void setVisible(bool visible)
void addComponents(E layer, Children &... children)
Variadic shared-layer registration with an enum layer key.
Definition Core.h:283
Core * topmostMatching(const std::function< bool(Core &)> &accept)
Find the front-most (last-painted) node in this subtree that satisfies accept, searching topmost-firs...
void setEnabled(bool enabled)
virtual void setActive(bool active)
void removeComponent(Core &child)
bool isVisibilityIndependent() const
Definition Core.h:137
virtual void onEnabledChanged(bool enabled)
Definition Core.h:300
void addComponent(Core &child, E layer)
Register a child at a layer identified by any enum value.
Definition Core.h:212
virtual sf::RenderStates getRenderStates() const
Definition Core.h:102
bool isEnabled() const
void setParentEnabled(bool enabled)
static void linkChild(Core *parent, Core *child)
friend class AppManager
Definition Core.h:351
virtual void onWindowResize(unsigned int, unsigned int)
Definition Core.h:142
void addComponents(Children &... children)
Register multiple child components at the default layer.
Definition Core.h:250
void setVisibilityIndependent(bool independent)
Definition Core.h:136
static void unlinkAll(Core *core)
static constexpr int DefaultLayer
Definition Core.h:162
void addComponent(Core &child, int layer)
void addComponent(Core &child)
void drawChildren(sf::RenderTarget &target, sf::RenderStates states) const
virtual ~Core()
const std::vector< Child > & getChildren() const
Definition Core.h:306
bool isVisible() const
void setFlag(State state, bool status)
bool checkFlag(State state) const
Trait that provides system-level boolean flag management.
Definition Flaggable.h:53
Trait that adds keyboard-focus and blur callbacks to any Core object.
Definition Focusable.h:46
Trait that adds mouse-hover and mouse-leave callbacks to any Core object.
Definition Hoverable.h:47
Trait that adds keyboard-input callbacks to any Core object.
Definition Keyable.h:55
Trait that provides position, bounds, and animated movement.
Trait that adds mouse-wheel and raw mouse-button callbacks to any Core object.
Definition Scrollable.h:55
Trait that allows a component to subscribe to and publish framework events.
Trait that gives components the ability to unsubscribe from events.
Trait that adds per-frame update and window lifecycle callbacks to any Core object.
Definition Updatable.h:61
Layer
Framework-provided default layer enum.
Definition Core.h:52
@ Overlay
Definition Core.h:55
@ Background
Definition Core.h:53
@ Content
Definition Core.h:54
@ VISIBILITY_INDEPENDENT
This child opts OUT of a parent container's setVisible/setActive cascade (it manages its own visibili...
Definition Flag.h:76
#define MALENA_API
Definition Animate.h:25
A registered child plus the layer key it draws/iterates under.
Definition Core.h:171
Core * component
Definition Core.h:172