SDOM - Simple SDL Document Object Model
A lightweight, extensible Document Object Model for SDL-based applications.
Loading...
Searching...
No Matches
SDOM.hpp
Go to the documentation of this file.
1/*** SDOM.hpp **************************************
2 * ___ ___ ___ __ __ _
3 * / __| \ / _ \| \/ | | |_ _ __ _ __
4 * \__ \ |) | (_) | |\/| |_| ' \| '_ \ '_ \
5 * |___/___/ \___/|_| |_(_)_||_| .__/ .__/
6 * |_| |_|
7 *
8 * The SDOM.hpp header file serves as a centralized location for
9 * defining commonly used types, global macros, and debugging
10 * utilities within the SDOM namespace. It includes type aliases,
11 * such as ID, and provides macros for error handling (ERROR),
12 * warnings (WARNING), and debugging (DEBUG) with formatted output.
13 * This file helps standardize and simplify code across the project.
14 *
15 * Note:
16 * SDOM.hpp includes both the umbrella header (SDOM_Front.hpp) for
17 * implementation and an interface-safe header (SDOM_Interface.hpp)
18 * for type definitions, macros, and utilities. This ensures you
19 * have access to all SDOM features with a single include. For
20 * advanced usage, you may include individual SDOM headers as needed.
21 *
22 * This software is provided 'as-is', without any express or implied
23 * warranty. In no event will the authors be held liable for any damages
24 * arising from the use of this software.
25 *
26 * Permission is granted to anyone to use this software for any purpose,
27 * including commercial applications, and to alter it and redistribute it
28 * freely, subject to the following restrictions:
29 *
30 * 1. The origin of this software must not be misrepresented; you must not
31 * claim that you wrote the original software. If you use this software
32 * in a product, an acknowledgment in the product documentation would be
33 * appreciated but is not required.
34 * 2. Altered source versions must be plainly marked as such, and must not be
35 * misrepresented as being the original software.
36 * 3. This notice may not be removed or altered from any source distribution.
37 *
38 * Released under the ZLIB License.
39 * Original Author: Jay Faries (warte67)
40 *
41 **********************/
42
43#pragma once
44
45#include <SDL3/SDL.h>
46#include <SDL3_image/SDL_image.h>
47#include <SDL3_mixer/SDL_mixer.h>
48#include <SDL3_ttf/SDL_ttf.h>
49
50#include <any>
51#include <algorithm>
52#include <chrono>
53#include <functional>
54#include <fstream>
55#include <iomanip>
56#include <iostream>
57#include <map>
58#include <memory>
59#include <mutex>
60#include <queue>
61#include <sstream>
62#include <string>
63#include <unordered_map>
64#include <unordered_set>
65#include <vector>
66
67// #define SOL_ALL_AUTOMAGIC 0
68#include <sol/sol.hpp>
69
70constexpr bool DEBUG_REGISTER_LUA = false;
71
72// Enable verbose Lua-related test/info logs when set to 1. Default is off.
73#ifndef DEBUG_LUA_TESTS
74#define DEBUG_LUA_TESTS 0
75#endif
76
77// Garbage Collection / Orphan Retention
78constexpr int ORPHAN_GRACE_PERIOD = 5000; // default grace period for orphaned objects (in milliseconds)
79
84namespace SDOM
85{
92 // Exception class definition
93 class Exception : public std::exception
94 {
95 public:
96 Exception(const std::string& message, const std::string& file, int line)
97 : message_(message), file_(file), line_(line) {}
98 const char* what() const noexcept override { return message_.c_str(); }
99 std::string getFile() const { return file_; }
100 int getLine() const { return line_; }
101 private:
102 std::string message_;
103 std::string file_;
104 int line_;
105 };
106
107 // // stand alone SDOM functions
108 // static const char* version();
109 // static const char* compilationDate();
110
111 // class Core;
112 // class Factory;
113 // class Stage;
114
115 // void quit();
116 // void shutdown();
117 // Core& getCore();
118 // Factory& getFactory();
119 // Stage* getStage();
120 // DomHandle getStageHandle();
121 // SDL_Renderer* getRenderer();
122 // SDL_Window* getWindow();
123 // SDL_Texture* getTexture();
124
125
136 enum class AnchorPoint : uint8_t
137 {
138 // Main anchor points
139 DEFAULT = 0,
140 TOP_LEFT = 0,
141 TOP_CENTER = 1,
142 TOP_RIGHT = 2,
143 MIDDLE_LEFT = 3,
144 MIDDLE_CENTER = 4,
145 MIDDLE_RIGHT = 5,
146 BOTTOM_LEFT = 6,
147 BOTTOM_CENTER = 7,
148 BOTTOM_RIGHT = 8,
149
152 LEFT = MIDDLE_LEFT,
155 TOP = TOP_CENTER,
168 };
169
170 /*
171 * Note: Anchor name normalization
172 * --------------------------------
173 * Canonicalization of user-provided anchor strings is performed by
174 * the helper function SDOM::normalizeAnchorString(const std::string&),
175 * implemented in `src/SDOM_Utils.cpp`.
176 *
177 * Behavior summary:
178 * - Strips whitespace and lower-cases the input.
179 * - Recognizes a single operator character joining two keywords
180 * (one of: '-', '|', '&', '+', ',') and returns the joined form
181 * using '_' as the separator (e.g. "top+left" -> "top_left").
182 * - Validates keyword pairs (e.g. disallows "top_bottom" or
183 * "left_right") and returns an empty string while emitting a
184 * WARNING on invalid inputs.
185 *
186 * The Factory and other parsers call this function before looking up
187 * entries in `stringToAnchorPoint_` so consumers can pass flexible
188 * anchor names (spaces, different joiners, mixed case) and still
189 * resolve to the canonical enum value.
190 */
191
201 inline static const std::unordered_map<AnchorPoint, std::string> anchorPointToString_ = {
202 { AnchorPoint::TOP_LEFT, "top_left" },
203 { AnchorPoint::TOP_CENTER, "top_center" },
204 { AnchorPoint::TOP_RIGHT, "top_right" },
205 { AnchorPoint::MIDDLE_LEFT, "middle_left" },
206 { AnchorPoint::MIDDLE_CENTER,"middle_center" },
207 { AnchorPoint::MIDDLE_RIGHT, "middle_right" },
208 { AnchorPoint::BOTTOM_LEFT, "bottom_left" },
209 { AnchorPoint::BOTTOM_CENTER,"bottom_center" },
210 { AnchorPoint::BOTTOM_RIGHT, "bottom_right" }
211 };
212
254 inline static const std::unordered_map<std::string, AnchorPoint> stringToAnchorPoint_ = {
257 { "default", AnchorPoint::DEFAULT },
258 { "left", AnchorPoint::LEFT },
259 { "center", AnchorPoint::CENTER },
260 { "right", AnchorPoint::RIGHT },
261 { "top", AnchorPoint::TOP },
262 { "top_left", AnchorPoint::TOP_LEFT },
263 { "top_center", AnchorPoint::TOP_CENTER },
264 { "top_right", AnchorPoint::TOP_RIGHT },
265 { "middle", AnchorPoint::MIDDLE },
266 { "middle_left", AnchorPoint::MIDDLE_LEFT },
267 { "middle_center", AnchorPoint::MIDDLE_CENTER },
268 { "middle_right", AnchorPoint::MIDDLE_RIGHT },
269 { "bottom", AnchorPoint::BOTTOM },
270 { "bottom_left", AnchorPoint::BOTTOM_LEFT },
271 { "bottom_center", AnchorPoint::BOTTOM_CENTER },
272 { "bottom_right", AnchorPoint::BOTTOM_RIGHT },
274
277 { "center_middle", AnchorPoint::MIDDLE_CENTER },
278 { "right_middle", AnchorPoint::MIDDLE_RIGHT },
279 { "left_middle", AnchorPoint::MIDDLE_LEFT },
280 { "center_top", AnchorPoint::TOP_CENTER },
281 { "right_top", AnchorPoint::TOP_RIGHT },
282 { "left_top", AnchorPoint::TOP_LEFT },
283 { "center_bottom", AnchorPoint::BOTTOM_CENTER },
284 { "right_bottom", AnchorPoint::BOTTOM_RIGHT },
285 { "left_bottom", AnchorPoint::BOTTOM_LEFT },
287 }; // unordered_map stringToAnchorPoint_
288
306 struct Bounds
307 {
308 float left = 0.0f;
309 float top = 0.0f;
310 float right = 0.0f;
311 float bottom = 0.0f;
312
317 float width() const { return abs(right - left); }
318
323 float height() const { return abs(bottom - top); }
324
325 // Equality operator with epsilon for floating-point comparison
326 bool operator==(const Bounds& other) const {
327 constexpr float epsilon = 0.0001f;
328 return std::abs(left - other.left) < epsilon &&
329 std::abs(top - other.top) < epsilon &&
330 std::abs(right - other.right) < epsilon &&
331 std::abs(bottom - other.bottom) < epsilon;
332 }
333
334 bool operator!=(const Bounds& other) const {
335 return !(*this == other);
336 }
337 };
338
339} // namespace SDOM
340
345// Macro for throwing exceptions
346#define ERROR(message) throw SDOM::Exception(message, __FILE__, __LINE__)
347
348
353// Macro for showing warnings
354#define WARNING(message) SDOM::showWarning(message, __FILE__, __LINE__)
355
360// Macro for debug logging (statement-safe, parenthesized parameter)
361#define DEBUG_LOG(...) do { \
362 std::ostringstream _sdom_dbg_oss; \
363 _sdom_dbg_oss << __VA_ARGS__; \
364 std::cout << CLR::GREEN << "[DEBUG] " << _sdom_dbg_oss.str() << CLR::RESET << std::endl; \
365} while(0)
366
371// Macro for failure logging (statement-safe, parenthesized parameter)
372#define FAIL(...) do { \
373 std::ostringstream _sdom_dbg_oss; \
374 _sdom_dbg_oss << __VA_ARGS__; \
375 std::cout << CLR::RED << "[FAILED] " << _sdom_dbg_oss.str() << CLR::RESET << std::endl; \
376} while(0)
377
382// Macro for informational logging (statement-safe, parenthesized parameter)
383#define INFO(...) do { \
384 std::ostringstream _sdom_dbg_oss; \
385 _sdom_dbg_oss << __VA_ARGS__; \
386 std::cout << CLR::YELLOW << "[INFO] " << (_sdom_dbg_oss.str()) << CLR::RESET << std::endl; } while(0)
387
388// Lua-specific informational logging (only active when DEBUG_LUA_TESTS == 1)
389#define LUA_INFO(...) do { if (DEBUG_LUA_TESTS) { std::ostringstream _sdom_lua_dbg_oss; _sdom_lua_dbg_oss << __VA_ARGS__; std::cout << CLR::YELLOW << "[LUA-INFO] " << (_sdom_lua_dbg_oss.str()) << CLR::RESET << std::endl; } } while(0)
390
395// Macro for debug errors (statement-safe)
396#define DEBUG_ERR(message) do { std::cout << CLR::DARK << \
397 "\n Debug: " << \
398 CLR::YELLOW << (message) << std::endl << CLR::DARK << \
399 " File: " << CLR::ORANGE << __FILE__ << CLR::DARK << std::endl << \
400 " Line: " << CLR::ORANGE << __LINE__ << CLR::RESET << "\n" << std::endl; } while(0)
401
407// Assertion macro for testing equality
408#define ASSERT_EQ(val, expected) \
409 if ((val) != (expected)) { \
410 ERROR("Assertion failed: " + std::string(#val) + " == " + std::string(#expected) \
411 + ", actual: " + std::to_string((val)) + ", expected: " + std::to_string((expected))); \
412 }
413
415#include <SDOM/SDOM_CLR.hpp>
419#include <SDOM/SDOM_Utils.hpp>
420
421#ifndef SDOM_USE_INDIVIDUAL_HEADERS
422 // SDOM_Front.hpp is an umbrella header meant for implementation files only.
423 // Including it from SDOM.hpp can create circular includes (SDOM.hpp -> SDOM_Front.hpp -> SDOM_Core.hpp -> SDOM.hpp)
424 // which may leave class definitions incomplete during header processing. Consumers who want the full
425 // API should include SDOM_Front.hpp directly in .cpp files. Keep this block intentionally empty here
426 // to avoid accidental circular include dependencies.
427#endif
428
429
430
431
constexpr int ORPHAN_GRACE_PERIOD
Definition SDOM.hpp:78
constexpr bool DEBUG_REGISTER_LUA
Definition SDOM.hpp:70
Static container for ANSI escape sequences for terminal text formatting and colorization.
Custom exception class for SDOM errors.
Definition SDOM.hpp:94
const char * what() const noexcept override
Definition SDOM.hpp:98
Exception(const std::string &message, const std::string &file, int line)
Definition SDOM.hpp:96
std::string getFile() const
Definition SDOM.hpp:99
int getLine() const
Definition SDOM.hpp:100
Contains all core classes and utilities for the SDOM library.
Definition lua_BindHelpers.hpp:7
static const std::unordered_map< std::string, AnchorPoint > stringToAnchorPoint_
Maps string names to AnchorPoint enum values.
Definition SDOM.hpp:254
static const std::unordered_map< AnchorPoint, std::string > anchorPointToString_
Maps AnchorPoint enum values to their corresponding string names.
Definition SDOM.hpp:201
AnchorPoint
Reference points for anchoring child edges to a parent.
Definition SDOM.hpp:137
@ MIDDLE_RIGHT
Middle-right edge of the parent.
@ RIGHT_TOP
Alias for TOP_RIGHT.
@ BOTTOM
Alias for BOTTOM_CENTER.
@ RIGHT
Alias for MIDDLE_RIGHT.
@ RIGHT_BOTTOM
Alias for BOTTOM_RIGHT.
@ BOTTOM_RIGHT
Bottom-right corner of the parent.
@ BOTTOM_CENTER
Bottom-center edge of the parent.
@ MIDDLE
Alias for MIDDLE_CENTER.
@ LEFT_BOTTOM
Alias for BOTTOM_LEFT.
@ DEFAULT
Default anchor point (same as TOP_LEFT)
@ LEFT_TOP
Alias for TOP_LEFT.
@ TOP
Alias for TOP_CENTER.
@ LEFT
Alias for MIDDLE_LEFT.
@ TOP_LEFT
Top-left corner of the parent.
@ MIDDLE_CENTER
Center of the parent.
@ BOTTOM_LEFT
Bottom-left corner of the parent.
@ TOP_RIGHT
Top-right corner of the parent.
@ MIDDLE_LEFT
Middle-left edge of the parent.
@ CENTER_MIDDLE
Alias for MIDDLE_CENTER.
@ CENTER_TOP
Alias for TOP_CENTER.
@ CENTER
Alias for MIDDLE_CENTER.
@ CENTER_BOTTOM
Alias for BOTTOM_CENTER.
@ TOP_CENTER
Top-center edge of the parent.
@ LEFT_MIDDLE
Alias for MIDDLE_LEFT.
@ RIGHT_MIDDLE
Alias for MIDDLE_RIGHT.
Represents a rectangle's position and size in 2D space.
Definition SDOM.hpp:307
bool operator==(const Bounds &other) const
Definition SDOM.hpp:326
float left
Left edge coordinate.
Definition SDOM.hpp:308
float top
Top edge coordinate.
Definition SDOM.hpp:309
bool operator!=(const Bounds &other) const
Definition SDOM.hpp:334
float right
Right edge coordinate.
Definition SDOM.hpp:310
float bottom
Bottom edge coordinate.
Definition SDOM.hpp:311
float height() const
Calculates the height of the bounds.
Definition SDOM.hpp:323
float width() const
Calculates the width of the bounds.
Definition SDOM.hpp:317