Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
11 changes: 9 additions & 2 deletions src/backends/sdl2_iodevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <SDL.h>

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;
Expand Down
15 changes: 15 additions & 0 deletions src/backends/sdl2_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <SDL.h>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
56 changes: 55 additions & 1 deletion src/tinyui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,18 @@
};

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 {
Expand All @@ -66,6 +72,10 @@

Context *gCtx = nullptr;

Context::~Context() {
clearImageCache();
}

Context *Context::create(const char *title, const Style &style) {
auto *ctx = new Context;
ctx->mLogger = log_message;
Expand Down Expand Up @@ -96,6 +106,10 @@
delete ctx;
}

Context *Context::getCurrent() {
return gCtx;
}

void Context::addImage(const char *name, Image *image) {
if (name == nullptr || image == nullptr) {
return;
Expand Down Expand Up @@ -123,6 +137,46 @@
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);
Comment thread
kimkulling marked this conversation as resolved.
if (data == nullptr) {
return nullptr;
}

image = new Image;
int32_t pitch = w * bytesPerPixel;
pitch = (pitch + 3) & ~3;
Comment thread
kimkulling marked this conversation as resolved.
image->mSurfaceImpl = Renderer::createSurfaceImpl(data, w, h, bytesPerPixel, pitch);
Comment thread
kimkulling marked this conversation as resolved.
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;

Check failure on line 174 in src/tinyui.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rewrite the code so that you no longer need this "delete".

See more on https://sonarcloud.io/project/issues?id=kimkulling_tiny_ui&issues=AaC10sxQvCLzrcXCzStD&open=AaC10sxQvCLzrcXCzStD&pullRequest=64
}
}
mImageCache.clear();
}

bool TinyUi::createContext(const char *title, const Style &style) {
if (gCtx != nullptr) {
return false;
Expand Down
37 changes: 30 additions & 7 deletions src/tinyui.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cstdint>
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -500,16 +511,16 @@ 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.
/// @param name The name of the image.
/// @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);

Expand All @@ -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 {
Expand All @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions src/tinyui_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
68 changes: 5 additions & 63 deletions src/widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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};
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions src/widgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading