diff --git a/CMakeLists.txt b/CMakeLists.txt index e7faae3..fb92534 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,9 +25,9 @@ INCLUDE_DIRECTORIES( contrib/stb_image ) -find_package(SDL2 CONFIG REQUIRED) +find_package(SDL2 CONFIG REQUIRED) find_package(SDL2_image CONFIG REQUIRED) -find_package(SDL2_ttf CONFIG REQUIRED) +find_package(SDL2_ttf CONFIG REQUIRED) # Find GoogleTest for unit tests find_package(GTest QUIET) @@ -39,7 +39,7 @@ SET(tinyui_backends_src src/backends/sdl2_iodevice.cpp ) -SOURCE_GROUP( Backends FILES ${tinyui_backends_src} ) +SOURCE_GROUP(Backends FILES ${tinyui_backends_src} ) ADD_LIBRARY(tiny_ui src/tinyui.h diff --git a/src/backends/sdl2_iodevice.h b/src/backends/sdl2_iodevice.h index fabd151..b31bf8a 100644 --- a/src/backends/sdl2_iodevice.h +++ b/src/backends/sdl2_iodevice.h @@ -23,13 +23,20 @@ SOFTWARE. */ #pragma once +/** + * @file sdl2_iodevice.h + * @brief SDL2 I/O device implementation for TinyUI. + * + * This file contains the SDL2-based input/output device backend for the TinyUI library. + */ + #include namespace tinyui { -/// @brief the SDL2 implementation for an io-device. +/// @brief The SDL2 implementation for an io-device. /// -/// IO-Devices are used to contrl any kind of input / output operations. +/// IO-Devices are used to control any kind of input / output operations. struct IODevice { // No copying or moving allowed. IODevice(const IODevice &) = delete; diff --git a/src/backends/sdl2_renderer.h b/src/backends/sdl2_renderer.h index 22c8545..83c3163 100644 --- a/src/backends/sdl2_renderer.h +++ b/src/backends/sdl2_renderer.h @@ -23,6 +23,13 @@ SOFTWARE. */ #pragma once +/** + * @file sdl2_renderer.h + * @brief SDL2 renderer implementation for TinyUI. + * + * This file contains the SDL2-based rendering backend for the TinyUI library. + */ + #include "tinyui.h" #include @@ -55,9 +62,11 @@ struct SurfaceImpl { } }; +/// @brief The font implementation using the SDL2_ttf library. struct FontImpl { TTF_Font *mFontImpl{nullptr}; + /// @brief Clear the font implementation. void clear() { if (mFontImpl != nullptr) { TTF_CloseFont(mFontImpl); @@ -121,7 +130,13 @@ struct Renderer { ~Renderer() = default; // Render implementation functions. + /// @brief Initialize the renderer. + /// @param ctx The TinyUI context. + /// @return ResultOk if successful, ErrorCode otherwise. static ret_code initRenderer(Context &ctx); + /// @brief Release the renderer. + /// @param ctx The TinyUI context. + /// @return ResultOk if successful, ErrorCode otherwise. static ret_code releaseRenderer(Context &ctx); static ret_code initScreen(Context &ctx, int32_t x, int32_t y, int32_t w, int32_t h); static ret_code initScreen(Context &ctx, SDL_Window *mWindow, SDL_Renderer *mRenderer); diff --git a/src/tinyui.cpp b/src/tinyui.cpp index afd992a..56ffa2f 100644 --- a/src/tinyui.cpp +++ b/src/tinyui.cpp @@ -51,12 +51,18 @@ static constexpr char const *SeverityToken[] = { }; static void logVersion(const Context &ctx) { - const std::string msg ="TinyUI Version: " + std::to_string(ctx.mVersion.major) + "." + std::to_string(ctx.mVersion.minor) + "." + std::to_string(ctx.mVersion.patch); + const std::string msg ="TinyUI Version: " + + std::to_string(ctx.mVersion.major) + + "." + + std::to_string(ctx.mVersion.minor) + + "." + + std::to_string(ctx.mVersion.patch); ctx.mLogger(LogSeverity::Info, msg.c_str()); } void log_message(LogSeverity severity, const char *message) { assert(message != nullptr); + if (severity == LogSeverity::Message) { std::cout << message << "\n"; } else { @@ -66,6 +72,10 @@ void log_message(LogSeverity severity, const char *message) { Context *gCtx = nullptr; +Context::~Context() { + clearImageCache(); +} + Context *Context::create(const char *title, const Style &style) { auto *ctx = new Context; ctx->mLogger = log_message; @@ -96,6 +106,10 @@ void Context::destroy(Context *ctx) { delete ctx; } +Context *Context::getCurrent() { + return gCtx; +} + void Context::addImage(const char *name, Image *image) { if (name == nullptr || image == nullptr) { return; @@ -123,6 +137,46 @@ bool Context::removeImage(const char *name) { return mImageCache.erase(std::string(name)) > 0; } +Image *Context::loadIntoImageCache(const char *filename) { + if (filename == nullptr) { + return nullptr; + } + + Image *image = getImage(filename); + if (image != nullptr) { + return image; + } + + int w{ -1 }; + int h{ -1 }; + int bytesPerPixel{ -1 }; + unsigned char *data = stbi_load(filename, &w, &h, &bytesPerPixel, 0); + if (data == nullptr) { + return nullptr; + } + + image = new Image; + int32_t pitch = w * bytesPerPixel; + pitch = (pitch + 3) & ~3; + image->mSurfaceImpl = Renderer::createSurfaceImpl(data, w, h, bytesPerPixel, pitch); + image->mX = w; + image->mY = h; + image->mComp = bytesPerPixel; + mImageCache[filename] = image; + + return image; +} + +void Context::clearImageCache() { + for (auto it = mImageCache.begin(); it != mImageCache.end(); ++it) { + if (auto *image = it->second; image != nullptr) { + Renderer::releaseSurfaceImpl(image->mSurfaceImpl); + delete image; + } + } + mImageCache.clear(); +} + bool TinyUi::createContext(const char *title, const Style &style) { if (gCtx != nullptr) { return false; diff --git a/src/tinyui.h b/src/tinyui.h index 782e245..27626e9 100644 --- a/src/tinyui.h +++ b/src/tinyui.h @@ -23,6 +23,14 @@ SOFTWARE. */ #pragma once +/** + * @file tinyui.h + * @brief Main header file for the TinyUI library. + * + * This file contains the core types, structures, and interfaces for the TinyUI library, + * including widget definitions, context management, and rendering interfaces. + */ + #include "tinyui_config.h" #include @@ -98,7 +106,7 @@ struct SDLContext; // Type declarations ---------------------------------------------------------- -/// @brief This enum is used to describe the alignment of a widget. +/// @brief The unique identifier type used for widgets. using Id = uint64_t; /// @brief The return code type used in the ui library. @@ -462,7 +470,10 @@ struct BackendContext { void *mHandle{nullptr}; ///< The backend specific handle. }; -/// @brief The tiny ui context. +/// @brief The main context struct for the TinyUI library. +/// +/// This struct holds all the global state and configuration for a TinyUI instance, +/// including the widget tree, styles, fonts, images, and event handling. struct Context { bool mCreated{false}; ///< The created state. bool mRequestShutdown{false}; ///< The request shutdown state. @@ -500,7 +511,7 @@ struct Context { static void destroy(Context *ctx); /// @brief Will return the current tiny ui context. - /// @return The current tiny ui context. + /// @return The current tiny ui context, nullptr if not created. static Context *getCurrent(); /// @brief Will add an image to the image cache. @@ -508,8 +519,8 @@ struct Context { /// @param image The image to add. void addImage(const char *name, Image *image); - /// @brief Will lookfor for an imgae described by its name. - /// @param name The name of the image- + /// @brief Will look for an image described by its name. + /// @param name The name of the image. /// @return The image if found, nullptr otherwise. Image *getImage(const char *name); @@ -518,15 +529,22 @@ struct Context { /// @return true if successful. bool removeImage(const char *name); + /// @brief Will load an image into the image cache. + /// @param[in] filename The name of the image to load. + /// @return A pointer showing to the image or nullptr in case of an error. + Image *loadIntoImageCache(const char *filename); + + void clearImageCache(); + private: /// @brief The default class constructor Context() = default; /// @brief The class destructor. - ~Context() = default; + ~Context(); }; -/// @brief The tiny ui app interface. +/// @brief The tiny ui application interface. /// /// The tiny ui interface is used to create and manage the tiny ui context and to run the tiny ui. struct TinyUi { @@ -536,6 +554,11 @@ struct TinyUi { /// @return true if successful. static bool createContext(const char *title, const Style &style); + /// @brief Will create the tinyui context with a custom logger. + /// @param[in] title The app title. + /// @param[in] style The style to use. + /// @param[in] logger The custom logger function. + /// @return true if successful. static bool createContext(const char *title, const Style &style, tui_log_func logger); /// @brief Will destroy the context. diff --git a/src/tinyui_config.h b/src/tinyui_config.h index 7953b12..a0d2d2a 100644 --- a/src/tinyui_config.h +++ b/src/tinyui_config.h @@ -23,5 +23,12 @@ SOFTWARE. */ #pragma once +/** + * @file tinyui_config.h + * @brief Configuration file for the TinyUI library. + * + * This file contains configuration macros and settings for the TinyUI library. + */ + // Enable this to get verbose logs. //#define TINYUI_TRACE_ENABLED diff --git a/src/widgets.cpp b/src/widgets.cpp index 25980de..a047570 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -43,64 +43,7 @@ namespace { static Id id{ RootHandle }; return ++id; } - - Image *findImage(Context &ctx, const char *filename) { - if (filename == nullptr) { - return nullptr; - } - - auto it = ctx.mImageCache.find(filename); - if (it == ctx.mImageCache.end()) { - return nullptr; - } - - return it->second; - } - - Image *loadIntoImageCache(Context &ctx, const char *filename) { - if (filename == nullptr) { - return nullptr; - } - - Image *image = findImage(ctx, filename); - if (image != nullptr) { - return image; - } - - int w{ -1 }; - int h{ -1 }; - int bytesPerPixel{ -1 }; - unsigned char *data = stbi_load(filename, &w, &h, &bytesPerPixel, 0); - if (data == nullptr) { - return nullptr; - } - - image = new Image; - if (image == nullptr) { - return nullptr; - } - - int32_t pitch = w * bytesPerPixel; - pitch = (pitch + 3) & ~3; - image->mSurfaceImpl = Renderer::createSurfaceImpl(data, w, h, bytesPerPixel, pitch); - image->mX = w; - image->mY = h; - image->mComp = bytesPerPixel; - ctx.mImageCache[filename] = image; - - return image; - } - - void releaseImageCache(Context &ctx) { - for (auto it = ctx.mImageCache.begin(); it != ctx.mImageCache.end(); ++it) { - if (Image *image = it->second; image != nullptr) { - Renderer::releaseSurfaceImpl(image->mSurfaceImpl); - delete image; - } - } - ctx.mImageCache.clear(); - } - + Widget *getValidRoot(Context &ctx) { if (ctx.mRoot != nullptr) { return ctx.mRoot; @@ -345,7 +288,7 @@ WidgetHandle Widgets::textButton(WidgetHandle parentId, const char *text, const return child->mHandle; } -WidgetHandle Widgets::imageButton(WidgetHandle parentId, const char *image, const Rect &rect, CallbackI *callback) { +WidgetHandle Widgets::imageButton(WidgetHandle parentId, const char *imageName, const Rect &rect, CallbackI *callback) { auto &ctx = TinyUi::getContext(); if (ctx.mBackendCtx == nullptr) { return WidgetHandle{WidgetHandle::InvalidId}; @@ -361,8 +304,8 @@ WidgetHandle Widgets::imageButton(WidgetHandle parentId, const char *image, cons callback->incRef(); } - if (image != nullptr) { - child->mImage = loadIntoImageCache(ctx, image); + if (imageName != nullptr) { + child->mImage = ctx.loadIntoImageCache(imageName); } return child->mHandle; @@ -396,7 +339,7 @@ WidgetHandle Widgets::imageBox(WidgetHandle parentId, const char* image, const R Widget *child = createWidget(ctx, parentId, rect, WidgetType::ImageBox); child->mFilledRect = filled; if (image != nullptr) { - child->mImage = loadIntoImageCache(ctx, image); + child->mImage = ctx.loadIntoImageCache(image); } return child->mHandle; @@ -776,7 +719,6 @@ void Widgets::clear() { Widget *current{ctx.mRoot}; recursiveClear(current); ctx.mRoot = nullptr; - releaseImageCache(ctx); } bool Widgets::clearItem(WidgetHandle id, bool recursive) { diff --git a/src/widgets.h b/src/widgets.h index 0aabec6..125c593 100644 --- a/src/widgets.h +++ b/src/widgets.h @@ -23,6 +23,14 @@ SOFTWARE. */ #pragma once +/** + * @file widgets.h + * @brief Widget definitions for the TinyUI library. + * + * This file contains all widget types, widget creation functions, and widget management + * utilities for the TinyUI library. + */ + #include "tinyui.h" namespace tinyui {